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