t_mmap.c revision 1.10 1 1.10 christos /* $NetBSD: t_mmap.c,v 1.10 2017/01/10 22:36: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.10 christos __RCSID("$NetBSD: t_mmap.c,v 1.10 2017/01/10 22:36:29 christos Exp $");
59 1.1 jruoho
60 1.1 jruoho #include <sys/param.h>
61 1.1 jruoho #include <sys/mman.h>
62 1.10 christos #include <sys/stat.h>
63 1.2 jruoho #include <sys/socket.h>
64 1.1 jruoho #include <sys/sysctl.h>
65 1.1 jruoho #include <sys/wait.h>
66 1.1 jruoho
67 1.2 jruoho #include <atf-c.h>
68 1.1 jruoho #include <errno.h>
69 1.1 jruoho #include <fcntl.h>
70 1.1 jruoho #include <signal.h>
71 1.3 jruoho #include <stdio.h>
72 1.1 jruoho #include <stdlib.h>
73 1.1 jruoho #include <string.h>
74 1.1 jruoho #include <unistd.h>
75 1.5 martin #include <paths.h>
76 1.5 martin #include <machine/disklabel.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.5 martin sprintf(dev, _PATH_DEV "%s%c", dk, 'a'+RAW_PART);
182 1.5 martin fprintf(stderr, "trying: %s\n", dev);
183 1.3 jruoho
184 1.5 martin if ((fd = open(dev, O_RDONLY)) >= 0) {
185 1.5 martin (void)fprintf(stderr, "using %s\n", dev);
186 1.3 jruoho break;
187 1.3 jruoho }
188 1.3 jruoho }
189 1.5 martin free(drives);
190 1.3 jruoho
191 1.5 martin if (fd < 0)
192 1.4 jruoho atf_tc_skip("failed to find suitable block device");
193 1.3 jruoho
194 1.3 jruoho map = mmap(NULL, 4096, PROT_READ, MAP_FILE, fd, 0);
195 1.3 jruoho ATF_REQUIRE(map != MAP_FAILED);
196 1.3 jruoho
197 1.3 jruoho (void)fprintf(stderr, "first byte %x\n", *map);
198 1.3 jruoho ATF_REQUIRE(close(fd) == 0);
199 1.3 jruoho (void)fprintf(stderr, "first byte %x\n", *map);
200 1.3 jruoho
201 1.3 jruoho ATF_REQUIRE(munmap(map, 4096) == 0);
202 1.3 jruoho }
203 1.3 jruoho
204 1.1 jruoho ATF_TC(mmap_err);
205 1.1 jruoho ATF_TC_HEAD(mmap_err, tc)
206 1.1 jruoho {
207 1.1 jruoho atf_tc_set_md_var(tc, "descr", "Test error conditions of mmap(2)");
208 1.1 jruoho }
209 1.1 jruoho
210 1.1 jruoho ATF_TC_BODY(mmap_err, tc)
211 1.1 jruoho {
212 1.1 jruoho size_t addr = SIZE_MAX;
213 1.1 jruoho void *map;
214 1.1 jruoho
215 1.1 jruoho errno = 0;
216 1.1 jruoho map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, -1, 0);
217 1.1 jruoho
218 1.1 jruoho ATF_REQUIRE(map == MAP_FAILED);
219 1.1 jruoho ATF_REQUIRE(errno == EBADF);
220 1.1 jruoho
221 1.1 jruoho errno = 0;
222 1.1 jruoho map = mmap(&addr, page, PROT_READ, MAP_FIXED|MAP_PRIVATE, -1, 0);
223 1.1 jruoho
224 1.1 jruoho ATF_REQUIRE(map == MAP_FAILED);
225 1.1 jruoho ATF_REQUIRE(errno == EINVAL);
226 1.1 jruoho
227 1.1 jruoho errno = 0;
228 1.1 jruoho map = mmap(NULL, page, PROT_READ, MAP_ANON|MAP_PRIVATE, INT_MAX, 0);
229 1.1 jruoho
230 1.1 jruoho ATF_REQUIRE(map == MAP_FAILED);
231 1.1 jruoho ATF_REQUIRE(errno == EINVAL);
232 1.1 jruoho }
233 1.1 jruoho
234 1.2 jruoho ATF_TC_WITH_CLEANUP(mmap_loan);
235 1.2 jruoho ATF_TC_HEAD(mmap_loan, tc)
236 1.2 jruoho {
237 1.2 jruoho atf_tc_set_md_var(tc, "descr", "Test uvm page loanout with mmap(2)");
238 1.2 jruoho }
239 1.2 jruoho
240 1.2 jruoho ATF_TC_BODY(mmap_loan, tc)
241 1.2 jruoho {
242 1.2 jruoho char buf[BUFSIZE];
243 1.2 jruoho char *vp, *vp2;
244 1.2 jruoho int fd;
245 1.2 jruoho
246 1.2 jruoho fd = open(path, O_RDWR | O_CREAT, 0600);
247 1.2 jruoho ATF_REQUIRE(fd >= 0);
248 1.2 jruoho
249 1.2 jruoho (void)memset(buf, 'x', sizeof(buf));
250 1.2 jruoho (void)write(fd, buf, sizeof(buf));
251 1.2 jruoho
252 1.2 jruoho vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
253 1.2 jruoho MAP_FILE | MAP_PRIVATE, fd, 0);
254 1.2 jruoho
255 1.2 jruoho ATF_REQUIRE(vp != MAP_FAILED);
256 1.2 jruoho
257 1.2 jruoho vp2 = vp;
258 1.2 jruoho
259 1.2 jruoho testloan(vp, vp2, 'A', 0);
260 1.2 jruoho testloan(vp, vp2, 'B', 1);
261 1.2 jruoho
262 1.2 jruoho ATF_REQUIRE(munmap(vp, BUFSIZE) == 0);
263 1.2 jruoho
264 1.2 jruoho vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
265 1.2 jruoho MAP_FILE | MAP_SHARED, fd, 0);
266 1.2 jruoho
267 1.2 jruoho vp2 = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
268 1.2 jruoho MAP_FILE | MAP_SHARED, fd, 0);
269 1.2 jruoho
270 1.2 jruoho ATF_REQUIRE(vp != MAP_FAILED);
271 1.2 jruoho ATF_REQUIRE(vp2 != MAP_FAILED);
272 1.2 jruoho
273 1.2 jruoho testloan(vp, vp2, 'E', 1);
274 1.2 jruoho
275 1.2 jruoho ATF_REQUIRE(munmap(vp, BUFSIZE) == 0);
276 1.2 jruoho ATF_REQUIRE(munmap(vp2, BUFSIZE) == 0);
277 1.2 jruoho }
278 1.2 jruoho
279 1.2 jruoho ATF_TC_CLEANUP(mmap_loan, tc)
280 1.2 jruoho {
281 1.2 jruoho (void)unlink(path);
282 1.2 jruoho }
283 1.2 jruoho
284 1.1 jruoho ATF_TC_WITH_CLEANUP(mmap_prot_1);
285 1.1 jruoho ATF_TC_HEAD(mmap_prot_1, tc)
286 1.1 jruoho {
287 1.1 jruoho atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #1");
288 1.1 jruoho }
289 1.1 jruoho
290 1.1 jruoho ATF_TC_BODY(mmap_prot_1, tc)
291 1.1 jruoho {
292 1.1 jruoho void *map;
293 1.1 jruoho int fd;
294 1.1 jruoho
295 1.1 jruoho /*
296 1.1 jruoho * Open a file write-only and try to
297 1.1 jruoho * map it read-only. This should fail.
298 1.1 jruoho */
299 1.1 jruoho fd = open(path, O_WRONLY | O_CREAT, 0700);
300 1.1 jruoho
301 1.1 jruoho if (fd < 0)
302 1.1 jruoho return;
303 1.1 jruoho
304 1.1 jruoho ATF_REQUIRE(write(fd, "XXX", 3) == 3);
305 1.1 jruoho
306 1.1 jruoho map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0);
307 1.1 jruoho map_check(map, 1);
308 1.1 jruoho
309 1.1 jruoho map = mmap(NULL, 3, PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0);
310 1.1 jruoho map_check(map, 0);
311 1.1 jruoho
312 1.1 jruoho ATF_REQUIRE(close(fd) == 0);
313 1.1 jruoho }
314 1.1 jruoho
315 1.1 jruoho ATF_TC_CLEANUP(mmap_prot_1, tc)
316 1.1 jruoho {
317 1.1 jruoho (void)unlink(path);
318 1.1 jruoho }
319 1.1 jruoho
320 1.1 jruoho ATF_TC(mmap_prot_2);
321 1.1 jruoho ATF_TC_HEAD(mmap_prot_2, tc)
322 1.1 jruoho {
323 1.1 jruoho atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #2");
324 1.1 jruoho }
325 1.1 jruoho
326 1.1 jruoho ATF_TC_BODY(mmap_prot_2, tc)
327 1.1 jruoho {
328 1.1 jruoho char buf[2];
329 1.1 jruoho void *map;
330 1.1 jruoho pid_t pid;
331 1.1 jruoho int sta;
332 1.1 jruoho
333 1.1 jruoho /*
334 1.1 jruoho * Make a PROT_NONE mapping and try to access it.
335 1.1 jruoho * If we catch a SIGSEGV, all works as expected.
336 1.1 jruoho */
337 1.1 jruoho map = mmap(NULL, page, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
338 1.1 jruoho ATF_REQUIRE(map != MAP_FAILED);
339 1.1 jruoho
340 1.1 jruoho pid = fork();
341 1.1 jruoho ATF_REQUIRE(pid >= 0);
342 1.1 jruoho
343 1.1 jruoho if (pid == 0) {
344 1.1 jruoho ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
345 1.1 jruoho ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0);
346 1.1 jruoho }
347 1.1 jruoho
348 1.1 jruoho (void)wait(&sta);
349 1.1 jruoho
350 1.1 jruoho ATF_REQUIRE(WIFEXITED(sta) != 0);
351 1.1 jruoho ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
352 1.1 jruoho ATF_REQUIRE(munmap(map, page) == 0);
353 1.1 jruoho }
354 1.1 jruoho
355 1.1 jruoho ATF_TC_WITH_CLEANUP(mmap_prot_3);
356 1.1 jruoho ATF_TC_HEAD(mmap_prot_3, tc)
357 1.1 jruoho {
358 1.1 jruoho atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #3");
359 1.1 jruoho }
360 1.1 jruoho
361 1.1 jruoho ATF_TC_BODY(mmap_prot_3, tc)
362 1.1 jruoho {
363 1.1 jruoho char buf[2];
364 1.1 jruoho int fd, sta;
365 1.1 jruoho void *map;
366 1.1 jruoho pid_t pid;
367 1.1 jruoho
368 1.1 jruoho /*
369 1.1 jruoho * Open a file, change the permissions
370 1.1 jruoho * to read-only, and try to map it as
371 1.1 jruoho * PROT_NONE. This should succeed, but
372 1.1 jruoho * the access should generate SIGSEGV.
373 1.1 jruoho */
374 1.1 jruoho fd = open(path, O_RDWR | O_CREAT, 0700);
375 1.1 jruoho
376 1.1 jruoho if (fd < 0)
377 1.1 jruoho return;
378 1.1 jruoho
379 1.1 jruoho ATF_REQUIRE(write(fd, "XXX", 3) == 3);
380 1.1 jruoho ATF_REQUIRE(close(fd) == 0);
381 1.1 jruoho ATF_REQUIRE(chmod(path, 0444) == 0);
382 1.1 jruoho
383 1.1 jruoho fd = open(path, O_RDONLY);
384 1.1 jruoho ATF_REQUIRE(fd != -1);
385 1.1 jruoho
386 1.1 jruoho map = mmap(NULL, 3, PROT_NONE, MAP_FILE | MAP_SHARED, fd, 0);
387 1.1 jruoho ATF_REQUIRE(map != MAP_FAILED);
388 1.1 jruoho
389 1.1 jruoho pid = fork();
390 1.1 jruoho
391 1.1 jruoho ATF_REQUIRE(pid >= 0);
392 1.1 jruoho
393 1.1 jruoho if (pid == 0) {
394 1.1 jruoho ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
395 1.1 jruoho ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0);
396 1.1 jruoho }
397 1.1 jruoho
398 1.1 jruoho (void)wait(&sta);
399 1.1 jruoho
400 1.1 jruoho ATF_REQUIRE(WIFEXITED(sta) != 0);
401 1.1 jruoho ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
402 1.1 jruoho ATF_REQUIRE(munmap(map, 3) == 0);
403 1.1 jruoho }
404 1.1 jruoho
405 1.1 jruoho ATF_TC_CLEANUP(mmap_prot_3, tc)
406 1.1 jruoho {
407 1.1 jruoho (void)unlink(path);
408 1.1 jruoho }
409 1.1 jruoho
410 1.1 jruoho ATF_TC_WITH_CLEANUP(mmap_truncate);
411 1.1 jruoho ATF_TC_HEAD(mmap_truncate, tc)
412 1.1 jruoho {
413 1.1 jruoho atf_tc_set_md_var(tc, "descr", "Test mmap(2) and ftruncate(2)");
414 1.1 jruoho }
415 1.1 jruoho
416 1.1 jruoho ATF_TC_BODY(mmap_truncate, tc)
417 1.1 jruoho {
418 1.1 jruoho char *map;
419 1.1 jruoho long i;
420 1.1 jruoho int fd;
421 1.1 jruoho
422 1.1 jruoho fd = open(path, O_RDWR | O_CREAT, 0700);
423 1.1 jruoho
424 1.1 jruoho if (fd < 0)
425 1.1 jruoho return;
426 1.1 jruoho
427 1.1 jruoho /*
428 1.1 jruoho * See that ftruncate(2) works
429 1.1 jruoho * while the file is mapped.
430 1.1 jruoho */
431 1.1 jruoho ATF_REQUIRE(ftruncate(fd, page) == 0);
432 1.1 jruoho
433 1.1 jruoho map = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_FILE|MAP_PRIVATE,
434 1.1 jruoho fd, 0);
435 1.1 jruoho ATF_REQUIRE(map != MAP_FAILED);
436 1.1 jruoho
437 1.1 jruoho for (i = 0; i < page; i++)
438 1.1 jruoho map[i] = 'x';
439 1.1 jruoho
440 1.1 jruoho ATF_REQUIRE(ftruncate(fd, 0) == 0);
441 1.1 jruoho ATF_REQUIRE(ftruncate(fd, page / 8) == 0);
442 1.1 jruoho ATF_REQUIRE(ftruncate(fd, page / 4) == 0);
443 1.1 jruoho ATF_REQUIRE(ftruncate(fd, page / 2) == 0);
444 1.1 jruoho ATF_REQUIRE(ftruncate(fd, page / 12) == 0);
445 1.1 jruoho ATF_REQUIRE(ftruncate(fd, page / 64) == 0);
446 1.1 jruoho
447 1.1 jruoho ATF_REQUIRE(close(fd) == 0);
448 1.1 jruoho }
449 1.1 jruoho
450 1.1 jruoho ATF_TC_CLEANUP(mmap_truncate, tc)
451 1.1 jruoho {
452 1.1 jruoho (void)unlink(path);
453 1.1 jruoho }
454 1.1 jruoho
455 1.8 christos ATF_TC_WITH_CLEANUP(mmap_truncate_signal);
456 1.8 christos ATF_TC_HEAD(mmap_truncate_signal, tc)
457 1.8 christos {
458 1.8 christos atf_tc_set_md_var(tc, "descr",
459 1.8 christos "Test mmap(2) ftruncate(2) causing signal");
460 1.8 christos }
461 1.8 christos
462 1.8 christos ATF_TC_BODY(mmap_truncate_signal, tc)
463 1.8 christos {
464 1.8 christos char *map;
465 1.8 christos long i;
466 1.8 christos int fd, sta;
467 1.8 christos pid_t pid;
468 1.8 christos
469 1.8 christos fd = open(path, O_RDWR | O_CREAT, 0700);
470 1.8 christos
471 1.8 christos if (fd < 0)
472 1.8 christos return;
473 1.8 christos
474 1.8 christos ATF_REQUIRE(write(fd, "foo\n", 5) == 5);
475 1.8 christos
476 1.8 christos map = mmap(NULL, page, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0);
477 1.8 christos ATF_REQUIRE(map != MAP_FAILED);
478 1.8 christos
479 1.8 christos sta = 0;
480 1.8 christos for (i = 0; i < 5; i++)
481 1.8 christos sta += map[i];
482 1.8 christos ATF_REQUIRE(sta == 334);
483 1.8 christos
484 1.8 christos ATF_REQUIRE(ftruncate(fd, 0) == 0);
485 1.8 christos pid = fork();
486 1.8 christos ATF_REQUIRE(pid >= 0);
487 1.8 christos
488 1.8 christos if (pid == 0) {
489 1.8 christos ATF_REQUIRE(signal(SIGBUS, map_sighandler) != SIG_ERR);
490 1.9 martin ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
491 1.8 christos sta = 0;
492 1.8 christos for (i = 0; i < page; i++)
493 1.8 christos sta += map[i];
494 1.9 martin /* child never will get this far, but the compiler will
495 1.9 martin not know, so better use the values calculated to
496 1.9 martin prevent the access to be optimized out */
497 1.8 christos ATF_REQUIRE(i == 0);
498 1.9 martin ATF_REQUIRE(sta == 0);
499 1.9 martin return;
500 1.8 christos }
501 1.8 christos
502 1.8 christos (void)wait(&sta);
503 1.8 christos
504 1.8 christos ATF_REQUIRE(WIFEXITED(sta) != 0);
505 1.9 martin if (WEXITSTATUS(sta) == SIGSEGV)
506 1.9 martin atf_tc_fail("child process got SIGSEGV instead of SIGBUS");
507 1.8 christos ATF_REQUIRE(WEXITSTATUS(sta) == SIGBUS);
508 1.8 christos ATF_REQUIRE(munmap(map, page) == 0);
509 1.8 christos ATF_REQUIRE(close(fd) == 0);
510 1.8 christos }
511 1.8 christos
512 1.8 christos ATF_TC_CLEANUP(mmap_truncate_signal, tc)
513 1.8 christos {
514 1.8 christos (void)unlink(path);
515 1.8 christos }
516 1.8 christos
517 1.1 jruoho ATF_TC(mmap_va0);
518 1.1 jruoho ATF_TC_HEAD(mmap_va0, tc)
519 1.1 jruoho {
520 1.1 jruoho atf_tc_set_md_var(tc, "descr", "Test mmap(2) and vm.user_va0_disable");
521 1.1 jruoho }
522 1.1 jruoho
523 1.1 jruoho ATF_TC_BODY(mmap_va0, tc)
524 1.1 jruoho {
525 1.1 jruoho int flags = MAP_ANON | MAP_FIXED | MAP_PRIVATE;
526 1.1 jruoho size_t len = sizeof(int);
527 1.1 jruoho void *map;
528 1.1 jruoho int val;
529 1.1 jruoho
530 1.1 jruoho /*
531 1.1 jruoho * Make an anonymous fixed mapping at zero address. If the address
532 1.1 jruoho * is restricted as noted in security(7), the syscall should fail.
533 1.1 jruoho */
534 1.1 jruoho if (sysctlbyname("vm.user_va0_disable", &val, &len, NULL, 0) != 0)
535 1.1 jruoho atf_tc_fail("failed to read vm.user_va0_disable");
536 1.1 jruoho
537 1.1 jruoho map = mmap(NULL, page, PROT_EXEC, flags, -1, 0);
538 1.1 jruoho map_check(map, val);
539 1.1 jruoho
540 1.1 jruoho map = mmap(NULL, page, PROT_READ, flags, -1, 0);
541 1.1 jruoho map_check(map, val);
542 1.1 jruoho
543 1.1 jruoho map = mmap(NULL, page, PROT_WRITE, flags, -1, 0);
544 1.1 jruoho map_check(map, val);
545 1.1 jruoho
546 1.1 jruoho map = mmap(NULL, page, PROT_READ|PROT_WRITE, flags, -1, 0);
547 1.1 jruoho map_check(map, val);
548 1.1 jruoho
549 1.1 jruoho map = mmap(NULL, page, PROT_EXEC|PROT_READ|PROT_WRITE, flags, -1, 0);
550 1.1 jruoho map_check(map, val);
551 1.1 jruoho }
552 1.1 jruoho
553 1.1 jruoho ATF_TP_ADD_TCS(tp)
554 1.1 jruoho {
555 1.1 jruoho page = sysconf(_SC_PAGESIZE);
556 1.1 jruoho ATF_REQUIRE(page >= 0);
557 1.1 jruoho
558 1.3 jruoho ATF_TP_ADD_TC(tp, mmap_block);
559 1.1 jruoho ATF_TP_ADD_TC(tp, mmap_err);
560 1.2 jruoho ATF_TP_ADD_TC(tp, mmap_loan);
561 1.1 jruoho ATF_TP_ADD_TC(tp, mmap_prot_1);
562 1.1 jruoho ATF_TP_ADD_TC(tp, mmap_prot_2);
563 1.1 jruoho ATF_TP_ADD_TC(tp, mmap_prot_3);
564 1.1 jruoho ATF_TP_ADD_TC(tp, mmap_truncate);
565 1.8 christos ATF_TP_ADD_TC(tp, mmap_truncate_signal);
566 1.1 jruoho ATF_TP_ADD_TC(tp, mmap_va0);
567 1.1 jruoho
568 1.1 jruoho return atf_no_error();
569 1.1 jruoho }
570