t_mmap.c revision 1.13 1 1.13 christos /* $NetBSD: t_mmap.c,v 1.13 2017/05/23 13:04:29 christos Exp $ */
2 1.1 jruoho
3 1.1 jruoho /*-
4 1.1 jruoho * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 1.1 jruoho * All rights reserved.
6 1.1 jruoho *
7 1.1 jruoho * This code is derived from software contributed to The NetBSD Foundation
8 1.1 jruoho * by Jukka Ruohonen.
9 1.1 jruoho *
10 1.1 jruoho * Redistribution and use in source and binary forms, with or without
11 1.1 jruoho * modification, are permitted provided that the following conditions
12 1.1 jruoho * are met:
13 1.1 jruoho * 1. Redistributions of source code must retain the above copyright
14 1.1 jruoho * notice, this list of conditions and the following disclaimer.
15 1.1 jruoho * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 jruoho * notice, this list of conditions and the following disclaimer in the
17 1.1 jruoho * documentation and/or other materials provided with the distribution.
18 1.1 jruoho *
19 1.1 jruoho * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 jruoho * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 jruoho * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 jruoho * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 jruoho * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 jruoho * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 jruoho * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 jruoho * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 jruoho * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 jruoho * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 jruoho * POSSIBILITY OF SUCH DAMAGE.
30 1.1 jruoho */
31 1.2 jruoho
32 1.2 jruoho /*-
33 1.2 jruoho * Copyright (c)2004 YAMAMOTO Takashi,
34 1.2 jruoho * All rights reserved.
35 1.2 jruoho *
36 1.2 jruoho * Redistribution and use in source and binary forms, with or without
37 1.2 jruoho * modification, are permitted provided that the following conditions
38 1.2 jruoho * are met:
39 1.2 jruoho * 1. Redistributions of source code must retain the above copyright
40 1.2 jruoho * notice, this list of conditions and the following disclaimer.
41 1.2 jruoho * 2. Redistributions in binary form must reproduce the above copyright
42 1.2 jruoho * notice, this list of conditions and the following disclaimer in the
43 1.2 jruoho * documentation and/or other materials provided with the distribution.
44 1.2 jruoho *
45 1.2 jruoho * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
46 1.2 jruoho * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 1.2 jruoho * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 1.2 jruoho * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
49 1.2 jruoho * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 1.2 jruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 1.2 jruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 1.2 jruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 1.2 jruoho * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 1.2 jruoho * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 1.2 jruoho * SUCH DAMAGE.
56 1.2 jruoho */
57 1.1 jruoho #include <sys/cdefs.h>
58 1.13 christos __RCSID("$NetBSD: t_mmap.c,v 1.13 2017/05/23 13:04:29 christos Exp $");
59 1.1 jruoho
60 1.1 jruoho #include <sys/param.h>
61 1.12 christos #include <sys/disklabel.h>
62 1.1 jruoho #include <sys/mman.h>
63 1.10 christos #include <sys/stat.h>
64 1.2 jruoho #include <sys/socket.h>
65 1.1 jruoho #include <sys/sysctl.h>
66 1.1 jruoho #include <sys/wait.h>
67 1.1 jruoho
68 1.2 jruoho #include <atf-c.h>
69 1.1 jruoho #include <errno.h>
70 1.1 jruoho #include <fcntl.h>
71 1.1 jruoho #include <signal.h>
72 1.3 jruoho #include <stdio.h>
73 1.1 jruoho #include <stdlib.h>
74 1.1 jruoho #include <string.h>
75 1.1 jruoho #include <unistd.h>
76 1.5 martin #include <paths.h>
77 1.1 jruoho
78 1.1 jruoho static long page = 0;
79 1.1 jruoho static char path[] = "mmap";
80 1.1 jruoho static void map_check(void *, int);
81 1.1 jruoho static void map_sighandler(int);
82 1.2 jruoho static void testloan(void *, void *, char, int);
83 1.2 jruoho
84 1.2 jruoho #define BUFSIZE (32 * 1024) /* enough size to trigger sosend_loan */
85 1.1 jruoho
86 1.1 jruoho static void
87 1.1 jruoho map_check(void *map, int flag)
88 1.1 jruoho {
89 1.1 jruoho
90 1.1 jruoho if (flag != 0) {
91 1.1 jruoho ATF_REQUIRE(map == MAP_FAILED);
92 1.1 jruoho return;
93 1.1 jruoho }
94 1.1 jruoho
95 1.1 jruoho ATF_REQUIRE(map != MAP_FAILED);
96 1.1 jruoho ATF_REQUIRE(munmap(map, page) == 0);
97 1.1 jruoho }
98 1.1 jruoho
99 1.2 jruoho void
100 1.2 jruoho testloan(void *vp, void *vp2, char pat, int docheck)
101 1.2 jruoho {
102 1.2 jruoho char buf[BUFSIZE];
103 1.2 jruoho char backup[BUFSIZE];
104 1.2 jruoho ssize_t nwritten;
105 1.2 jruoho ssize_t nread;
106 1.2 jruoho int fds[2];
107 1.2 jruoho int val;
108 1.2 jruoho
109 1.2 jruoho val = BUFSIZE;
110 1.2 jruoho
111 1.2 jruoho if (docheck != 0)
112 1.2 jruoho (void)memcpy(backup, vp, BUFSIZE);
113 1.2 jruoho
114 1.2 jruoho if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, fds) != 0)
115 1.2 jruoho atf_tc_fail("socketpair() failed");
116 1.2 jruoho
117 1.2 jruoho val = BUFSIZE;
118 1.2 jruoho
119 1.2 jruoho if (setsockopt(fds[1], SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)) != 0)
120 1.2 jruoho atf_tc_fail("setsockopt() failed, SO_RCVBUF");
121 1.2 jruoho
122 1.2 jruoho val = BUFSIZE;
123 1.2 jruoho
124 1.2 jruoho if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) != 0)
125 1.2 jruoho atf_tc_fail("setsockopt() failed, SO_SNDBUF");
126 1.2 jruoho
127 1.2 jruoho if (fcntl(fds[0], F_SETFL, O_NONBLOCK) != 0)
128 1.2 jruoho atf_tc_fail("fcntl() failed");
129 1.2 jruoho
130 1.2 jruoho nwritten = write(fds[0], (char *)vp + page, BUFSIZE - page);
131 1.2 jruoho
132 1.2 jruoho if (nwritten == -1)
133 1.2 jruoho atf_tc_fail("write() failed");
134 1.2 jruoho
135 1.2 jruoho /* Break loan. */
136 1.2 jruoho (void)memset(vp2, pat, BUFSIZE);
137 1.2 jruoho
138 1.2 jruoho nread = read(fds[1], buf + page, BUFSIZE - page);
139 1.2 jruoho
140 1.2 jruoho if (nread == -1)
141 1.2 jruoho atf_tc_fail("read() failed");
142 1.2 jruoho
143 1.2 jruoho if (nread != nwritten)
144 1.2 jruoho atf_tc_fail("too short read");
145 1.2 jruoho
146 1.2 jruoho if (docheck != 0 && memcmp(backup, buf + page, nread) != 0)
147 1.2 jruoho atf_tc_fail("data mismatch");
148 1.2 jruoho
149 1.2 jruoho ATF_REQUIRE(close(fds[0]) == 0);
150 1.2 jruoho ATF_REQUIRE(close(fds[1]) == 0);
151 1.2 jruoho }
152 1.2 jruoho
153 1.1 jruoho static void
154 1.1 jruoho map_sighandler(int signo)
155 1.1 jruoho {
156 1.1 jruoho _exit(signo);
157 1.1 jruoho }
158 1.1 jruoho
159 1.3 jruoho ATF_TC(mmap_block);
160 1.3 jruoho ATF_TC_HEAD(mmap_block, tc)
161 1.3 jruoho {
162 1.3 jruoho atf_tc_set_md_var(tc, "descr", "Test mmap(2) with a block device");
163 1.5 martin atf_tc_set_md_var(tc, "require.user", "root");
164 1.3 jruoho }
165 1.3 jruoho
166 1.3 jruoho ATF_TC_BODY(mmap_block, tc)
167 1.3 jruoho {
168 1.5 martin static const int mib[] = { CTL_HW, HW_DISKNAMES };
169 1.5 martin static const unsigned int miblen = __arraycount(mib);
170 1.5 martin char *map, *dk, *drives, dev[PATH_MAX];
171 1.5 martin size_t len;
172 1.5 martin int fd = -1;
173 1.3 jruoho
174 1.7 bouyer atf_tc_skip("The test case causes a panic (PR kern/38889, kern/46592)");
175 1.3 jruoho
176 1.5 martin ATF_REQUIRE(sysctl(mib, miblen, NULL, &len, NULL, 0) == 0);
177 1.5 martin drives = malloc(len);
178 1.5 martin ATF_REQUIRE(drives != NULL);
179 1.5 martin ATF_REQUIRE(sysctl(mib, miblen, drives, &len, NULL, 0) == 0);
180 1.5 martin for (dk = strtok(drives, " "); dk != NULL; dk = strtok(NULL, " ")) {
181 1.13 christos if (strncmp(dk, "dk", 2) == 0)
182 1.13 christos snprintf(dev, sizeof(dev), _PATH_DEV "%s", dk);
183 1.13 christos else
184 1.13 christos snprintf(dev, sizeof(dev), _PATH_DEV "%s%c", dk,
185 1.13 christos 'a' + RAW_PART);
186 1.5 martin fprintf(stderr, "trying: %s\n", dev);
187 1.3 jruoho
188 1.5 martin if ((fd = open(dev, O_RDONLY)) >= 0) {
189 1.5 martin (void)fprintf(stderr, "using %s\n", dev);
190 1.3 jruoho break;
191 1.13 christos } else
192 1.13 christos (void)fprintf(stderr, "%s: %s\n", dev, strerror(errno));
193 1.3 jruoho }
194 1.5 martin free(drives);
195 1.3 jruoho
196 1.5 martin if (fd < 0)
197 1.4 jruoho atf_tc_skip("failed to find suitable block device");
198 1.3 jruoho
199 1.3 jruoho map = mmap(NULL, 4096, PROT_READ, MAP_FILE, fd, 0);
200 1.13 christos ATF_REQUIRE_MSG(map != MAP_FAILED, "mmap: %s", strerror(errno));
201 1.3 jruoho
202 1.3 jruoho (void)fprintf(stderr, "first byte %x\n", *map);
203 1.3 jruoho ATF_REQUIRE(close(fd) == 0);
204 1.3 jruoho (void)fprintf(stderr, "first byte %x\n", *map);
205 1.3 jruoho
206 1.3 jruoho ATF_REQUIRE(munmap(map, 4096) == 0);
207 1.3 jruoho }
208 1.3 jruoho
209 1.1 jruoho ATF_TC(mmap_err);
210 1.1 jruoho ATF_TC_HEAD(mmap_err, tc)
211 1.1 jruoho {
212 1.1 jruoho atf_tc_set_md_var(tc, "descr", "Test error conditions of mmap(2)");
213 1.1 jruoho }
214 1.1 jruoho
215 1.1 jruoho ATF_TC_BODY(mmap_err, tc)
216 1.1 jruoho {
217 1.1 jruoho size_t addr = SIZE_MAX;
218 1.1 jruoho void *map;
219 1.1 jruoho
220 1.1 jruoho errno = 0;
221 1.1 jruoho map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, -1, 0);
222 1.1 jruoho
223 1.1 jruoho ATF_REQUIRE(map == MAP_FAILED);
224 1.1 jruoho ATF_REQUIRE(errno == EBADF);
225 1.1 jruoho
226 1.1 jruoho errno = 0;
227 1.1 jruoho map = mmap(&addr, page, PROT_READ, MAP_FIXED|MAP_PRIVATE, -1, 0);
228 1.1 jruoho
229 1.1 jruoho ATF_REQUIRE(map == MAP_FAILED);
230 1.1 jruoho ATF_REQUIRE(errno == EINVAL);
231 1.1 jruoho
232 1.1 jruoho errno = 0;
233 1.1 jruoho map = mmap(NULL, page, PROT_READ, MAP_ANON|MAP_PRIVATE, INT_MAX, 0);
234 1.1 jruoho
235 1.1 jruoho ATF_REQUIRE(map == MAP_FAILED);
236 1.1 jruoho ATF_REQUIRE(errno == EINVAL);
237 1.1 jruoho }
238 1.1 jruoho
239 1.2 jruoho ATF_TC_WITH_CLEANUP(mmap_loan);
240 1.2 jruoho ATF_TC_HEAD(mmap_loan, tc)
241 1.2 jruoho {
242 1.2 jruoho atf_tc_set_md_var(tc, "descr", "Test uvm page loanout with mmap(2)");
243 1.2 jruoho }
244 1.2 jruoho
245 1.2 jruoho ATF_TC_BODY(mmap_loan, tc)
246 1.2 jruoho {
247 1.2 jruoho char buf[BUFSIZE];
248 1.2 jruoho char *vp, *vp2;
249 1.2 jruoho int fd;
250 1.2 jruoho
251 1.2 jruoho fd = open(path, O_RDWR | O_CREAT, 0600);
252 1.2 jruoho ATF_REQUIRE(fd >= 0);
253 1.2 jruoho
254 1.2 jruoho (void)memset(buf, 'x', sizeof(buf));
255 1.2 jruoho (void)write(fd, buf, sizeof(buf));
256 1.2 jruoho
257 1.2 jruoho vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
258 1.2 jruoho MAP_FILE | MAP_PRIVATE, fd, 0);
259 1.2 jruoho
260 1.2 jruoho ATF_REQUIRE(vp != MAP_FAILED);
261 1.2 jruoho
262 1.2 jruoho vp2 = vp;
263 1.2 jruoho
264 1.2 jruoho testloan(vp, vp2, 'A', 0);
265 1.2 jruoho testloan(vp, vp2, 'B', 1);
266 1.2 jruoho
267 1.2 jruoho ATF_REQUIRE(munmap(vp, BUFSIZE) == 0);
268 1.2 jruoho
269 1.2 jruoho vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
270 1.2 jruoho MAP_FILE | MAP_SHARED, fd, 0);
271 1.2 jruoho
272 1.2 jruoho vp2 = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
273 1.2 jruoho MAP_FILE | MAP_SHARED, fd, 0);
274 1.2 jruoho
275 1.2 jruoho ATF_REQUIRE(vp != MAP_FAILED);
276 1.2 jruoho ATF_REQUIRE(vp2 != MAP_FAILED);
277 1.2 jruoho
278 1.2 jruoho testloan(vp, vp2, 'E', 1);
279 1.2 jruoho
280 1.2 jruoho ATF_REQUIRE(munmap(vp, BUFSIZE) == 0);
281 1.2 jruoho ATF_REQUIRE(munmap(vp2, BUFSIZE) == 0);
282 1.2 jruoho }
283 1.2 jruoho
284 1.2 jruoho ATF_TC_CLEANUP(mmap_loan, tc)
285 1.2 jruoho {
286 1.2 jruoho (void)unlink(path);
287 1.2 jruoho }
288 1.2 jruoho
289 1.1 jruoho ATF_TC_WITH_CLEANUP(mmap_prot_1);
290 1.1 jruoho ATF_TC_HEAD(mmap_prot_1, tc)
291 1.1 jruoho {
292 1.1 jruoho atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #1");
293 1.1 jruoho }
294 1.1 jruoho
295 1.1 jruoho ATF_TC_BODY(mmap_prot_1, tc)
296 1.1 jruoho {
297 1.1 jruoho void *map;
298 1.1 jruoho int fd;
299 1.1 jruoho
300 1.1 jruoho /*
301 1.1 jruoho * Open a file write-only and try to
302 1.1 jruoho * map it read-only. This should fail.
303 1.1 jruoho */
304 1.1 jruoho fd = open(path, O_WRONLY | O_CREAT, 0700);
305 1.1 jruoho
306 1.1 jruoho if (fd < 0)
307 1.1 jruoho return;
308 1.1 jruoho
309 1.1 jruoho ATF_REQUIRE(write(fd, "XXX", 3) == 3);
310 1.1 jruoho
311 1.1 jruoho map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0);
312 1.1 jruoho map_check(map, 1);
313 1.1 jruoho
314 1.1 jruoho map = mmap(NULL, 3, PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0);
315 1.1 jruoho map_check(map, 0);
316 1.1 jruoho
317 1.1 jruoho ATF_REQUIRE(close(fd) == 0);
318 1.1 jruoho }
319 1.1 jruoho
320 1.1 jruoho ATF_TC_CLEANUP(mmap_prot_1, tc)
321 1.1 jruoho {
322 1.1 jruoho (void)unlink(path);
323 1.1 jruoho }
324 1.1 jruoho
325 1.1 jruoho ATF_TC(mmap_prot_2);
326 1.1 jruoho ATF_TC_HEAD(mmap_prot_2, tc)
327 1.1 jruoho {
328 1.1 jruoho atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #2");
329 1.1 jruoho }
330 1.1 jruoho
331 1.1 jruoho ATF_TC_BODY(mmap_prot_2, tc)
332 1.1 jruoho {
333 1.1 jruoho char buf[2];
334 1.1 jruoho void *map;
335 1.1 jruoho pid_t pid;
336 1.1 jruoho int sta;
337 1.1 jruoho
338 1.1 jruoho /*
339 1.1 jruoho * Make a PROT_NONE mapping and try to access it.
340 1.1 jruoho * If we catch a SIGSEGV, all works as expected.
341 1.1 jruoho */
342 1.1 jruoho map = mmap(NULL, page, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
343 1.1 jruoho ATF_REQUIRE(map != MAP_FAILED);
344 1.1 jruoho
345 1.1 jruoho pid = fork();
346 1.1 jruoho ATF_REQUIRE(pid >= 0);
347 1.1 jruoho
348 1.1 jruoho if (pid == 0) {
349 1.1 jruoho ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
350 1.1 jruoho ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0);
351 1.1 jruoho }
352 1.1 jruoho
353 1.1 jruoho (void)wait(&sta);
354 1.1 jruoho
355 1.1 jruoho ATF_REQUIRE(WIFEXITED(sta) != 0);
356 1.1 jruoho ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
357 1.1 jruoho ATF_REQUIRE(munmap(map, page) == 0);
358 1.1 jruoho }
359 1.1 jruoho
360 1.1 jruoho ATF_TC_WITH_CLEANUP(mmap_prot_3);
361 1.1 jruoho ATF_TC_HEAD(mmap_prot_3, tc)
362 1.1 jruoho {
363 1.1 jruoho atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #3");
364 1.1 jruoho }
365 1.1 jruoho
366 1.1 jruoho ATF_TC_BODY(mmap_prot_3, tc)
367 1.1 jruoho {
368 1.1 jruoho char buf[2];
369 1.1 jruoho int fd, sta;
370 1.1 jruoho void *map;
371 1.1 jruoho pid_t pid;
372 1.1 jruoho
373 1.1 jruoho /*
374 1.1 jruoho * Open a file, change the permissions
375 1.1 jruoho * to read-only, and try to map it as
376 1.1 jruoho * PROT_NONE. This should succeed, but
377 1.1 jruoho * the access should generate SIGSEGV.
378 1.1 jruoho */
379 1.1 jruoho fd = open(path, O_RDWR | O_CREAT, 0700);
380 1.1 jruoho
381 1.1 jruoho if (fd < 0)
382 1.1 jruoho return;
383 1.1 jruoho
384 1.1 jruoho ATF_REQUIRE(write(fd, "XXX", 3) == 3);
385 1.1 jruoho ATF_REQUIRE(close(fd) == 0);
386 1.1 jruoho ATF_REQUIRE(chmod(path, 0444) == 0);
387 1.1 jruoho
388 1.1 jruoho fd = open(path, O_RDONLY);
389 1.1 jruoho ATF_REQUIRE(fd != -1);
390 1.1 jruoho
391 1.1 jruoho map = mmap(NULL, 3, PROT_NONE, MAP_FILE | MAP_SHARED, fd, 0);
392 1.1 jruoho ATF_REQUIRE(map != MAP_FAILED);
393 1.1 jruoho
394 1.1 jruoho pid = fork();
395 1.1 jruoho
396 1.1 jruoho ATF_REQUIRE(pid >= 0);
397 1.1 jruoho
398 1.1 jruoho if (pid == 0) {
399 1.1 jruoho ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
400 1.1 jruoho ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0);
401 1.1 jruoho }
402 1.1 jruoho
403 1.1 jruoho (void)wait(&sta);
404 1.1 jruoho
405 1.1 jruoho ATF_REQUIRE(WIFEXITED(sta) != 0);
406 1.1 jruoho ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
407 1.1 jruoho ATF_REQUIRE(munmap(map, 3) == 0);
408 1.1 jruoho }
409 1.1 jruoho
410 1.1 jruoho ATF_TC_CLEANUP(mmap_prot_3, tc)
411 1.1 jruoho {
412 1.1 jruoho (void)unlink(path);
413 1.1 jruoho }
414 1.1 jruoho
415 1.1 jruoho ATF_TC_WITH_CLEANUP(mmap_truncate);
416 1.1 jruoho ATF_TC_HEAD(mmap_truncate, tc)
417 1.1 jruoho {
418 1.1 jruoho atf_tc_set_md_var(tc, "descr", "Test mmap(2) and ftruncate(2)");
419 1.1 jruoho }
420 1.1 jruoho
421 1.1 jruoho ATF_TC_BODY(mmap_truncate, tc)
422 1.1 jruoho {
423 1.1 jruoho char *map;
424 1.1 jruoho long i;
425 1.1 jruoho int fd;
426 1.1 jruoho
427 1.1 jruoho fd = open(path, O_RDWR | O_CREAT, 0700);
428 1.1 jruoho
429 1.1 jruoho if (fd < 0)
430 1.1 jruoho return;
431 1.1 jruoho
432 1.1 jruoho /*
433 1.1 jruoho * See that ftruncate(2) works
434 1.1 jruoho * while the file is mapped.
435 1.1 jruoho */
436 1.1 jruoho ATF_REQUIRE(ftruncate(fd, page) == 0);
437 1.1 jruoho
438 1.1 jruoho map = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_FILE|MAP_PRIVATE,
439 1.1 jruoho fd, 0);
440 1.1 jruoho ATF_REQUIRE(map != MAP_FAILED);
441 1.1 jruoho
442 1.1 jruoho for (i = 0; i < page; i++)
443 1.1 jruoho map[i] = 'x';
444 1.1 jruoho
445 1.1 jruoho ATF_REQUIRE(ftruncate(fd, 0) == 0);
446 1.1 jruoho ATF_REQUIRE(ftruncate(fd, page / 8) == 0);
447 1.1 jruoho ATF_REQUIRE(ftruncate(fd, page / 4) == 0);
448 1.1 jruoho ATF_REQUIRE(ftruncate(fd, page / 2) == 0);
449 1.1 jruoho ATF_REQUIRE(ftruncate(fd, page / 12) == 0);
450 1.1 jruoho ATF_REQUIRE(ftruncate(fd, page / 64) == 0);
451 1.1 jruoho
452 1.11 christos (void)munmap(map, page);
453 1.1 jruoho ATF_REQUIRE(close(fd) == 0);
454 1.1 jruoho }
455 1.1 jruoho
456 1.1 jruoho ATF_TC_CLEANUP(mmap_truncate, tc)
457 1.1 jruoho {
458 1.1 jruoho (void)unlink(path);
459 1.1 jruoho }
460 1.1 jruoho
461 1.8 christos ATF_TC_WITH_CLEANUP(mmap_truncate_signal);
462 1.8 christos ATF_TC_HEAD(mmap_truncate_signal, tc)
463 1.8 christos {
464 1.8 christos atf_tc_set_md_var(tc, "descr",
465 1.8 christos "Test mmap(2) ftruncate(2) causing signal");
466 1.8 christos }
467 1.8 christos
468 1.8 christos ATF_TC_BODY(mmap_truncate_signal, tc)
469 1.8 christos {
470 1.8 christos char *map;
471 1.8 christos long i;
472 1.8 christos int fd, sta;
473 1.8 christos pid_t pid;
474 1.8 christos
475 1.8 christos fd = open(path, O_RDWR | O_CREAT, 0700);
476 1.8 christos
477 1.8 christos if (fd < 0)
478 1.8 christos return;
479 1.8 christos
480 1.8 christos ATF_REQUIRE(write(fd, "foo\n", 5) == 5);
481 1.8 christos
482 1.8 christos map = mmap(NULL, page, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0);
483 1.8 christos ATF_REQUIRE(map != MAP_FAILED);
484 1.8 christos
485 1.8 christos sta = 0;
486 1.8 christos for (i = 0; i < 5; i++)
487 1.8 christos sta += map[i];
488 1.8 christos ATF_REQUIRE(sta == 334);
489 1.8 christos
490 1.8 christos ATF_REQUIRE(ftruncate(fd, 0) == 0);
491 1.8 christos pid = fork();
492 1.8 christos ATF_REQUIRE(pid >= 0);
493 1.8 christos
494 1.8 christos if (pid == 0) {
495 1.8 christos ATF_REQUIRE(signal(SIGBUS, map_sighandler) != SIG_ERR);
496 1.9 martin ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
497 1.8 christos sta = 0;
498 1.8 christos for (i = 0; i < page; i++)
499 1.8 christos sta += map[i];
500 1.9 martin /* child never will get this far, but the compiler will
501 1.9 martin not know, so better use the values calculated to
502 1.9 martin prevent the access to be optimized out */
503 1.8 christos ATF_REQUIRE(i == 0);
504 1.9 martin ATF_REQUIRE(sta == 0);
505 1.11 christos (void)munmap(map, page);
506 1.11 christos (void)close(fd);
507 1.9 martin return;
508 1.8 christos }
509 1.8 christos
510 1.8 christos (void)wait(&sta);
511 1.8 christos
512 1.8 christos ATF_REQUIRE(WIFEXITED(sta) != 0);
513 1.9 martin if (WEXITSTATUS(sta) == SIGSEGV)
514 1.9 martin atf_tc_fail("child process got SIGSEGV instead of SIGBUS");
515 1.8 christos ATF_REQUIRE(WEXITSTATUS(sta) == SIGBUS);
516 1.8 christos ATF_REQUIRE(munmap(map, page) == 0);
517 1.8 christos ATF_REQUIRE(close(fd) == 0);
518 1.8 christos }
519 1.8 christos
520 1.8 christos ATF_TC_CLEANUP(mmap_truncate_signal, tc)
521 1.8 christos {
522 1.8 christos (void)unlink(path);
523 1.8 christos }
524 1.8 christos
525 1.1 jruoho ATF_TC(mmap_va0);
526 1.1 jruoho ATF_TC_HEAD(mmap_va0, tc)
527 1.1 jruoho {
528 1.1 jruoho atf_tc_set_md_var(tc, "descr", "Test mmap(2) and vm.user_va0_disable");
529 1.1 jruoho }
530 1.1 jruoho
531 1.1 jruoho ATF_TC_BODY(mmap_va0, tc)
532 1.1 jruoho {
533 1.1 jruoho int flags = MAP_ANON | MAP_FIXED | MAP_PRIVATE;
534 1.1 jruoho size_t len = sizeof(int);
535 1.1 jruoho void *map;
536 1.1 jruoho int val;
537 1.1 jruoho
538 1.1 jruoho /*
539 1.1 jruoho * Make an anonymous fixed mapping at zero address. If the address
540 1.1 jruoho * is restricted as noted in security(7), the syscall should fail.
541 1.1 jruoho */
542 1.1 jruoho if (sysctlbyname("vm.user_va0_disable", &val, &len, NULL, 0) != 0)
543 1.1 jruoho atf_tc_fail("failed to read vm.user_va0_disable");
544 1.1 jruoho
545 1.1 jruoho map = mmap(NULL, page, PROT_EXEC, flags, -1, 0);
546 1.1 jruoho map_check(map, val);
547 1.1 jruoho
548 1.1 jruoho map = mmap(NULL, page, PROT_READ, flags, -1, 0);
549 1.1 jruoho map_check(map, val);
550 1.1 jruoho
551 1.1 jruoho map = mmap(NULL, page, PROT_WRITE, flags, -1, 0);
552 1.1 jruoho map_check(map, val);
553 1.1 jruoho
554 1.1 jruoho map = mmap(NULL, page, PROT_READ|PROT_WRITE, flags, -1, 0);
555 1.1 jruoho map_check(map, val);
556 1.1 jruoho
557 1.1 jruoho map = mmap(NULL, page, PROT_EXEC|PROT_READ|PROT_WRITE, flags, -1, 0);
558 1.1 jruoho map_check(map, val);
559 1.1 jruoho }
560 1.1 jruoho
561 1.1 jruoho ATF_TP_ADD_TCS(tp)
562 1.1 jruoho {
563 1.1 jruoho page = sysconf(_SC_PAGESIZE);
564 1.1 jruoho ATF_REQUIRE(page >= 0);
565 1.1 jruoho
566 1.3 jruoho ATF_TP_ADD_TC(tp, mmap_block);
567 1.1 jruoho ATF_TP_ADD_TC(tp, mmap_err);
568 1.2 jruoho ATF_TP_ADD_TC(tp, mmap_loan);
569 1.1 jruoho ATF_TP_ADD_TC(tp, mmap_prot_1);
570 1.1 jruoho ATF_TP_ADD_TC(tp, mmap_prot_2);
571 1.1 jruoho ATF_TP_ADD_TC(tp, mmap_prot_3);
572 1.1 jruoho ATF_TP_ADD_TC(tp, mmap_truncate);
573 1.8 christos ATF_TP_ADD_TC(tp, mmap_truncate_signal);
574 1.1 jruoho ATF_TP_ADD_TC(tp, mmap_va0);
575 1.1 jruoho
576 1.1 jruoho return atf_no_error();
577 1.1 jruoho }
578