tools/testing/selftests/vm/map_fixed_noreplace.c: add test for MAP_FIXED_NOREPLACE
[muen/linux.git] / tools / testing / selftests / vm / map_fixed_noreplace.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 /*
4  * Test that MAP_FIXED_NOREPLACE works.
5  *
6  * Copyright 2018, Jann Horn <jannh@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 }