1 #define _GNU_SOURCE 2 3 #include <stdio.h> 4 5 #include "tests/sys_mman.h" 6 #include <assert.h> 7 #include <stdlib.h> 8 #include <sys/types.h> 9 #include <unistd.h> 10 #include <errno.h> 11 #include <syscall.h> 12 13 14 #ifndef REMAP_FIXED 15 #define MREMAP_FIXED 2 16 #endif 17 18 19 static int PAGE; 20 21 void mapanon_fixed ( void* start, size_t length ) 22 { 23 void* r = mmap(start, length, PROT_NONE, 24 MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0,0); 25 assert(r != MAP_FAILED); 26 assert(r == start); 27 } 28 29 void unmap_and_check ( void* start, size_t length ) 30 { 31 int r = munmap( start, length ); 32 assert(r == 0); 33 } 34 35 char* workingarea = NULL; 36 char* try_dst = NULL; 37 38 // set up working area so expansion limit is 20*PAGE 39 // 40 // | 10 | 20 | 10 | 60 | 41 // | pre | src | FREE | post | 42 // 43 // A suitable attempted fixed dst is workingarea + 150*PAGE. 44 45 char* setup ( void* other_stuff, int other_len ) 46 { 47 if (!workingarea) { 48 workingarea = mmap(0, 200*PAGE, PROT_NONE, 49 MAP_ANONYMOUS|MAP_PRIVATE, 0,0); 50 assert(workingarea); 51 try_dst = workingarea + 150*PAGE; 52 unmap_and_check(workingarea, 200*PAGE); 53 } 54 55 if (other_stuff) { 56 unmap_and_check(other_stuff, other_len); 57 } 58 59 // get rid of the old working area 60 unmap_and_check( workingarea, 200*PAGE); 61 62 // pre block 63 mapanon_fixed( workingarea + 0*PAGE, 9*PAGE); 64 65 // the area 66 mapanon_fixed( workingarea + 10*PAGE, 20*PAGE ); 67 68 // upper half 69 mapanon_fixed( workingarea + 40*PAGE, 60*PAGE ); 70 71 return workingarea + 10*PAGE; 72 } 73 74 /* show the working area */ 75 void show ( void ) 76 { 77 int i,r __attribute__((unused)); 78 for (i = 0; i < 200; i++) { 79 r = mprotect( workingarea + i * PAGE, PAGE, PROT_NONE ); 80 // We used to print 'X' or '.' according to the mprotect result, but the 81 // results are too variable and the test was never reliable. So now we 82 // just always print '.'. At least this test gives mremap a thorough 83 // working out and so will detect egregious problems like crashes. 84 //printf("%c", r == 0 ? 'X' : '.'); 85 printf("."); 86 if (i == 49 || i == 99 || i == 149) printf("\n"); 87 } 88 printf("\n"); 89 } 90 91 92 char* dst = NULL; 93 char* src = NULL; 94 char* dst_impossible = NULL; 95 96 97 char* identify ( char* p ) 98 { 99 if (p == dst) return "dst"; 100 if (p == src) return "src"; 101 if (p == dst_impossible) return "dst_imp!"; 102 if (p == try_dst) return "dst_poss"; 103 return "other"; 104 } 105 106 int main ( void ) 107 { 108 int alocal, maymove, fixed, nsi, dstpossible; 109 int newsizes[6] = { 19, 20, 21, 29, 30, 31 }; 110 111 char* tidythis = NULL; 112 int tidylen = 0; 113 int firsttime = 1; 114 char buf[100]; 115 116 dst_impossible = (char*)(&alocal) + 500 * 1000 * 1000; 117 118 PAGE = sysconf(_SC_PAGESIZE); 119 120 for (maymove = 0; maymove <= 1 ; maymove++) { 121 for (fixed = 0; fixed <= 1; fixed++) { 122 printf("\n"); 123 for (nsi = 0; nsi < 6; nsi++) { 124 for (dstpossible = 0; dstpossible <= 1; dstpossible++) { 125 126 char* r; 127 int newsize = newsizes[nsi] * PAGE; 128 int flags = (maymove ? MREMAP_MAYMOVE : 0) | 129 (fixed ? MREMAP_FIXED : 0); 130 dst = dstpossible ? try_dst : dst_impossible; 131 src = setup( tidythis, tidylen ); 132 133 if (firsttime) { 134 printf("dst_possible = %p\n", try_dst ); 135 printf("dst_impossible = %p\n", dst_impossible ); 136 printf(" src = %p\n", src); 137 printf("\n"); 138 sprintf(buf, "cat /proc/%d/maps", getpid()); 139 if (0) system(buf); 140 firsttime = 0; 141 } 142 143 printf("maymv %d fixed %d newsz %2d dstpo %d dst %p -> ", 144 maymove, fixed, newsizes[nsi], dstpossible, dst ); 145 r = (char*) 146 syscall(__NR_mremap, src, 20*PAGE, newsize, flags, dst, 0 ); 147 // We used to print the address or error, but that was also unreliable. 148 //if (r == MAP_FAILED) 149 // printf("error %d\n", errno); 150 //else 151 // printf("%p (== %s)\n", r, identify(r)); 152 printf("\n"); 153 154 if (1) { 155 show(); 156 printf("\n"); 157 } 158 159 if (r != MAP_FAILED) { 160 if (r != src && r != try_dst && r != dst_impossible) { 161 tidythis = r; 162 tidylen = newsize; 163 } 164 } 165 166 } 167 } 168 } 169 } 170 return 0; 171 } 172