aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Ellerman <mpe@ellerman.id.au>2018-10-26 18:10:48 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-10-26 19:38:15 -0400
commit91cbacc34512e37c9bb89125ca4b224ca6459245 (patch)
tree50cc12ba385ea0b15a2f73dcbba93d50183eee51
parent7eef5f97c1f94c7b72520b42d372037e97a81b95 (diff)
tools/testing/selftests/vm/map_fixed_noreplace.c: add test for MAP_FIXED_NOREPLACE
Add a test for MAP_FIXED_NOREPLACE, based on some code originally by Jann Horn. This would have caught the overlap bug reported by Daniel Micay. I originally suggested to Michal that we create MAP_FIXED_NOREPLACE, but instead of writing a selftest I spent my time bike-shedding whether it should be called MAP_FIXED_SAFE/NOCLOBBER/WEAK/NEW .. mea culpa. Link: http://lkml.kernel.org/r/20181013133929.28653-1-mpe@ellerman.id.au Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Reviewed-by: Kees Cook <keescook@chromium.org> Reviewed-by: Khalid Aziz <khalid.aziz@oracle.com> Acked-by: Michal Hocko <mhocko@suse.com> Cc: Jann Horn <jannh@google.com> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Florian Weimer <fweimer@redhat.com> Cc: John Hubbard <jhubbard@nvidia.com> Cc: Matthew Wilcox <willy@infradead.org> Cc: Abdul Haleem <abdhalee@linux.vnet.ibm.com> Cc: Joel Stanley <joel@jms.id.au> Cc: Jason Evans <jasone@google.com> Cc: David Goldblatt <davidtgoldblatt@gmail.com> Cc: Daniel Micay <danielmicay@gmail.com> Cc: Shuah Khan <shuah@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--tools/testing/selftests/vm/.gitignore1
-rw-r--r--tools/testing/selftests/vm/Makefile1
-rw-r--r--tools/testing/selftests/vm/map_fixed_noreplace.c206
3 files changed, 208 insertions, 0 deletions
diff --git a/tools/testing/selftests/vm/.gitignore b/tools/testing/selftests/vm/.gitignore
index af5ff83f6d7f..31b3c98b6d34 100644
--- a/tools/testing/selftests/vm/.gitignore
+++ b/tools/testing/selftests/vm/.gitignore
@@ -13,3 +13,4 @@ mlock-random-test
13virtual_address_range 13virtual_address_range
14gup_benchmark 14gup_benchmark
15va_128TBswitch 15va_128TBswitch
16map_fixed_noreplace
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
index e94b7b14bcb2..6e67e726e5a5 100644
--- a/tools/testing/selftests/vm/Makefile
+++ b/tools/testing/selftests/vm/Makefile
@@ -12,6 +12,7 @@ TEST_GEN_FILES += gup_benchmark
12TEST_GEN_FILES += hugepage-mmap 12TEST_GEN_FILES += hugepage-mmap
13TEST_GEN_FILES += hugepage-shm 13TEST_GEN_FILES += hugepage-shm
14TEST_GEN_FILES += map_hugetlb 14TEST_GEN_FILES += map_hugetlb
15TEST_GEN_FILES += map_fixed_noreplace
15TEST_GEN_FILES += map_populate 16TEST_GEN_FILES += map_populate
16TEST_GEN_FILES += mlock-random-test 17TEST_GEN_FILES += mlock-random-test
17TEST_GEN_FILES += mlock2-tests 18TEST_GEN_FILES += mlock2-tests
diff --git a/tools/testing/selftests/vm/map_fixed_noreplace.c b/tools/testing/selftests/vm/map_fixed_noreplace.c
new file mode 100644
index 000000000000..d91bde511268
--- /dev/null
+++ b/tools/testing/selftests/vm/map_fixed_noreplace.c
@@ -0,0 +1,206 @@
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
23static 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
31int 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}