Home | History | Annotate | Download | only in vm
      1 // SPDX-License-Identifier: GPL-2.0
      2 
      3 /*
      4  * Test that MAP_FIXED_NOREPLACE works.
      5  *
      6  * Copyright 2018, Jann Horn <jannh (at) google.com>
      7  * Copyright 2018, Michael Ellerman, IBM Corporation.
      8  */
      9 
     10 #include <sys/mman.h>
     11 #include <errno.h>
     12 #include <stdio.h>
     13 #include <stdlib.h>
     14 #include <unistd.h>
     15 
     16 #ifndef MAP_FIXED_NOREPLACE
     17 #define MAP_FIXED_NOREPLACE 0x100000
     18 #endif
     19 
     20 #define BASE_ADDRESS	(256ul * 1024 * 1024)
     21 
     22 
     23 static void dump_maps(void)
     24 {
     25 	char cmd[32];
     26 
     27 	snprintf(cmd, sizeof(cmd), "cat /proc/%d/maps", getpid());
     28 	system(cmd);
     29 }
     30 
     31 int main(void)
     32 {
     33 	unsigned long flags, addr, size, page_size;
     34 	char *p;
     35 
     36 	page_size = sysconf(_SC_PAGE_SIZE);
     37 
     38 	flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE;
     39 
     40 	// Check we can map all the areas we need below
     41 	errno = 0;
     42 	addr = BASE_ADDRESS;
     43 	size = 5 * page_size;
     44 	p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
     45 
     46 	printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
     47 
     48 	if (p == MAP_FAILED) {
     49 		dump_maps();
     50 		printf("Error: couldn't map the space we need for the test\n");
     51 		return 1;
     52 	}
     53 
     54 	errno = 0;
     55 	if (munmap((void *)addr, 5 * page_size) != 0) {
     56 		dump_maps();
     57 		printf("Error: munmap failed!?\n");
     58 		return 1;
     59 	}
     60 	printf("unmap() successful\n");
     61 
     62 	errno = 0;
     63 	addr = BASE_ADDRESS + page_size;
     64 	size = 3 * page_size;
     65 	p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
     66 	printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
     67 
     68 	if (p == MAP_FAILED) {
     69 		dump_maps();
     70 		printf("Error: first mmap() failed unexpectedly\n");
     71 		return 1;
     72 	}
     73 
     74 	/*
     75 	 * Exact same mapping again:
     76 	 *   base |  free  | new
     77 	 *     +1 | mapped | new
     78 	 *     +2 | mapped | new
     79 	 *     +3 | mapped | new
     80 	 *     +4 |  free  | new
     81 	 */
     82 	errno = 0;
     83 	addr = BASE_ADDRESS;
     84 	size = 5 * page_size;
     85 	p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
     86 	printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
     87 
     88 	if (p != MAP_FAILED) {
     89 		dump_maps();
     90 		printf("Error:1: mmap() succeeded when it shouldn't have\n");
     91 		return 1;
     92 	}
     93 
     94 	/*
     95 	 * Second mapping contained within first:
     96 	 *
     97 	 *   base |  free  |
     98 	 *     +1 | mapped |
     99 	 *     +2 | mapped | new
    100 	 *     +3 | mapped |
    101 	 *     +4 |  free  |
    102 	 */
    103 	errno = 0;
    104 	addr = BASE_ADDRESS + (2 * page_size);
    105 	size = page_size;
    106 	p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
    107 	printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
    108 
    109 	if (p != MAP_FAILED) {
    110 		dump_maps();
    111 		printf("Error:2: mmap() succeeded when it shouldn't have\n");
    112 		return 1;
    113 	}
    114 
    115 	/*
    116 	 * Overlap end of existing mapping:
    117 	 *   base |  free  |
    118 	 *     +1 | mapped |
    119 	 *     +2 | mapped |
    120 	 *     +3 | mapped | new
    121 	 *     +4 |  free  | new
    122 	 */
    123 	errno = 0;
    124 	addr = BASE_ADDRESS + (3 * page_size);
    125 	size = 2 * page_size;
    126 	p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
    127 	printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
    128 
    129 	if (p != MAP_FAILED) {
    130 		dump_maps();
    131 		printf("Error:3: mmap() succeeded when it shouldn't have\n");
    132 		return 1;
    133 	}
    134 
    135 	/*
    136 	 * Overlap start of existing mapping:
    137 	 *   base |  free  | new
    138 	 *     +1 | mapped | new
    139 	 *     +2 | mapped |
    140 	 *     +3 | mapped |
    141 	 *     +4 |  free  |
    142 	 */
    143 	errno = 0;
    144 	addr = BASE_ADDRESS;
    145 	size = 2 * page_size;
    146 	p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
    147 	printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
    148 
    149 	if (p != MAP_FAILED) {
    150 		dump_maps();
    151 		printf("Error:4: mmap() succeeded when it shouldn't have\n");
    152 		return 1;
    153 	}
    154 
    155 	/*
    156 	 * Adjacent to start of existing mapping:
    157 	 *   base |  free  | new
    158 	 *     +1 | mapped |
    159 	 *     +2 | mapped |
    160 	 *     +3 | mapped |
    161 	 *     +4 |  free  |
    162 	 */
    163 	errno = 0;
    164 	addr = BASE_ADDRESS;
    165 	size = page_size;
    166 	p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
    167 	printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
    168 
    169 	if (p == MAP_FAILED) {
    170 		dump_maps();
    171 		printf("Error:5: mmap() failed when it shouldn't have\n");
    172 		return 1;
    173 	}
    174 
    175 	/*
    176 	 * Adjacent to end of existing mapping:
    177 	 *   base |  free  |
    178 	 *     +1 | mapped |
    179 	 *     +2 | mapped |
    180 	 *     +3 | mapped |
    181 	 *     +4 |  free  |  new
    182 	 */
    183 	errno = 0;
    184 	addr = BASE_ADDRESS + (4 * page_size);
    185 	size = page_size;
    186 	p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
    187 	printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
    188 
    189 	if (p == MAP_FAILED) {
    190 		dump_maps();
    191 		printf("Error:6: mmap() failed when it shouldn't have\n");
    192 		return 1;
    193 	}
    194 
    195 	addr = BASE_ADDRESS;
    196 	size = 5 * page_size;
    197 	if (munmap((void *)addr, size) != 0) {
    198 		dump_maps();
    199 		printf("Error: munmap failed!?\n");
    200 		return 1;
    201 	}
    202 	printf("unmap() successful\n");
    203 
    204 	printf("OK\n");
    205 	return 0;
    206 }
    207