Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 /*
0004  * Test that MAP_FIXED_NOREPLACE works.
0005  *
0006  * Copyright 2018, Jann Horn <jannh@google.com>
0007  * Copyright 2018, Michael Ellerman, IBM Corporation.
0008  */
0009 
0010 #include <sys/mman.h>
0011 #include <errno.h>
0012 #include <stdio.h>
0013 #include <stdlib.h>
0014 #include <unistd.h>
0015 
0016 #ifndef MAP_FIXED_NOREPLACE
0017 #define MAP_FIXED_NOREPLACE 0x100000
0018 #endif
0019 
0020 static void dump_maps(void)
0021 {
0022     char cmd[32];
0023 
0024     snprintf(cmd, sizeof(cmd), "cat /proc/%d/maps", getpid());
0025     system(cmd);
0026 }
0027 
0028 static unsigned long find_base_addr(unsigned long size)
0029 {
0030     void *addr;
0031     unsigned long flags;
0032 
0033     flags = MAP_PRIVATE | MAP_ANONYMOUS;
0034     addr = mmap(NULL, size, PROT_NONE, flags, -1, 0);
0035     if (addr == MAP_FAILED) {
0036         printf("Error: couldn't map the space we need for the test\n");
0037         return 0;
0038     }
0039 
0040     if (munmap(addr, size) != 0) {
0041         printf("Error: couldn't map the space we need for the test\n");
0042         return 0;
0043     }
0044     return (unsigned long)addr;
0045 }
0046 
0047 int main(void)
0048 {
0049     unsigned long base_addr;
0050     unsigned long flags, addr, size, page_size;
0051     char *p;
0052 
0053     page_size = sysconf(_SC_PAGE_SIZE);
0054 
0055     //let's find a base addr that is free before we start the tests
0056     size = 5 * page_size;
0057     base_addr = find_base_addr(size);
0058     if (!base_addr) {
0059         printf("Error: couldn't map the space we need for the test\n");
0060         return 1;
0061     }
0062 
0063     flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE;
0064 
0065     // Check we can map all the areas we need below
0066     errno = 0;
0067     addr = base_addr;
0068     size = 5 * page_size;
0069     p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
0070 
0071     printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
0072 
0073     if (p == MAP_FAILED) {
0074         dump_maps();
0075         printf("Error: couldn't map the space we need for the test\n");
0076         return 1;
0077     }
0078 
0079     errno = 0;
0080     if (munmap((void *)addr, 5 * page_size) != 0) {
0081         dump_maps();
0082         printf("Error: munmap failed!?\n");
0083         return 1;
0084     }
0085     printf("unmap() successful\n");
0086 
0087     errno = 0;
0088     addr = base_addr + page_size;
0089     size = 3 * page_size;
0090     p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
0091     printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
0092 
0093     if (p == MAP_FAILED) {
0094         dump_maps();
0095         printf("Error: first mmap() failed unexpectedly\n");
0096         return 1;
0097     }
0098 
0099     /*
0100      * Exact same mapping again:
0101      *   base |  free  | new
0102      *     +1 | mapped | new
0103      *     +2 | mapped | new
0104      *     +3 | mapped | new
0105      *     +4 |  free  | new
0106      */
0107     errno = 0;
0108     addr = base_addr;
0109     size = 5 * page_size;
0110     p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
0111     printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
0112 
0113     if (p != MAP_FAILED) {
0114         dump_maps();
0115         printf("Error:1: mmap() succeeded when it shouldn't have\n");
0116         return 1;
0117     }
0118 
0119     /*
0120      * Second mapping contained within first:
0121      *
0122      *   base |  free  |
0123      *     +1 | mapped |
0124      *     +2 | mapped | new
0125      *     +3 | mapped |
0126      *     +4 |  free  |
0127      */
0128     errno = 0;
0129     addr = base_addr + (2 * page_size);
0130     size = page_size;
0131     p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
0132     printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
0133 
0134     if (p != MAP_FAILED) {
0135         dump_maps();
0136         printf("Error:2: mmap() succeeded when it shouldn't have\n");
0137         return 1;
0138     }
0139 
0140     /*
0141      * Overlap end of existing mapping:
0142      *   base |  free  |
0143      *     +1 | mapped |
0144      *     +2 | mapped |
0145      *     +3 | mapped | new
0146      *     +4 |  free  | new
0147      */
0148     errno = 0;
0149     addr = base_addr + (3 * page_size);
0150     size = 2 * page_size;
0151     p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
0152     printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
0153 
0154     if (p != MAP_FAILED) {
0155         dump_maps();
0156         printf("Error:3: mmap() succeeded when it shouldn't have\n");
0157         return 1;
0158     }
0159 
0160     /*
0161      * Overlap start of existing mapping:
0162      *   base |  free  | new
0163      *     +1 | mapped | new
0164      *     +2 | mapped |
0165      *     +3 | mapped |
0166      *     +4 |  free  |
0167      */
0168     errno = 0;
0169     addr = base_addr;
0170     size = 2 * page_size;
0171     p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
0172     printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
0173 
0174     if (p != MAP_FAILED) {
0175         dump_maps();
0176         printf("Error:4: mmap() succeeded when it shouldn't have\n");
0177         return 1;
0178     }
0179 
0180     /*
0181      * Adjacent to start of existing mapping:
0182      *   base |  free  | new
0183      *     +1 | mapped |
0184      *     +2 | mapped |
0185      *     +3 | mapped |
0186      *     +4 |  free  |
0187      */
0188     errno = 0;
0189     addr = base_addr;
0190     size = page_size;
0191     p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
0192     printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
0193 
0194     if (p == MAP_FAILED) {
0195         dump_maps();
0196         printf("Error:5: mmap() failed when it shouldn't have\n");
0197         return 1;
0198     }
0199 
0200     /*
0201      * Adjacent to end of existing mapping:
0202      *   base |  free  |
0203      *     +1 | mapped |
0204      *     +2 | mapped |
0205      *     +3 | mapped |
0206      *     +4 |  free  |  new
0207      */
0208     errno = 0;
0209     addr = base_addr + (4 * page_size);
0210     size = page_size;
0211     p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
0212     printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
0213 
0214     if (p == MAP_FAILED) {
0215         dump_maps();
0216         printf("Error:6: mmap() failed when it shouldn't have\n");
0217         return 1;
0218     }
0219 
0220     addr = base_addr;
0221     size = 5 * page_size;
0222     if (munmap((void *)addr, size) != 0) {
0223         dump_maps();
0224         printf("Error: munmap failed!?\n");
0225         return 1;
0226     }
0227     printf("unmap() successful\n");
0228 
0229     printf("OK\n");
0230     return 0;
0231 }