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 19static int PAGE; 20 21void 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 29void unmap_and_check ( void* start, size_t length ) 30{ 31 int r = munmap( start, length ); 32 assert(r == 0); 33} 34 35char* workingarea = NULL; 36char* 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 45char* 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 */ 75void 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 92char* dst = NULL; 93char* src = NULL; 94char* dst_impossible = NULL; 95 96 97char* 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 106int 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