Merge 5.17-rc6 into char-misc-next
[linux-2.6-microblaze.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 static void dump_maps(void)
21 {
22         char cmd[32];
23
24         snprintf(cmd, sizeof(cmd), "cat /proc/%d/maps", getpid());
25         system(cmd);
26 }
27
28 static unsigned long find_base_addr(unsigned long size)
29 {
30         void *addr;
31         unsigned long flags;
32
33         flags = MAP_PRIVATE | MAP_ANONYMOUS;
34         addr = mmap(NULL, size, PROT_NONE, flags, -1, 0);
35         if (addr == MAP_FAILED) {
36                 printf("Error: couldn't map the space we need for the test\n");
37                 return 0;
38         }
39
40         if (munmap(addr, size) != 0) {
41                 printf("Error: couldn't map the space we need for the test\n");
42                 return 0;
43         }
44         return (unsigned long)addr;
45 }
46
47 int main(void)
48 {
49         unsigned long base_addr;
50         unsigned long flags, addr, size, page_size;
51         char *p;
52
53         page_size = sysconf(_SC_PAGE_SIZE);
54
55         //let's find a base addr that is free before we start the tests
56         size = 5 * page_size;
57         base_addr = find_base_addr(size);
58         if (!base_addr) {
59                 printf("Error: couldn't map the space we need for the test\n");
60                 return 1;
61         }
62
63         flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE;
64
65         // Check we can map all the areas we need below
66         errno = 0;
67         addr = base_addr;
68         size = 5 * page_size;
69         p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
70
71         printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
72
73         if (p == MAP_FAILED) {
74                 dump_maps();
75                 printf("Error: couldn't map the space we need for the test\n");
76                 return 1;
77         }
78
79         errno = 0;
80         if (munmap((void *)addr, 5 * page_size) != 0) {
81                 dump_maps();
82                 printf("Error: munmap failed!?\n");
83                 return 1;
84         }
85         printf("unmap() successful\n");
86
87         errno = 0;
88         addr = base_addr + page_size;
89         size = 3 * page_size;
90         p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
91         printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
92
93         if (p == MAP_FAILED) {
94                 dump_maps();
95                 printf("Error: first mmap() failed unexpectedly\n");
96                 return 1;
97         }
98
99         /*
100          * Exact same mapping again:
101          *   base |  free  | new
102          *     +1 | mapped | new
103          *     +2 | mapped | new
104          *     +3 | mapped | new
105          *     +4 |  free  | new
106          */
107         errno = 0;
108         addr = base_addr;
109         size = 5 * page_size;
110         p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
111         printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
112
113         if (p != MAP_FAILED) {
114                 dump_maps();
115                 printf("Error:1: mmap() succeeded when it shouldn't have\n");
116                 return 1;
117         }
118
119         /*
120          * Second mapping contained within first:
121          *
122          *   base |  free  |
123          *     +1 | mapped |
124          *     +2 | mapped | new
125          *     +3 | mapped |
126          *     +4 |  free  |
127          */
128         errno = 0;
129         addr = base_addr + (2 * page_size);
130         size = page_size;
131         p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
132         printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
133
134         if (p != MAP_FAILED) {
135                 dump_maps();
136                 printf("Error:2: mmap() succeeded when it shouldn't have\n");
137                 return 1;
138         }
139
140         /*
141          * Overlap end of existing mapping:
142          *   base |  free  |
143          *     +1 | mapped |
144          *     +2 | mapped |
145          *     +3 | mapped | new
146          *     +4 |  free  | new
147          */
148         errno = 0;
149         addr = base_addr + (3 * page_size);
150         size = 2 * page_size;
151         p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
152         printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
153
154         if (p != MAP_FAILED) {
155                 dump_maps();
156                 printf("Error:3: mmap() succeeded when it shouldn't have\n");
157                 return 1;
158         }
159
160         /*
161          * Overlap start of existing mapping:
162          *   base |  free  | new
163          *     +1 | mapped | new
164          *     +2 | mapped |
165          *     +3 | mapped |
166          *     +4 |  free  |
167          */
168         errno = 0;
169         addr = base_addr;
170         size = 2 * page_size;
171         p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
172         printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
173
174         if (p != MAP_FAILED) {
175                 dump_maps();
176                 printf("Error:4: mmap() succeeded when it shouldn't have\n");
177                 return 1;
178         }
179
180         /*
181          * Adjacent to start of existing mapping:
182          *   base |  free  | new
183          *     +1 | mapped |
184          *     +2 | mapped |
185          *     +3 | mapped |
186          *     +4 |  free  |
187          */
188         errno = 0;
189         addr = base_addr;
190         size = page_size;
191         p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
192         printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
193
194         if (p == MAP_FAILED) {
195                 dump_maps();
196                 printf("Error:5: mmap() failed when it shouldn't have\n");
197                 return 1;
198         }
199
200         /*
201          * Adjacent to end of existing mapping:
202          *   base |  free  |
203          *     +1 | mapped |
204          *     +2 | mapped |
205          *     +3 | mapped |
206          *     +4 |  free  |  new
207          */
208         errno = 0;
209         addr = base_addr + (4 * page_size);
210         size = page_size;
211         p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
212         printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
213
214         if (p == MAP_FAILED) {
215                 dump_maps();
216                 printf("Error:6: mmap() failed when it shouldn't have\n");
217                 return 1;
218         }
219
220         addr = base_addr;
221         size = 5 * page_size;
222         if (munmap((void *)addr, size) != 0) {
223                 dump_maps();
224                 printf("Error: munmap failed!?\n");
225                 return 1;
226         }
227         printf("unmap() successful\n");
228
229         printf("OK\n");
230         return 0;
231 }