#define _GNU_SOURCE #include #include #include #include #include #include #include #include #ifndef PAGE_SIZE #define PAGE_SIZE 4096 #endif static void my_segv(int sig) { printf ("Test FAILED\n"); _exit (EXIT_FAILURE); } int main(void) { const char *file = "mrtst2.c"; char *addr, *addr2, *addr3; int fd; fd = open (file, O_RDONLY); if (fd == -1) return EXIT_FAILURE; addr = mmap (NULL, PAGE_SIZE * 2, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); if (addr == MAP_FAILED) { perror("mmap()"); return EXIT_FAILURE; } addr2 = mmap (NULL, PAGE_SIZE * 2, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (addr2 == MAP_FAILED) { perror("mmap()"); return EXIT_FAILURE; } /* split VMA to fail mremap() */ mprotect (addr, PAGE_SIZE, PROT_READ | PROT_WRITE); /* VMAs won't be merged, bug */ mprotect (addr, PAGE_SIZE, PROT_READ); /* make sure dest is here and writable */ addr2[0] = 3; /* expose the bug */ addr3 = mremap (addr, PAGE_SIZE * 2, PAGE_SIZE * 2, MREMAP_MAYMOVE | MREMAP_FIXED | MREMAP_DONTUNMAP, addr2); if (addr3 == addr2) { printf ("Even VMAs merged? Excellent!\n"); return 0; } assert (addr3 == MAP_FAILED); signal (SIGSEGV, my_segv); /* see if dest address unmapped */ addr2[0] = 5; assert (addr2[0] == 5); printf ("Test PASSED\n"); return 0; }