| #define _GNU_SOURCE | |
| #include <sys/mman.h> | |
| #include <errno.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| #include <assert.h> | |
| #ifndef MREMAP_DONTUNMAP | |
| #define MREMAP_DONTUNMAP 4 | |
| #endif | |
| int main(void) | |
| { | |
| unsigned long page_size = getpagesize(); | |
| unsigned long num_pages = 5; | |
| void *mapping1 = | |
| mmap((void *)0x20000000, num_pages * page_size, | |
| PROT_WRITE | PROT_READ, | |
| MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE, -1, 0); | |
| assert(mapping1 != MAP_FAILED); | |
| /* | |
| * We're going to end up adding VM_ACCOUNT to this unrelated mapping causing | |
| * us to incorrectly reduce the vm commit by this number of pages when | |
| * unmapped, this mapping will exist just beyond the first mapping. | |
| **/ | |
| unsigned long unrelated_mapping_pages = 1024; | |
| void *unrelated_mapping = mmap((char *)mapping1 + num_pages * page_size, | |
| unrelated_mapping_pages * page_size, | |
| PROT_NONE, | |
| MAP_PRIVATE | MAP_ANONYMOUS | | |
| MAP_FIXED_NOREPLACE, -1, 0); | |
| assert(unrelated_mapping != MAP_FAILED); | |
| /* remap the 4th page onto the 2nd page */ | |
| void *mapping_remaped = | |
| mremap((char *)mapping1 + (num_pages - 2) * page_size, page_size, | |
| page_size, MREMAP_DONTUNMAP | MREMAP_FIXED | MREMAP_MAYMOVE, | |
| (char *)mapping1 + 1 * page_size); | |
| /* At this point the unrelated mapping just had VM_ACCOUNT added to it */ | |
| munmap(unrelated_mapping, unrelated_mapping_pages * page_size); | |
| /* | |
| * And we just incorrectly subtracted from the commitment the number of pages | |
| * in the unrelated mapping | |
| **/ | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment