1 // SPDX-License-Identifier: GPL-2.0 2 3 /* 4 * Test that MAP_FIXED_NOREPLACE works. 5 * 6 * Copyright 2018, Jann Horn <jannh (at) google.com> 7 * Copyright 2018, Michael Ellerman, IBM Corporation. 8 */ 9 10 #include <sys/mman.h> 11 #include <errno.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <unistd.h> 15 16 #ifndef MAP_FIXED_NOREPLACE 17 #define MAP_FIXED_NOREPLACE 0x100000 18 #endif 19 20 #define BASE_ADDRESS (256ul * 1024 * 1024) 21 22 23 static void dump_maps(void) 24 { 25 char cmd[32]; 26 27 snprintf(cmd, sizeof(cmd), "cat /proc/%d/maps", getpid()); 28 system(cmd); 29 } 30 31 int main(void) 32 { 33 unsigned long flags, addr, size, page_size; 34 char *p; 35 36 page_size = sysconf(_SC_PAGE_SIZE); 37 38 flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE; 39 40 // Check we can map all the areas we need below 41 errno = 0; 42 addr = BASE_ADDRESS; 43 size = 5 * page_size; 44 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0); 45 46 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p); 47 48 if (p == MAP_FAILED) { 49 dump_maps(); 50 printf("Error: couldn't map the space we need for the test\n"); 51 return 1; 52 } 53 54 errno = 0; 55 if (munmap((void *)addr, 5 * page_size) != 0) { 56 dump_maps(); 57 printf("Error: munmap failed!?\n"); 58 return 1; 59 } 60 printf("unmap() successful\n"); 61 62 errno = 0; 63 addr = BASE_ADDRESS + page_size; 64 size = 3 * page_size; 65 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0); 66 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p); 67 68 if (p == MAP_FAILED) { 69 dump_maps(); 70 printf("Error: first mmap() failed unexpectedly\n"); 71 return 1; 72 } 73 74 /* 75 * Exact same mapping again: 76 * base | free | new 77 * +1 | mapped | new 78 * +2 | mapped | new 79 * +3 | mapped | new 80 * +4 | free | new 81 */ 82 errno = 0; 83 addr = BASE_ADDRESS; 84 size = 5 * page_size; 85 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0); 86 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p); 87 88 if (p != MAP_FAILED) { 89 dump_maps(); 90 printf("Error:1: mmap() succeeded when it shouldn't have\n"); 91 return 1; 92 } 93 94 /* 95 * Second mapping contained within first: 96 * 97 * base | free | 98 * +1 | mapped | 99 * +2 | mapped | new 100 * +3 | mapped | 101 * +4 | free | 102 */ 103 errno = 0; 104 addr = BASE_ADDRESS + (2 * page_size); 105 size = page_size; 106 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0); 107 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p); 108 109 if (p != MAP_FAILED) { 110 dump_maps(); 111 printf("Error:2: mmap() succeeded when it shouldn't have\n"); 112 return 1; 113 } 114 115 /* 116 * Overlap end of existing mapping: 117 * base | free | 118 * +1 | mapped | 119 * +2 | mapped | 120 * +3 | mapped | new 121 * +4 | free | new 122 */ 123 errno = 0; 124 addr = BASE_ADDRESS + (3 * page_size); 125 size = 2 * page_size; 126 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0); 127 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p); 128 129 if (p != MAP_FAILED) { 130 dump_maps(); 131 printf("Error:3: mmap() succeeded when it shouldn't have\n"); 132 return 1; 133 } 134 135 /* 136 * Overlap start of existing mapping: 137 * base | free | new 138 * +1 | mapped | new 139 * +2 | mapped | 140 * +3 | mapped | 141 * +4 | free | 142 */ 143 errno = 0; 144 addr = BASE_ADDRESS; 145 size = 2 * page_size; 146 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0); 147 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p); 148 149 if (p != MAP_FAILED) { 150 dump_maps(); 151 printf("Error:4: mmap() succeeded when it shouldn't have\n"); 152 return 1; 153 } 154 155 /* 156 * Adjacent to start of existing mapping: 157 * base | free | new 158 * +1 | mapped | 159 * +2 | mapped | 160 * +3 | mapped | 161 * +4 | free | 162 */ 163 errno = 0; 164 addr = BASE_ADDRESS; 165 size = page_size; 166 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0); 167 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p); 168 169 if (p == MAP_FAILED) { 170 dump_maps(); 171 printf("Error:5: mmap() failed when it shouldn't have\n"); 172 return 1; 173 } 174 175 /* 176 * Adjacent to end of existing mapping: 177 * base | free | 178 * +1 | mapped | 179 * +2 | mapped | 180 * +3 | mapped | 181 * +4 | free | new 182 */ 183 errno = 0; 184 addr = BASE_ADDRESS + (4 * page_size); 185 size = page_size; 186 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0); 187 printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p); 188 189 if (p == MAP_FAILED) { 190 dump_maps(); 191 printf("Error:6: mmap() failed when it shouldn't have\n"); 192 return 1; 193 } 194 195 addr = BASE_ADDRESS; 196 size = 5 * page_size; 197 if (munmap((void *)addr, size) != 0) { 198 dump_maps(); 199 printf("Error: munmap failed!?\n"); 200 return 1; 201 } 202 printf("unmap() successful\n"); 203 204 printf("OK\n"); 205 return 0; 206 } 207