xref: /freebsd/tests/sys/posixshm/posixshm_test.c (revision 734e82fe33aa764367791a7d603b383996c6b40b)
1 /*-
2  * Copyright (c) 2006 Robert N. M. Watson
3  * All rights reserved.
4  *
5  * Copyright (c) 2021 The FreeBSD Foundation
6  *
7  * Portions of this software were developed by Ka Ho Ng
8  * under sponsorship from the FreeBSD Foundation.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #include <sys/param.h>
34 #include <sys/ioctl.h>
35 #include <sys/mman.h>
36 #include <sys/resource.h>
37 #include <sys/stat.h>
38 #include <sys/syscall.h>
39 #include <sys/sysctl.h>
40 #include <sys/wait.h>
41 
42 #include <ctype.h>
43 #include <errno.h>
44 #include <fcntl.h>
45 #include <signal.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <unistd.h>
50 
51 #include <atf-c.h>
52 
53 #define	TEST_PATH_LEN	256
54 static char test_path[TEST_PATH_LEN];
55 static char test_path2[TEST_PATH_LEN];
56 static unsigned int test_path_idx = 0;
57 
58 static void
59 gen_a_test_path(char *path)
60 {
61 	snprintf(path, TEST_PATH_LEN, "/%s/tmp.XXXXXX%d",
62 	    getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR"),
63 	    test_path_idx);
64 
65 	test_path_idx++;
66 
67 	ATF_REQUIRE_MSG(mkstemp(path) != -1,
68 	    "mkstemp failed; errno=%d", errno);
69 	ATF_REQUIRE_MSG(unlink(path) == 0,
70 	    "unlink failed; errno=%d", errno);
71 }
72 
73 static void
74 gen_test_path(void)
75 {
76 	gen_a_test_path(test_path);
77 }
78 
79 static void
80 gen_test_path2(void)
81 {
82 	gen_a_test_path(test_path2);
83 }
84 
85 /*
86  * Attempt a shm_open() that should fail with an expected error of 'error'.
87  */
88 static void
89 shm_open_should_fail(const char *path, int flags, mode_t mode, int error)
90 {
91 	int fd;
92 
93 	fd = shm_open(path, flags, mode);
94 	ATF_CHECK_MSG(fd == -1, "shm_open didn't fail");
95 	ATF_CHECK_MSG(error == errno,
96 	    "shm_open didn't fail with expected errno; errno=%d; expected "
97 	    "errno=%d", errno, error);
98 }
99 
100 /*
101  * Attempt a shm_unlink() that should fail with an expected error of 'error'.
102  */
103 static void
104 shm_unlink_should_fail(const char *path, int error)
105 {
106 
107 	ATF_CHECK_MSG(shm_unlink(path) == -1, "shm_unlink didn't fail");
108 	ATF_CHECK_MSG(error == errno,
109 	    "shm_unlink didn't fail with expected errno; errno=%d; expected "
110 	    "errno=%d", errno, error);
111 }
112 
113 /*
114  * Open the test object and write a value to the first byte.  Returns valid fd
115  * on success and -1 on failure.
116  */
117 static int
118 scribble_object(const char *path, char value)
119 {
120 	char *page;
121 	int fd, pagesize;
122 
123 	ATF_REQUIRE(0 < (pagesize = getpagesize()));
124 
125 	fd = shm_open(path, O_CREAT|O_EXCL|O_RDWR, 0777);
126 	if (fd < 0 && errno == EEXIST) {
127 		if (shm_unlink(test_path) < 0)
128 			atf_tc_fail("shm_unlink");
129 		fd = shm_open(test_path, O_CREAT | O_EXCL | O_RDWR, 0777);
130 	}
131 	if (fd < 0)
132 		atf_tc_fail("shm_open failed; errno=%d", errno);
133 	if (ftruncate(fd, pagesize) < 0)
134 		atf_tc_fail("ftruncate failed; errno=%d", errno);
135 
136 	page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
137 	if (page == MAP_FAILED)
138 		atf_tc_fail("mmap failed; errno=%d", errno);
139 
140 	page[0] = value;
141 	ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
142 	    errno);
143 
144 	return (fd);
145 }
146 
147 /*
148  * Fail the test case if the 'path' does not refer to an shm whose first byte
149  * is equal to expected_value
150  */
151 static void
152 verify_object(const char *path, char expected_value)
153 {
154 	int fd;
155 	int pagesize;
156 	char *page;
157 
158 	ATF_REQUIRE(0 < (pagesize = getpagesize()));
159 
160 	fd = shm_open(path, O_RDONLY, 0777);
161 	if (fd < 0)
162 		atf_tc_fail("shm_open failed in verify_object; errno=%d, path=%s",
163 		    errno, path);
164 
165 	page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0);
166 	if (page == MAP_FAILED)
167 		atf_tc_fail("mmap(1)");
168 	if (page[0] != expected_value)
169 		atf_tc_fail("Renamed object has incorrect value; has"
170 		    "%d (0x%x, '%c'), expected %d (0x%x, '%c')\n",
171 		    page[0], page[0], isprint(page[0]) ? page[0] : ' ',
172 		    expected_value, expected_value,
173 		    isprint(expected_value) ? expected_value : ' ');
174 	ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
175 	    errno);
176 	close(fd);
177 }
178 
179 static off_t shm_max_pages = 32;
180 static const char byte_to_fill = 0x5f;
181 
182 static int
183 shm_fill(int fd, off_t offset, off_t len)
184 {
185 	int error;
186 	size_t blen, page_size;
187 	char *buf;
188 
189 	error = 0;
190 	page_size = getpagesize();
191 	buf = malloc(page_size);
192 	if (buf == NULL)
193 		return (1);
194 
195 	while (len > 0) {
196 		blen = len < (off_t)page_size ? (size_t)len : page_size;
197 		memset(buf, byte_to_fill, blen);
198 		if (pwrite(fd, buf, blen, offset) != (ssize_t)blen) {
199 			error = 1;
200 			break;
201 		}
202 		len -= blen;
203 		offset += blen;
204 	}
205 
206 	free(buf);
207 	return (error);
208 }
209 
210 static int
211 check_content_dealloc(int fd, off_t hole_start, off_t hole_len, off_t shm_sz)
212 {
213 	int error;
214 	size_t blen, page_size;
215 	off_t offset, resid;
216 	struct stat statbuf;
217 	char *buf, *sblk;
218 
219 	error = 0;
220 	page_size = getpagesize();
221 	buf = malloc(page_size * 2);
222 	if (buf == NULL)
223 		return (1);
224 	sblk = buf + page_size;
225 
226 	memset(sblk, 0, page_size);
227 
228 	if ((uint64_t)hole_start + hole_len > (uint64_t)shm_sz)
229 		hole_len = shm_sz - hole_start;
230 
231 	/*
232 	 * Check hole is zeroed.
233 	 */
234 	offset = hole_start;
235 	resid = hole_len;
236 	while (resid > 0) {
237 		blen = resid < (off_t)page_size ? (size_t)resid : page_size;
238 		if (pread(fd, buf, blen, offset) != (ssize_t)blen) {
239 			error = 1;
240 			break;
241 		}
242 		if (memcmp(buf, sblk, blen) != 0) {
243 			error = 1;
244 			break;
245 		}
246 		resid -= blen;
247 		offset += blen;
248 	}
249 
250 	memset(sblk, byte_to_fill, page_size);
251 
252 	/*
253 	 * Check file region before hole is zeroed.
254 	 */
255 	offset = 0;
256 	resid = hole_start;
257 	while (resid > 0) {
258 		blen = resid < (off_t)page_size ? (size_t)resid : page_size;
259 		if (pread(fd, buf, blen, offset) != (ssize_t)blen) {
260 			error = 1;
261 			break;
262 		}
263 		if (memcmp(buf, sblk, blen) != 0) {
264 			error = 1;
265 			break;
266 		}
267 		resid -= blen;
268 		offset += blen;
269 	}
270 
271 	/*
272 	 * Check file region after hole is zeroed.
273 	 */
274 	offset = hole_start + hole_len;
275 	resid = shm_sz - offset;
276 	while (resid > 0) {
277 		blen = resid < (off_t)page_size ? (size_t)resid : page_size;
278 		if (pread(fd, buf, blen, offset) != (ssize_t)blen) {
279 			error = 1;
280 			break;
281 		}
282 		if (memcmp(buf, sblk, blen) != 0) {
283 			error = 1;
284 			break;
285 		}
286 		resid -= blen;
287 		offset += blen;
288 	}
289 
290 	/*
291 	 * Check file size matches with expected file size.
292 	 */
293 	if (fstat(fd, &statbuf) == -1)
294 		error = -1;
295 	if (statbuf.st_size != shm_sz)
296 		error = -1;
297 
298 	free(buf);
299 	return (error);
300 }
301 
302 ATF_TC_WITHOUT_HEAD(remap_object);
303 ATF_TC_BODY(remap_object, tc)
304 {
305 	char *page;
306 	int fd, pagesize;
307 
308 	ATF_REQUIRE(0 < (pagesize = getpagesize()));
309 
310 	gen_test_path();
311 	fd = scribble_object(test_path, '1');
312 
313 	page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
314 	if (page == MAP_FAILED)
315 		atf_tc_fail("mmap(2) failed; errno=%d", errno);
316 
317 	if (page[0] != '1')
318 		atf_tc_fail("missing data ('%c' != '1')", page[0]);
319 
320 	close(fd);
321 	ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
322 	    errno);
323 
324 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
325 	    "shm_unlink failed; errno=%d", errno);
326 }
327 
328 ATF_TC_WITHOUT_HEAD(rename_from_anon);
329 ATF_TC_BODY(rename_from_anon, tc)
330 {
331 	int rc;
332 
333 	gen_test_path();
334 	rc = shm_rename(SHM_ANON, test_path, 0);
335 	if (rc != -1)
336 		atf_tc_fail("shm_rename from SHM_ANON succeeded unexpectedly");
337 }
338 
339 ATF_TC_WITHOUT_HEAD(rename_bad_path_pointer);
340 ATF_TC_BODY(rename_bad_path_pointer, tc)
341 {
342 	const char *bad_path;
343 	int rc;
344 
345 	bad_path = (const char *)0x1;
346 
347 	gen_test_path();
348 	rc = shm_rename(test_path, bad_path, 0);
349 	if (rc != -1)
350 		atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly");
351 
352 	rc = shm_rename(bad_path, test_path, 0);
353 	if (rc != -1)
354 		atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly");
355 }
356 
357 ATF_TC_WITHOUT_HEAD(rename_from_nonexisting);
358 ATF_TC_BODY(rename_from_nonexisting, tc)
359 {
360 	int rc;
361 
362 	gen_test_path();
363 	gen_test_path2();
364 	rc = shm_rename(test_path, test_path2, 0);
365 	if (rc != -1)
366 		atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly");
367 
368 	if (errno != ENOENT)
369 		atf_tc_fail("Expected ENOENT to rename of nonexistent shm; got %d",
370 		    errno);
371 }
372 
373 ATF_TC_WITHOUT_HEAD(rename_to_anon);
374 ATF_TC_BODY(rename_to_anon, tc)
375 {
376 	int rc;
377 
378 	gen_test_path();
379 	rc = shm_rename(test_path, SHM_ANON, 0);
380 	if (rc != -1)
381 		atf_tc_fail("shm_rename to SHM_ANON succeeded unexpectedly");
382 }
383 
384 ATF_TC_WITHOUT_HEAD(rename_to_replace);
385 ATF_TC_BODY(rename_to_replace, tc)
386 {
387 	char expected_value;
388 	int fd;
389 	int fd2;
390 
391 	// Some contents we can verify later
392 	expected_value = 'g';
393 
394 	gen_test_path();
395 	fd = scribble_object(test_path, expected_value);
396 	close(fd);
397 
398 	// Give the other some different value so we can detect success
399 	gen_test_path2();
400 	fd2 = scribble_object(test_path2, 'h');
401 	close(fd2);
402 
403 	ATF_REQUIRE_MSG(shm_rename(test_path, test_path2, 0) == 0,
404 	    "shm_rename failed; errno=%d", errno);
405 
406 	// Read back renamed; verify contents
407 	verify_object(test_path2, expected_value);
408 }
409 
410 ATF_TC_WITHOUT_HEAD(rename_to_noreplace);
411 ATF_TC_BODY(rename_to_noreplace, tc)
412 {
413 	char expected_value_from;
414 	char expected_value_to;
415 	int fd_from;
416 	int fd_to;
417 	int rc;
418 
419 	// Some contents we can verify later
420 	expected_value_from = 'g';
421 	gen_test_path();
422 	fd_from = scribble_object(test_path, expected_value_from);
423 	close(fd_from);
424 
425 	// Give the other some different value so we can detect success
426 	expected_value_to = 'h';
427 	gen_test_path2();
428 	fd_to = scribble_object(test_path2, expected_value_to);
429 	close(fd_to);
430 
431 	rc = shm_rename(test_path, test_path2, SHM_RENAME_NOREPLACE);
432 	ATF_REQUIRE_MSG((rc == -1) && (errno == EEXIST),
433 	    "shm_rename didn't fail as expected; errno: %d; return: %d", errno,
434 	    rc);
435 
436 	// Read back renamed; verify contents
437 	verify_object(test_path2, expected_value_to);
438 }
439 
440 ATF_TC_WITHOUT_HEAD(rename_to_exchange);
441 ATF_TC_BODY(rename_to_exchange, tc)
442 {
443 	char expected_value_from;
444 	char expected_value_to;
445 	int fd_from;
446 	int fd_to;
447 
448 	// Some contents we can verify later
449 	expected_value_from = 'g';
450 	gen_test_path();
451 	fd_from = scribble_object(test_path, expected_value_from);
452 	close(fd_from);
453 
454 	// Give the other some different value so we can detect success
455 	expected_value_to = 'h';
456 	gen_test_path2();
457 	fd_to = scribble_object(test_path2, expected_value_to);
458 	close(fd_to);
459 
460 	ATF_REQUIRE_MSG(shm_rename(test_path, test_path2,
461 	    SHM_RENAME_EXCHANGE) == 0,
462 	    "shm_rename failed; errno=%d", errno);
463 
464 	// Read back renamed; verify contents
465 	verify_object(test_path, expected_value_to);
466 	verify_object(test_path2, expected_value_from);
467 }
468 
469 ATF_TC_WITHOUT_HEAD(rename_to_exchange_nonexisting);
470 ATF_TC_BODY(rename_to_exchange_nonexisting, tc)
471 {
472 	char expected_value_from;
473 	int fd_from;
474 
475 	// Some contents we can verify later
476 	expected_value_from = 'g';
477 	gen_test_path();
478 	fd_from = scribble_object(test_path, expected_value_from);
479 	close(fd_from);
480 
481 	gen_test_path2();
482 
483 	ATF_REQUIRE_MSG(shm_rename(test_path, test_path2,
484 	    SHM_RENAME_EXCHANGE) == 0,
485 	    "shm_rename failed; errno=%d", errno);
486 
487 	// Read back renamed; verify contents
488 	verify_object(test_path2, expected_value_from);
489 }
490 
491 ATF_TC_WITHOUT_HEAD(rename_to_self);
492 ATF_TC_BODY(rename_to_self, tc)
493 {
494 	int fd;
495 	char expected_value;
496 
497 	expected_value = 't';
498 
499 	gen_test_path();
500 	fd = scribble_object(test_path, expected_value);
501 	close(fd);
502 
503 	ATF_REQUIRE_MSG(shm_rename(test_path, test_path, 0) == 0,
504 	    "shm_rename failed; errno=%d", errno);
505 
506 	verify_object(test_path, expected_value);
507 }
508 
509 ATF_TC_WITHOUT_HEAD(rename_bad_flag);
510 ATF_TC_BODY(rename_bad_flag, tc)
511 {
512 	int fd;
513 	int rc;
514 
515 	/* Make sure we don't fail out due to ENOENT */
516 	gen_test_path();
517 	gen_test_path2();
518 	fd = scribble_object(test_path, 'd');
519 	close(fd);
520 	fd = scribble_object(test_path2, 'd');
521 	close(fd);
522 
523 	/*
524 	 * Note: if we end up with enough flags that we use all the bits,
525 	 * then remove this test completely.
526 	 */
527 	rc = shm_rename(test_path, test_path2, INT_MIN);
528 	ATF_REQUIRE_MSG((rc == -1) && (errno == EINVAL),
529 	    "shm_rename should have failed with EINVAL; got: return=%d, "
530 	    "errno=%d", rc, errno);
531 }
532 
533 ATF_TC_WITHOUT_HEAD(reopen_object);
534 ATF_TC_BODY(reopen_object, tc)
535 {
536 	char *page;
537 	int fd, pagesize;
538 
539 	ATF_REQUIRE(0 < (pagesize = getpagesize()));
540 
541 	gen_test_path();
542 	fd = scribble_object(test_path, '1');
543 	close(fd);
544 
545 	fd = shm_open(test_path, O_RDONLY, 0777);
546 	if (fd < 0)
547 		atf_tc_fail("shm_open(2) failed; errno=%d", errno);
548 
549 	page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0);
550 	if (page == MAP_FAILED)
551 		atf_tc_fail("mmap(2) failed; errno=%d", errno);
552 
553 	if (page[0] != '1')
554 		atf_tc_fail("missing data ('%c' != '1')", page[0]);
555 
556 	ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
557 	    errno);
558 	close(fd);
559 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
560 	    "shm_unlink failed; errno=%d", errno);
561 }
562 
563 ATF_TC_WITHOUT_HEAD(readonly_mmap_write);
564 ATF_TC_BODY(readonly_mmap_write, tc)
565 {
566 	char *page;
567 	int fd, pagesize;
568 
569 	ATF_REQUIRE(0 < (pagesize = getpagesize()));
570 
571 	gen_test_path();
572 
573 	fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777);
574 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
575 
576 	/* PROT_WRITE should fail with EACCES. */
577 	page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
578 	if (page != MAP_FAILED)
579 		atf_tc_fail("mmap(PROT_WRITE) succeeded unexpectedly");
580 
581 	if (errno != EACCES)
582 		atf_tc_fail("mmap(PROT_WRITE) didn't fail with EACCES; "
583 		    "errno=%d", errno);
584 
585 	close(fd);
586 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
587 	    "shm_unlink failed; errno=%d", errno);
588 }
589 
590 ATF_TC_WITHOUT_HEAD(open_after_link);
591 ATF_TC_BODY(open_after_link, tc)
592 {
593 	int fd;
594 
595 	gen_test_path();
596 
597 	fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777);
598 	ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno);
599 	close(fd);
600 
601 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, "shm_unlink failed: %d",
602 	    errno);
603 
604 	shm_open_should_fail(test_path, O_RDONLY, 0777, ENOENT);
605 }
606 
607 ATF_TC_WITHOUT_HEAD(open_invalid_path);
608 ATF_TC_BODY(open_invalid_path, tc)
609 {
610 
611 	shm_open_should_fail("blah", O_RDONLY, 0777, EINVAL);
612 }
613 
614 ATF_TC_WITHOUT_HEAD(open_write_only);
615 ATF_TC_BODY(open_write_only, tc)
616 {
617 
618 	gen_test_path();
619 
620 	shm_open_should_fail(test_path, O_WRONLY, 0777, EINVAL);
621 }
622 
623 ATF_TC_WITHOUT_HEAD(open_extra_flags);
624 ATF_TC_BODY(open_extra_flags, tc)
625 {
626 
627 	gen_test_path();
628 
629 	shm_open_should_fail(test_path, O_RDONLY | O_DIRECT, 0777, EINVAL);
630 }
631 
632 ATF_TC_WITHOUT_HEAD(open_anon);
633 ATF_TC_BODY(open_anon, tc)
634 {
635 	int fd;
636 
637 	fd = shm_open(SHM_ANON, O_RDWR, 0777);
638 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
639 	close(fd);
640 }
641 
642 ATF_TC_WITHOUT_HEAD(open_anon_readonly);
643 ATF_TC_BODY(open_anon_readonly, tc)
644 {
645 
646 	shm_open_should_fail(SHM_ANON, O_RDONLY, 0777, EINVAL);
647 }
648 
649 ATF_TC_WITHOUT_HEAD(open_bad_path_pointer);
650 ATF_TC_BODY(open_bad_path_pointer, tc)
651 {
652 
653 	shm_open_should_fail((char *)1024, O_RDONLY, 0777, EFAULT);
654 }
655 
656 ATF_TC_WITHOUT_HEAD(open_path_too_long);
657 ATF_TC_BODY(open_path_too_long, tc)
658 {
659 	char *page;
660 
661 	page = malloc(MAXPATHLEN + 1);
662 	memset(page, 'a', MAXPATHLEN);
663 	page[MAXPATHLEN] = '\0';
664 	shm_open_should_fail(page, O_RDONLY, 0777, ENAMETOOLONG);
665 	free(page);
666 }
667 
668 ATF_TC_WITHOUT_HEAD(open_nonexisting_object);
669 ATF_TC_BODY(open_nonexisting_object, tc)
670 {
671 
672 	shm_open_should_fail("/notreallythere", O_RDONLY, 0777, ENOENT);
673 }
674 
675 ATF_TC_WITHOUT_HEAD(open_create_existing_object);
676 ATF_TC_BODY(open_create_existing_object, tc)
677 {
678 	int fd;
679 
680 	gen_test_path();
681 
682 	fd = shm_open(test_path, O_RDONLY|O_CREAT, 0777);
683 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
684 	close(fd);
685 
686 	shm_open_should_fail(test_path, O_RDONLY|O_CREAT|O_EXCL,
687 	    0777, EEXIST);
688 
689 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
690 	    "shm_unlink failed; errno=%d", errno);
691 }
692 
693 ATF_TC_WITHOUT_HEAD(trunc_resets_object);
694 ATF_TC_BODY(trunc_resets_object, tc)
695 {
696 	struct stat sb;
697 	int fd;
698 
699 	gen_test_path();
700 
701 	/* Create object and set size to 1024. */
702 	fd = shm_open(test_path, O_RDWR | O_CREAT, 0777);
703 	ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno);
704 	ATF_REQUIRE_MSG(ftruncate(fd, 1024) != -1,
705 	    "ftruncate failed; errno=%d", errno);
706 	ATF_REQUIRE_MSG(fstat(fd, &sb) != -1,
707 	    "fstat(1) failed; errno=%d", errno);
708 	ATF_REQUIRE_MSG(sb.st_size == 1024, "size %d != 1024", (int)sb.st_size);
709 	close(fd);
710 
711 	/* Open with O_TRUNC which should reset size to 0. */
712 	fd = shm_open(test_path, O_RDWR | O_TRUNC, 0777);
713 	ATF_REQUIRE_MSG(fd >= 0, "shm_open(2) failed; errno=%d", errno);
714 	ATF_REQUIRE_MSG(fstat(fd, &sb) != -1,
715 	    "fstat(2) failed; errno=%d", errno);
716 	ATF_REQUIRE_MSG(sb.st_size == 0,
717 	    "size was not 0 after truncation: %d", (int)sb.st_size);
718 	close(fd);
719 	ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,
720 	    "shm_unlink failed; errno=%d", errno);
721 }
722 
723 ATF_TC_WITHOUT_HEAD(unlink_bad_path_pointer);
724 ATF_TC_BODY(unlink_bad_path_pointer, tc)
725 {
726 
727 	shm_unlink_should_fail((char *)1024, EFAULT);
728 }
729 
730 ATF_TC_WITHOUT_HEAD(unlink_path_too_long);
731 ATF_TC_BODY(unlink_path_too_long, tc)
732 {
733 	char *page;
734 
735 	page = malloc(MAXPATHLEN + 1);
736 	memset(page, 'a', MAXPATHLEN);
737 	page[MAXPATHLEN] = '\0';
738 	shm_unlink_should_fail(page, ENAMETOOLONG);
739 	free(page);
740 }
741 
742 ATF_TC_WITHOUT_HEAD(object_resize);
743 ATF_TC_BODY(object_resize, tc)
744 {
745 	pid_t pid;
746 	struct stat sb;
747 	char *page;
748 	int fd, pagesize, status;
749 
750 	ATF_REQUIRE(0 < (pagesize = getpagesize()));
751 
752 	/* Start off with a size of a single page. */
753 	fd = shm_open(SHM_ANON, O_CREAT|O_RDWR, 0777);
754 	if (fd < 0)
755 		atf_tc_fail("shm_open failed; errno=%d", errno);
756 
757 	if (ftruncate(fd, pagesize) < 0)
758 		atf_tc_fail("ftruncate(1) failed; errno=%d", errno);
759 
760 	if (fstat(fd, &sb) < 0)
761 		atf_tc_fail("fstat(1) failed; errno=%d", errno);
762 
763 	if (sb.st_size != pagesize)
764 		atf_tc_fail("first resize failed (%d != %d)",
765 		    (int)sb.st_size, pagesize);
766 
767 	/* Write a '1' to the first byte. */
768 	page = mmap(0, pagesize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
769 	if (page == MAP_FAILED)
770 		atf_tc_fail("mmap(1)");
771 
772 	page[0] = '1';
773 
774 	ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",
775 	    errno);
776 
777 	/* Grow the object to 2 pages. */
778 	if (ftruncate(fd, pagesize * 2) < 0)
779 		atf_tc_fail("ftruncate(2) failed; errno=%d", errno);
780 
781 	if (fstat(fd, &sb) < 0)
782 		atf_tc_fail("fstat(2) failed; errno=%d", errno);
783 
784 	if (sb.st_size != pagesize * 2)
785 		atf_tc_fail("second resize failed (%d != %d)",
786 		    (int)sb.st_size, pagesize * 2);
787 
788 	/* Check for '1' at the first byte. */
789 	page = mmap(0, pagesize * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
790 	if (page == MAP_FAILED)
791 		atf_tc_fail("mmap(2) failed; errno=%d", errno);
792 
793 	if (page[0] != '1')
794 		atf_tc_fail("'%c' != '1'", page[0]);
795 
796 	/* Write a '2' at the start of the second page. */
797 	page[pagesize] = '2';
798 
799 	/* Shrink the object back to 1 page. */
800 	if (ftruncate(fd, pagesize) < 0)
801 		atf_tc_fail("ftruncate(3) failed; errno=%d", errno);
802 
803 	if (fstat(fd, &sb) < 0)
804 		atf_tc_fail("fstat(3) failed; errno=%d", errno);
805 
806 	if (sb.st_size != pagesize)
807 		atf_tc_fail("third resize failed (%d != %d)",
808 		    (int)sb.st_size, pagesize);
809 
810 	/*
811 	 * Fork a child process to make sure the second page is no
812 	 * longer valid.
813 	 */
814 	pid = fork();
815 	if (pid == -1)
816 		atf_tc_fail("fork failed; errno=%d", errno);
817 
818 	if (pid == 0) {
819 		struct rlimit lim;
820 		char c;
821 
822 		/* Don't generate a core dump. */
823 		ATF_REQUIRE(getrlimit(RLIMIT_CORE, &lim) == 0);
824 		lim.rlim_cur = 0;
825 		ATF_REQUIRE(setrlimit(RLIMIT_CORE, &lim) == 0);
826 
827 		/*
828 		 * The previous ftruncate(2) shrunk the backing object
829 		 * so that this address is no longer valid, so reading
830 		 * from it should trigger a SIGBUS.
831 		 */
832 		c = page[pagesize];
833 		fprintf(stderr, "child: page 1: '%c'\n", c);
834 		exit(0);
835 	}
836 
837 	if (wait(&status) < 0)
838 		atf_tc_fail("wait failed; errno=%d", errno);
839 
840 	if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGBUS)
841 		atf_tc_fail("child terminated with status %x", status);
842 
843 	/* Grow the object back to 2 pages. */
844 	if (ftruncate(fd, pagesize * 2) < 0)
845 		atf_tc_fail("ftruncate(2) failed; errno=%d", errno);
846 
847 	if (fstat(fd, &sb) < 0)
848 		atf_tc_fail("fstat(2) failed; errno=%d", errno);
849 
850 	if (sb.st_size != pagesize * 2)
851 		atf_tc_fail("fourth resize failed (%d != %d)",
852 		    (int)sb.st_size, pagesize);
853 
854 	/*
855 	 * Note that the mapping at 'page' for the second page is
856 	 * still valid, and now that the shm object has been grown
857 	 * back up to 2 pages, there is now memory backing this page
858 	 * so the read will work.  However, the data should be zero
859 	 * rather than '2' as the old data was thrown away when the
860 	 * object was shrunk and the new pages when an object are
861 	 * grown are zero-filled.
862 	 */
863 	if (page[pagesize] != 0)
864 		atf_tc_fail("invalid data at %d: %x != 0",
865 		    pagesize, (int)page[pagesize]);
866 
867 	close(fd);
868 }
869 
870 /* Signal handler which does nothing. */
871 static void
872 ignoreit(int sig __unused)
873 {
874 	;
875 }
876 
877 ATF_TC_WITHOUT_HEAD(shm_functionality_across_fork);
878 ATF_TC_BODY(shm_functionality_across_fork, tc)
879 {
880 	char *cp, c;
881 	int error, desc, rv;
882 	long scval;
883 	sigset_t ss;
884 	struct sigaction sa;
885 	void *region;
886 	size_t i, psize;
887 
888 #ifndef _POSIX_SHARED_MEMORY_OBJECTS
889 	printf("_POSIX_SHARED_MEMORY_OBJECTS is undefined\n");
890 #else
891 	printf("_POSIX_SHARED_MEMORY_OBJECTS is defined as %ld\n",
892 	       (long)_POSIX_SHARED_MEMORY_OBJECTS - 0);
893 	if (_POSIX_SHARED_MEMORY_OBJECTS - 0 == -1)
894 		printf("***Indicates this feature may be unsupported!\n");
895 #endif
896 	errno = 0;
897 	scval = sysconf(_SC_SHARED_MEMORY_OBJECTS);
898 	if (scval == -1 && errno != 0) {
899 		atf_tc_fail("sysconf(_SC_SHARED_MEMORY_OBJECTS) failed; "
900 		    "errno=%d", errno);
901 	} else {
902 		printf("sysconf(_SC_SHARED_MEMORY_OBJECTS) returns %ld\n",
903 		       scval);
904 		if (scval == -1)
905 			printf("***Indicates this feature is unsupported!\n");
906 	}
907 
908 	errno = 0;
909 	scval = sysconf(_SC_PAGESIZE);
910 	if (scval == -1 && errno != 0) {
911 		atf_tc_fail("sysconf(_SC_PAGESIZE) failed; errno=%d", errno);
912 	} else if (scval <= 0) {
913 		fprintf(stderr, "bogus return from sysconf(_SC_PAGESIZE): %ld",
914 		    scval);
915 		psize = 4096;
916 	} else {
917 		printf("sysconf(_SC_PAGESIZE) returns %ld\n", scval);
918 		psize = scval;
919 	}
920 
921 	gen_test_path();
922 	desc = shm_open(test_path, O_EXCL | O_CREAT | O_RDWR, 0600);
923 
924 	ATF_REQUIRE_MSG(desc >= 0, "shm_open failed; errno=%d", errno);
925 	ATF_REQUIRE_MSG(shm_unlink(test_path) == 0,
926 	    "shm_unlink failed; errno=%d", errno);
927 	ATF_REQUIRE_MSG(ftruncate(desc, (off_t)psize) != -1,
928 	    "ftruncate failed; errno=%d", errno);
929 
930 	region = mmap(NULL, psize, PROT_READ | PROT_WRITE, MAP_SHARED, desc, 0);
931 	ATF_REQUIRE_MSG(region != MAP_FAILED, "mmap failed; errno=%d", errno);
932 	memset(region, '\377', psize);
933 
934 	sa.sa_flags = 0;
935 	sa.sa_handler = ignoreit;
936 	sigemptyset(&sa.sa_mask);
937 	ATF_REQUIRE_MSG(sigaction(SIGUSR1, &sa, (struct sigaction *)0) == 0,
938 	    "sigaction failed; errno=%d", errno);
939 
940 	sigemptyset(&ss);
941 	sigaddset(&ss, SIGUSR1);
942 	ATF_REQUIRE_MSG(sigprocmask(SIG_BLOCK, &ss, (sigset_t *)0) == 0,
943 	    "sigprocmask failed; errno=%d", errno);
944 
945 	rv = fork();
946 	ATF_REQUIRE_MSG(rv != -1, "fork failed; errno=%d", errno);
947 	if (rv == 0) {
948 		sigemptyset(&ss);
949 		sigsuspend(&ss);
950 
951 		for (cp = region; cp < (char *)region + psize; cp++) {
952 			if (*cp != '\151')
953 				_exit(1);
954 		}
955 		if (lseek(desc, 0, SEEK_SET) == -1)
956 			_exit(1);
957 		for (i = 0; i < psize; i++) {
958 			error = read(desc, &c, 1);
959 			if (c != '\151')
960 				_exit(1);
961 		}
962 		_exit(0);
963 	} else {
964 		int status;
965 
966 		memset(region, '\151', psize - 2);
967 		error = pwrite(desc, region, 2, psize - 2);
968 		if (error != 2) {
969 			if (error >= 0)
970 				atf_tc_fail("short write; %d bytes written",
971 				    error);
972 			else
973 				atf_tc_fail("shmfd write");
974 		}
975 		kill(rv, SIGUSR1);
976 		waitpid(rv, &status, 0);
977 
978 		if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
979 			printf("Functionality test successful\n");
980 		} else if (WIFEXITED(status)) {
981 			atf_tc_fail("Child process exited with status %d",
982 			    WEXITSTATUS(status));
983 		} else {
984 			atf_tc_fail("Child process terminated with %s",
985 			    strsignal(WTERMSIG(status)));
986 		}
987 	}
988 
989 	ATF_REQUIRE_MSG(munmap(region, psize) == 0, "munmap failed; errno=%d",
990 	    errno);
991 	shm_unlink(test_path);
992 }
993 
994 ATF_TC_WITHOUT_HEAD(cloexec);
995 ATF_TC_BODY(cloexec, tc)
996 {
997 	int fd;
998 
999 	gen_test_path();
1000 
1001 	/* shm_open(2) is required to set FD_CLOEXEC */
1002 	fd = shm_open(SHM_ANON, O_RDWR, 0777);
1003 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
1004 	ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0);
1005 	close(fd);
1006 
1007 	/* Also make sure that named shm is correct */
1008 	fd = shm_open(test_path, O_CREAT | O_RDWR, 0600);
1009 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
1010 	ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0);
1011 	close(fd);
1012 }
1013 
1014 ATF_TC_WITHOUT_HEAD(mode);
1015 ATF_TC_BODY(mode, tc)
1016 {
1017 	struct stat st;
1018 	int fd;
1019 	mode_t restore_mask;
1020 
1021 	gen_test_path();
1022 
1023 	/* Remove inhibitions from umask */
1024 	restore_mask = umask(0);
1025 	fd = shm_open(test_path, O_CREAT | O_RDWR, 0600);
1026 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
1027 	ATF_REQUIRE(fstat(fd, &st) == 0);
1028 	ATF_REQUIRE((st.st_mode & ACCESSPERMS) == 0600);
1029 	close(fd);
1030 	ATF_REQUIRE(shm_unlink(test_path) == 0);
1031 
1032 	fd = shm_open(test_path, O_CREAT | O_RDWR, 0660);
1033 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
1034 	ATF_REQUIRE(fstat(fd, &st) == 0);
1035 	ATF_REQUIRE((st.st_mode & ACCESSPERMS) == 0660);
1036 	close(fd);
1037 	ATF_REQUIRE(shm_unlink(test_path) == 0);
1038 
1039 	fd = shm_open(test_path, O_CREAT | O_RDWR, 0666);
1040 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
1041 	ATF_REQUIRE(fstat(fd, &st) == 0);
1042 	ATF_REQUIRE((st.st_mode & ACCESSPERMS) == 0666);
1043 	close(fd);
1044 	ATF_REQUIRE(shm_unlink(test_path) == 0);
1045 
1046 	umask(restore_mask);
1047 }
1048 
1049 ATF_TC_WITHOUT_HEAD(fallocate);
1050 ATF_TC_BODY(fallocate, tc)
1051 {
1052 	struct stat st;
1053 	int error, fd, sz;
1054 
1055 	/*
1056 	 * Primitive test case for posix_fallocate with shmd.  Effectively
1057 	 * expected to work like a smarter ftruncate that will grow the region
1058 	 * as needed in a race-free way.
1059 	 */
1060 	fd = shm_open(SHM_ANON, O_RDWR, 0666);
1061 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
1062 	/* Set the initial size. */
1063 	sz = 32;
1064 	ATF_REQUIRE(ftruncate(fd, sz) == 0);
1065 
1066 	/* Now grow it. */
1067 	error = 0;
1068 	sz *= 2;
1069 	ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, sz)) == 0,
1070 	    "posix_fallocate failed; error=%d", error);
1071 	ATF_REQUIRE(fstat(fd, &st) == 0);
1072 	ATF_REQUIRE(st.st_size == sz);
1073 	/* Attempt to shrink it; should succeed, but not change the size. */
1074 	ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, sz / 2)) == 0,
1075 	    "posix_fallocate failed; error=%d", error);
1076 	ATF_REQUIRE(fstat(fd, &st) == 0);
1077 	ATF_REQUIRE(st.st_size == sz);
1078 	/* Grow it using an offset of sz and len of sz. */
1079 	ATF_REQUIRE_MSG((error = posix_fallocate(fd, sz, sz)) == 0,
1080 	    "posix_fallocate failed; error=%d", error);
1081 	ATF_REQUIRE(fstat(fd, &st) == 0);
1082 	ATF_REQUIRE(st.st_size == sz * 2);
1083 
1084 	close(fd);
1085 }
1086 
1087 ATF_TC_WITHOUT_HEAD(fspacectl);
1088 ATF_TC_BODY(fspacectl, tc)
1089 {
1090 	struct spacectl_range range;
1091 	off_t offset, length, shm_sz;
1092 	size_t page_size;
1093 	int fd, error;
1094 
1095 	page_size = getpagesize();
1096 	shm_sz = shm_max_pages * page_size;
1097 
1098 	fd = shm_open("/testtest", O_RDWR | O_CREAT, 0666);
1099 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno:%d", errno);
1100 	ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, shm_sz)) == 0,
1101 	    "posix_fallocate failed; error=%d", error);
1102 
1103 	/* Aligned fspacectl(fd, SPACECTL_DEALLOC, ...) */
1104 	ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0);
1105 	range.r_offset = offset = page_size;
1106 	range.r_len = length = ((shm_max_pages - 1) * page_size) -
1107 	    range.r_offset;
1108 	ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0,
1109 	    "Aligned fspacectl failed; errno=%d", errno);
1110 	ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0,
1111 	    "Aligned fspacectl content checking failed");
1112 
1113 	/* Unaligned fspacectl(fd, SPACECTL_DEALLOC, ...) */
1114 	ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0);
1115 	range.r_offset = offset = page_size / 2;
1116 	range.r_len = length = (shm_max_pages - 1) * page_size +
1117 	    (page_size / 2) - offset;
1118 	ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0,
1119 	    "Unaligned fspacectl failed; errno=%d", errno);
1120 	ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0,
1121 	    "Unaligned fspacectl content checking failed");
1122 
1123 	/* Aligned fspacectl(fd, SPACECTL_DEALLOC, ...) to OFF_MAX */
1124 	ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0);
1125 	range.r_offset = offset = page_size;
1126 	range.r_len = length = OFF_MAX - offset;
1127 	ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0,
1128 	    "Aligned fspacectl to OFF_MAX failed; errno=%d", errno);
1129 	ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0,
1130 	    "Aligned fspacectl to OFF_MAX content checking failed");
1131 
1132 	/* Unaligned fspacectl(fd, SPACECTL_DEALLOC, ...) to OFF_MAX */
1133 	ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0);
1134 	range.r_offset = offset = page_size / 2;
1135 	range.r_len = length = OFF_MAX - offset;
1136 	ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0,
1137 	    "Unaligned fspacectl to OFF_MAX failed; errno=%d", errno);
1138 	ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0,
1139 	    "Unaligned fspacectl to OFF_MAX content checking failed");
1140 
1141 	/* Aligned fspacectl(fd, SPACECTL_DEALLOC, ...) past shm_sz */
1142 	ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0);
1143 	range.r_offset = offset = page_size;
1144 	range.r_len = length = (shm_max_pages + 1) * page_size - offset;
1145 	ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0,
1146 	    "Aligned fspacectl past shm_sz failed; errno=%d", errno);
1147 	ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0,
1148 	    "Aligned fspacectl past shm_sz content checking failed");
1149 
1150 	/* Unaligned fspacectl(fd, SPACECTL_DEALLOC, ...) past shm_sz */
1151 	ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0);
1152 	range.r_offset = offset = page_size / 2;
1153 	range.r_len = length = (shm_max_pages + 1) * page_size - offset;
1154 	ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0,
1155 	    "Unaligned fspacectl past shm_sz failed; errno=%d", errno);
1156 	ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0,
1157 	    "Unaligned fspacectl past shm_sz content checking failed");
1158 
1159 	ATF_REQUIRE(close(fd) == 0);
1160 }
1161 
1162 ATF_TC_WITHOUT_HEAD(accounting);
1163 ATF_TC_BODY(accounting, tc)
1164 {
1165 	struct spacectl_range range;
1166 	struct stat st;
1167 	off_t shm_sz, len;
1168 	size_t page_size;
1169 	int fd, error;
1170 
1171 	page_size = getpagesize();
1172 	shm_sz = shm_max_pages * page_size;
1173 
1174 	fd = shm_open("/testtest1", O_RDWR | O_CREAT, 0666);
1175 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno:%d", errno);
1176 	ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, shm_sz)) == 0,
1177 	    "posix_fallocate failed; error=%d", error);
1178 
1179 	ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0);
1180 	ATF_REQUIRE(fstat(fd, &st) == 0);
1181 	ATF_REQUIRE(st.st_blksize * st.st_blocks == (blkcnt_t)shm_sz);
1182 
1183 	range.r_offset = page_size;
1184 	range.r_len = len = (shm_max_pages - 1) * page_size -
1185 	    range.r_offset;
1186 	ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0,
1187 	    "SPACECTL_DEALLOC failed; errno=%d", errno);
1188 	ATF_REQUIRE(fstat(fd, &st) == 0);
1189 	ATF_REQUIRE(st.st_blksize * st.st_blocks == (blkcnt_t)(shm_sz - len));
1190 
1191 	ATF_REQUIRE(close(fd) == 0);
1192 }
1193 
1194 static int
1195 shm_open_large(int psind, int policy, size_t sz)
1196 {
1197 	int error, fd;
1198 
1199 	fd = shm_create_largepage(SHM_ANON, O_CREAT | O_RDWR, psind, policy, 0);
1200 	if (fd < 0 && errno == ENOTTY)
1201 		atf_tc_skip("no large page support");
1202 	ATF_REQUIRE_MSG(fd >= 0, "shm_create_largepage failed; errno=%d", errno);
1203 
1204 	error = ftruncate(fd, sz);
1205 	if (error != 0 && errno == ENOMEM)
1206 		/*
1207 		 * The test system might not have enough memory to accommodate
1208 		 * the request.
1209 		 */
1210 		atf_tc_skip("failed to allocate %zu-byte superpage", sz);
1211 	ATF_REQUIRE_MSG(error == 0, "ftruncate failed; errno=%d", errno);
1212 
1213 	return (fd);
1214 }
1215 
1216 static int
1217 pagesizes(size_t ps[MAXPAGESIZES])
1218 {
1219 	int pscnt;
1220 
1221 	pscnt = getpagesizes(ps, MAXPAGESIZES);
1222 	ATF_REQUIRE_MSG(pscnt != -1, "getpagesizes failed; errno=%d", errno);
1223 	ATF_REQUIRE_MSG(ps[0] != 0, "psind 0 is %zu", ps[0]);
1224 	ATF_REQUIRE_MSG(pscnt <= MAXPAGESIZES, "invalid pscnt %d", pscnt);
1225 	if (pscnt == 1)
1226 		atf_tc_skip("no large page support");
1227 	return (pscnt);
1228 }
1229 
1230 ATF_TC_WITHOUT_HEAD(largepage_basic);
1231 ATF_TC_BODY(largepage_basic, tc)
1232 {
1233 	char *zeroes;
1234 	char *addr, *vec;
1235 	size_t ps[MAXPAGESIZES];
1236 	int error, fd, pscnt;
1237 
1238 	pscnt = pagesizes(ps);
1239 	zeroes = calloc(1, ps[0]);
1240 	ATF_REQUIRE(zeroes != NULL);
1241 	for (int i = 1; i < pscnt; i++) {
1242 		fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
1243 
1244 		addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1245 		    0);
1246 		ATF_REQUIRE_MSG(addr != MAP_FAILED,
1247 		    "mmap(%zu bytes) failed; errno=%d", ps[i], errno);
1248 		ATF_REQUIRE_MSG(((uintptr_t)addr & (ps[i] - 1)) == 0,
1249 		    "mmap(%zu bytes) returned unaligned mapping; addr=%p",
1250 		    ps[i], addr);
1251 
1252 		/* Force a page fault. */
1253 		*(volatile char *)addr = 0;
1254 
1255 		vec = malloc(ps[i] / ps[0]);
1256 		ATF_REQUIRE(vec != NULL);
1257 		error = mincore(addr, ps[i], vec);
1258 		ATF_REQUIRE_MSG(error == 0, "mincore failed; errno=%d", errno);
1259 
1260 		/* Verify that all pages in the run are mapped. */
1261 		for (size_t p = 0; p < ps[i] / ps[0]; p++) {
1262 			ATF_REQUIRE_MSG((vec[p] & MINCORE_INCORE) != 0,
1263 			    "page %zu is not mapped", p);
1264 			ATF_REQUIRE_MSG((vec[p] & MINCORE_SUPER) ==
1265 			    MINCORE_PSIND(i),
1266 			    "page %zu is not in a %zu-byte superpage",
1267 			    p, ps[i]);
1268 		}
1269 
1270 		/* Validate zeroing. */
1271 		for (size_t p = 0; p < ps[i] / ps[0]; p++) {
1272 			ATF_REQUIRE_MSG(memcmp(addr + p * ps[0], zeroes,
1273 			    ps[0]) == 0, "page %zu miscompare", p);
1274 		}
1275 
1276 		free(vec);
1277 		ATF_REQUIRE(munmap(addr, ps[i]) == 0);
1278 		ATF_REQUIRE(close(fd) == 0);
1279 	}
1280 
1281 	free(zeroes);
1282 }
1283 
1284 extern int __sys_shm_open2(const char *, int, mode_t, int, const char *);
1285 
1286 ATF_TC_WITHOUT_HEAD(largepage_config);
1287 ATF_TC_BODY(largepage_config, tc)
1288 {
1289 	struct shm_largepage_conf lpc;
1290 	char *addr, *buf;
1291 	size_t ps[MAXPAGESIZES + 1]; /* silence warnings if MAXPAGESIZES == 1 */
1292 	int error, fd;
1293 
1294 	(void)pagesizes(ps);
1295 
1296 	fd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0);
1297 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; error=%d", errno);
1298 
1299 	/*
1300 	 * Configure a large page policy for an object created without
1301 	 * SHM_LARGEPAGE.
1302 	 */
1303 	lpc.psind = 1;
1304 	lpc.alloc_policy = SHM_LARGEPAGE_ALLOC_DEFAULT;
1305 	error = ioctl(fd, FIOSSHMLPGCNF, &lpc);
1306 	ATF_REQUIRE(error != 0);
1307 	ATF_REQUIRE_MSG(errno == ENOTTY, "ioctl(FIOSSHMLPGCNF) returned %d",
1308 	    errno);
1309 	ATF_REQUIRE(close(fd) == 0);
1310 
1311 	/*
1312 	 * Create a largepage object and try to use it without actually
1313 	 * configuring anything.
1314 	 */
1315 	fd = __sys_shm_open2(SHM_ANON, O_CREAT | O_RDWR, 0, SHM_LARGEPAGE,
1316 	    NULL);
1317 	if (fd < 0 && errno == ENOTTY)
1318 		atf_tc_skip("no large page support");
1319 	ATF_REQUIRE_MSG(fd >= 0, "shm_open2 failed; error=%d", errno);
1320 
1321 	error = ftruncate(fd, ps[1]);
1322 	ATF_REQUIRE(error != 0);
1323 	ATF_REQUIRE_MSG(errno == EINVAL, "ftruncate returned %d", errno);
1324 
1325 	addr = mmap(NULL, ps[1], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1326 	ATF_REQUIRE(addr == MAP_FAILED);
1327 	ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno);
1328 	addr = mmap(NULL, 0, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1329 	ATF_REQUIRE(addr == MAP_FAILED);
1330 	ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno);
1331 
1332 	buf = calloc(1, ps[0]);
1333 	ATF_REQUIRE(buf != NULL);
1334 	ATF_REQUIRE(write(fd, buf, ps[0]) == -1);
1335 	ATF_REQUIRE_MSG(errno == EINVAL, "write returned %d", errno);
1336 	free(buf);
1337 	buf = calloc(1, ps[1]);
1338 	ATF_REQUIRE(buf != NULL);
1339 	ATF_REQUIRE(write(fd, buf, ps[1]) == -1);
1340 	ATF_REQUIRE_MSG(errno == EINVAL, "write returned %d", errno);
1341 	free(buf);
1342 
1343 	error = posix_fallocate(fd, 0, ps[0]);
1344 	ATF_REQUIRE_MSG(error == EINVAL, "posix_fallocate returned %d", error);
1345 
1346 	ATF_REQUIRE(close(fd) == 0);
1347 }
1348 
1349 ATF_TC_WITHOUT_HEAD(largepage_mmap);
1350 ATF_TC_BODY(largepage_mmap, tc)
1351 {
1352 	char *addr, *addr1, *vec;
1353 	size_t ps[MAXPAGESIZES];
1354 	int fd, pscnt;
1355 
1356 	pscnt = pagesizes(ps);
1357 	for (int i = 1; i < pscnt; i++) {
1358 		fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
1359 
1360 		/* For mincore(). */
1361 		vec = malloc(ps[i]);
1362 		ATF_REQUIRE(vec != NULL);
1363 
1364 		/*
1365 		 * Wrong mapping size.
1366 		 */
1367 		addr = mmap(NULL, ps[i - 1], PROT_READ | PROT_WRITE, MAP_SHARED,
1368 		    fd, 0);
1369 		ATF_REQUIRE_MSG(addr == MAP_FAILED,
1370 		    "mmap(%zu bytes) succeeded", ps[i - 1]);
1371 		ATF_REQUIRE_MSG(errno == EINVAL,
1372 		    "mmap(%zu bytes) failed; error=%d", ps[i - 1], errno);
1373 
1374 		/*
1375 		 * Fixed mappings.
1376 		 */
1377 		addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1378 		    0);
1379 		ATF_REQUIRE_MSG(addr != MAP_FAILED,
1380 		    "mmap(%zu bytes) failed; errno=%d", ps[i], errno);
1381 		ATF_REQUIRE_MSG(((uintptr_t)addr & (ps[i] - 1)) == 0,
1382 		    "mmap(%zu bytes) returned unaligned mapping; addr=%p",
1383 		    ps[i], addr);
1384 
1385 		/* Try mapping a small page with anonymous memory. */
1386 		addr1 = mmap(addr, ps[i - 1], PROT_READ | PROT_WRITE,
1387 		    MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1388 		ATF_REQUIRE_MSG(addr1 == MAP_FAILED,
1389 		    "anon mmap(%zu bytes) succeeded", ps[i - 1]);
1390 		ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno);
1391 
1392 		/* Check MAP_EXCL when creating a second largepage mapping. */
1393 		addr1 = mmap(addr, ps[i], PROT_READ | PROT_WRITE,
1394 		    MAP_SHARED | MAP_FIXED | MAP_EXCL, fd, 0);
1395 		ATF_REQUIRE_MSG(addr1 == MAP_FAILED,
1396 		    "mmap(%zu bytes) succeeded", ps[i]);
1397 		/* XXX wrong errno */
1398 		ATF_REQUIRE_MSG(errno == ENOSPC, "mmap returned %d", errno);
1399 
1400 		/* Overwrite a largepage mapping with a lagepage mapping. */
1401 		addr1 = mmap(addr, ps[i], PROT_READ | PROT_WRITE,
1402 		    MAP_SHARED | MAP_FIXED, fd, 0);
1403 		ATF_REQUIRE_MSG(addr1 != MAP_FAILED,
1404 		    "mmap(%zu bytes) failed; errno=%d", ps[i], errno);
1405 		ATF_REQUIRE_MSG(addr == addr1,
1406 		    "mmap(%zu bytes) moved from %p to %p", ps[i], addr, addr1);
1407 
1408 		ATF_REQUIRE(munmap(addr, ps[i] == 0));
1409 
1410 		/* Clobber an anonymous mapping with a superpage. */
1411 		addr1 = mmap(NULL, ps[0], PROT_READ | PROT_WRITE,
1412 		    MAP_ANON | MAP_PRIVATE | MAP_ALIGNED(ffsl(ps[i]) - 1), -1,
1413 		    0);
1414 		ATF_REQUIRE_MSG(addr1 != MAP_FAILED,
1415 		    "mmap failed; error=%d", errno);
1416 		*(volatile char *)addr1 = '\0';
1417 		addr = mmap(addr1, ps[i], PROT_READ | PROT_WRITE,
1418 		    MAP_SHARED | MAP_FIXED, fd, 0);
1419 		ATF_REQUIRE_MSG(addr != MAP_FAILED,
1420 		    "mmap failed; error=%d", errno);
1421 		ATF_REQUIRE_MSG(addr == addr1,
1422 		    "mmap disobeyed MAP_FIXED, %p %p", addr, addr1);
1423 		*(volatile char *)addr = 0; /* fault */
1424 		ATF_REQUIRE(mincore(addr, ps[i], vec) == 0);
1425 		for (size_t p = 0; p < ps[i] / ps[0]; p++) {
1426 			ATF_REQUIRE_MSG((vec[p] & MINCORE_INCORE) != 0,
1427 			    "page %zu is not resident", p);
1428 			ATF_REQUIRE_MSG((vec[p] & MINCORE_SUPER) ==
1429 			    MINCORE_PSIND(i),
1430 			    "page %zu is not resident", p);
1431 		}
1432 
1433 		/*
1434 		 * Copy-on-write mappings are not permitted.
1435 		 */
1436 		addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_PRIVATE,
1437 		    fd, 0);
1438 		ATF_REQUIRE_MSG(addr == MAP_FAILED,
1439 		    "mmap(%zu bytes) succeeded", ps[i]);
1440 
1441 		ATF_REQUIRE(close(fd) == 0);
1442 	}
1443 }
1444 
1445 ATF_TC_WITHOUT_HEAD(largepage_munmap);
1446 ATF_TC_BODY(largepage_munmap, tc)
1447 {
1448 	char *addr;
1449 	size_t ps[MAXPAGESIZES], ps1;
1450 	int fd, pscnt;
1451 
1452 	pscnt = pagesizes(ps);
1453 	for (int i = 1; i < pscnt; i++) {
1454 		fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
1455 		ps1 = ps[i - 1];
1456 
1457 		addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1458 		    0);
1459 		ATF_REQUIRE_MSG(addr != MAP_FAILED,
1460 		    "mmap(%zu bytes) failed; errno=%d", ps[i], errno);
1461 
1462 		/* Try several unaligned munmap() requests. */
1463 		ATF_REQUIRE(munmap(addr, ps1) != 0);
1464 		ATF_REQUIRE_MSG(errno == EINVAL,
1465 		    "unexpected error %d from munmap", errno);
1466 		ATF_REQUIRE(munmap(addr, ps[i] - ps1));
1467 		ATF_REQUIRE_MSG(errno == EINVAL,
1468 		    "unexpected error %d from munmap", errno);
1469 		ATF_REQUIRE(munmap(addr + ps1, ps1) != 0);
1470 		ATF_REQUIRE_MSG(errno == EINVAL,
1471 		    "unexpected error %d from munmap", errno);
1472 		ATF_REQUIRE(munmap(addr, 0));
1473 		ATF_REQUIRE_MSG(errno == EINVAL,
1474 		    "unexpected error %d from munmap", errno);
1475 
1476 		ATF_REQUIRE(munmap(addr, ps[i]) == 0);
1477 		ATF_REQUIRE(close(fd) == 0);
1478 	}
1479 }
1480 
1481 static void
1482 largepage_madvise(char *addr, size_t sz, int advice, int error)
1483 {
1484 	if (error == 0) {
1485 		ATF_REQUIRE_MSG(madvise(addr, sz, advice) == 0,
1486 		    "madvise(%zu, %d) failed; error=%d", sz, advice, errno);
1487 	} else {
1488 		ATF_REQUIRE_MSG(madvise(addr, sz, advice) != 0,
1489 		    "madvise(%zu, %d) succeeded", sz, advice);
1490 		ATF_REQUIRE_MSG(errno == error,
1491 		    "unexpected error %d from madvise(%zu, %d)",
1492 		    errno, sz, advice);
1493 	}
1494 }
1495 
1496 ATF_TC_WITHOUT_HEAD(largepage_madvise);
1497 ATF_TC_BODY(largepage_madvise, tc)
1498 {
1499 	char *addr;
1500 	size_t ps[MAXPAGESIZES];
1501 	int fd, pscnt;
1502 
1503 	pscnt = pagesizes(ps);
1504 	for (int i = 1; i < pscnt; i++) {
1505 		fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
1506 		addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1507 		    0);
1508 		ATF_REQUIRE_MSG(addr != MAP_FAILED,
1509 		    "mmap(%zu bytes) failed; error=%d", ps[i], errno);
1510 
1511 		memset(addr, 0, ps[i]);
1512 
1513 		/* Advice that requires clipping. */
1514 		largepage_madvise(addr, ps[0], MADV_NORMAL, EINVAL);
1515 		largepage_madvise(addr, ps[i], MADV_NORMAL, 0);
1516 		largepage_madvise(addr, ps[0], MADV_RANDOM, EINVAL);
1517 		largepage_madvise(addr, ps[i], MADV_RANDOM, 0);
1518 		largepage_madvise(addr, ps[0], MADV_SEQUENTIAL, EINVAL);
1519 		largepage_madvise(addr, ps[i], MADV_SEQUENTIAL, 0);
1520 		largepage_madvise(addr, ps[0], MADV_NOSYNC, EINVAL);
1521 		largepage_madvise(addr, ps[i], MADV_NOSYNC, 0);
1522 		largepage_madvise(addr, ps[0], MADV_AUTOSYNC, EINVAL);
1523 		largepage_madvise(addr, ps[i], MADV_AUTOSYNC, 0);
1524 		largepage_madvise(addr, ps[0], MADV_CORE, EINVAL);
1525 		largepage_madvise(addr, ps[i], MADV_CORE, 0);
1526 		largepage_madvise(addr, ps[0], MADV_NOCORE, EINVAL);
1527 		largepage_madvise(addr, ps[i], MADV_NOCORE, 0);
1528 
1529 		/* Advice that does not result in clipping. */
1530 		largepage_madvise(addr, ps[0], MADV_DONTNEED, 0);
1531 		largepage_madvise(addr, ps[i], MADV_DONTNEED, 0);
1532 		largepage_madvise(addr, ps[0], MADV_WILLNEED, 0);
1533 		largepage_madvise(addr, ps[i], MADV_WILLNEED, 0);
1534 		largepage_madvise(addr, ps[0], MADV_FREE, 0);
1535 		largepage_madvise(addr, ps[i], MADV_FREE, 0);
1536 
1537 		ATF_REQUIRE(munmap(addr, ps[i]) == 0);
1538 		ATF_REQUIRE(close(fd) == 0);
1539 	}
1540 }
1541 
1542 ATF_TC(largepage_mlock);
1543 ATF_TC_HEAD(largepage_mlock, tc)
1544 {
1545 	/* Needed to set rlimit. */
1546 	atf_tc_set_md_var(tc, "require.user", "root");
1547 }
1548 ATF_TC_BODY(largepage_mlock, tc)
1549 {
1550 	struct rlimit rl;
1551 	char *addr;
1552 	size_t ps[MAXPAGESIZES], sz;
1553 	u_long max_wired, wired;
1554 	int fd, error, pscnt;
1555 
1556 	rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
1557 	ATF_REQUIRE_MSG(setrlimit(RLIMIT_MEMLOCK, &rl) == 0,
1558 	    "setrlimit failed; error=%d", errno);
1559 
1560 	sz = sizeof(max_wired);
1561 	error = sysctlbyname("vm.max_user_wired", &max_wired, &sz, NULL, 0);
1562 	ATF_REQUIRE_MSG(error == 0,
1563 	    "sysctlbyname(vm.max_user_wired) failed; error=%d", errno);
1564 
1565 	sz = sizeof(wired);
1566 	error = sysctlbyname("vm.stats.vm.v_user_wire_count", &wired, &sz, NULL,
1567 	    0);
1568 	ATF_REQUIRE_MSG(error == 0,
1569 	    "sysctlbyname(vm.stats.vm.v_user_wire_count) failed; error=%d",
1570 	    errno);
1571 
1572 	pscnt = pagesizes(ps);
1573 	for (int i = 1; i < pscnt; i++) {
1574 		if (ps[i] / ps[0] > max_wired - wired) {
1575 			/* Cannot wire past the limit. */
1576 			atf_tc_skip("test would exceed wiring limit");
1577 		}
1578 
1579 		fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
1580 		addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1581 		    0);
1582 		ATF_REQUIRE_MSG(addr != MAP_FAILED,
1583 		    "mmap(%zu bytes) failed; error=%d", ps[i], errno);
1584 
1585 		ATF_REQUIRE(mlock(addr, ps[0]) != 0);
1586 		ATF_REQUIRE_MSG(errno == EINVAL,
1587 		    "unexpected error %d from mlock(%zu bytes)", errno, ps[i]);
1588 		ATF_REQUIRE(mlock(addr, ps[i] - ps[0]) != 0);
1589 		ATF_REQUIRE_MSG(errno == EINVAL,
1590 		    "unexpected error %d from mlock(%zu bytes)", errno, ps[i]);
1591 
1592 		ATF_REQUIRE_MSG(mlock(addr, ps[i]) == 0,
1593 		    "mlock failed; error=%d", errno);
1594 
1595 		ATF_REQUIRE(munmap(addr, ps[i]) == 0);
1596 
1597 		ATF_REQUIRE(mlockall(MCL_FUTURE) == 0);
1598 		addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1599 		    0);
1600 		ATF_REQUIRE_MSG(addr != MAP_FAILED,
1601 		    "mmap(%zu bytes) failed; error=%d", ps[i], errno);
1602 
1603 		ATF_REQUIRE(munmap(addr, ps[i]) == 0);
1604 		ATF_REQUIRE(close(fd) == 0);
1605 	}
1606 }
1607 
1608 ATF_TC_WITHOUT_HEAD(largepage_msync);
1609 ATF_TC_BODY(largepage_msync, tc)
1610 {
1611 	char *addr;
1612 	size_t ps[MAXPAGESIZES];
1613 	int fd, pscnt;
1614 
1615 	pscnt = pagesizes(ps);
1616 	for (int i = 1; i < pscnt; i++) {
1617 		fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
1618 		addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1619 		    0);
1620 		ATF_REQUIRE_MSG(addr != MAP_FAILED,
1621 		    "mmap(%zu bytes) failed; error=%d", ps[i], errno);
1622 
1623 		memset(addr, 0, ps[i]);
1624 
1625 		/*
1626 		 * "Sync" requests are no-ops for SHM objects, so small
1627 		 * PAGE_SIZE-sized requests succeed.
1628 		 */
1629 		ATF_REQUIRE_MSG(msync(addr, ps[0], MS_ASYNC) == 0,
1630 		    "msync(MS_ASYNC) failed; error=%d", errno);
1631 		ATF_REQUIRE_MSG(msync(addr, ps[i], MS_ASYNC) == 0,
1632 		    "msync(MS_ASYNC) failed; error=%d", errno);
1633 		ATF_REQUIRE_MSG(msync(addr, ps[0], MS_SYNC) == 0,
1634 		    "msync(MS_SYNC) failed; error=%d", errno);
1635 		ATF_REQUIRE_MSG(msync(addr, ps[i], MS_SYNC) == 0,
1636 		    "msync(MS_SYNC) failed; error=%d", errno);
1637 
1638 		ATF_REQUIRE_MSG(msync(addr, ps[0], MS_INVALIDATE) != 0,
1639 		    "msync(MS_INVALIDATE) succeeded");
1640 		/* XXX wrong errno */
1641 		ATF_REQUIRE_MSG(errno == EBUSY,
1642 		    "unexpected error %d from msync(MS_INVALIDATE)", errno);
1643 		ATF_REQUIRE_MSG(msync(addr, ps[i], MS_INVALIDATE) == 0,
1644 		    "msync(MS_INVALIDATE) failed; error=%d", errno);
1645 		memset(addr, 0, ps[i]);
1646 
1647 		ATF_REQUIRE(munmap(addr, ps[i]) == 0);
1648 		ATF_REQUIRE(close(fd) == 0);
1649 	}
1650 }
1651 
1652 static void
1653 largepage_protect(char *addr, size_t sz, int prot, int error)
1654 {
1655 	if (error == 0) {
1656 		ATF_REQUIRE_MSG(mprotect(addr, sz, prot) == 0,
1657 		    "mprotect(%zu, %x) failed; error=%d", sz, prot, errno);
1658 	} else {
1659 		ATF_REQUIRE_MSG(mprotect(addr, sz, prot) != 0,
1660 		    "mprotect(%zu, %x) succeeded", sz, prot);
1661 		ATF_REQUIRE_MSG(errno == error,
1662 		    "unexpected error %d from mprotect(%zu, %x)",
1663 		    errno, sz, prot);
1664 	}
1665 }
1666 
1667 ATF_TC_WITHOUT_HEAD(largepage_mprotect);
1668 ATF_TC_BODY(largepage_mprotect, tc)
1669 {
1670 	char *addr, *addr1;
1671 	size_t ps[MAXPAGESIZES];
1672 	int fd, pscnt;
1673 
1674 	pscnt = pagesizes(ps);
1675 	for (int i = 1; i < pscnt; i++) {
1676 		/*
1677 		 * Reserve a contiguous region in the address space to avoid
1678 		 * spurious failures in the face of ASLR.
1679 		 */
1680 		addr = mmap(NULL, ps[i] * 2, PROT_NONE,
1681 		    MAP_ANON | MAP_ALIGNED(ffsl(ps[i]) - 1), -1, 0);
1682 		ATF_REQUIRE_MSG(addr != MAP_FAILED,
1683 		    "mmap(%zu bytes) failed; error=%d", ps[i], errno);
1684 		ATF_REQUIRE(munmap(addr, ps[i] * 2) == 0);
1685 
1686 		fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
1687 		addr = mmap(addr, ps[i], PROT_READ | PROT_WRITE,
1688 		    MAP_SHARED | MAP_FIXED, fd, 0);
1689 		ATF_REQUIRE_MSG(addr != MAP_FAILED,
1690 		    "mmap(%zu bytes) failed; error=%d", ps[i], errno);
1691 
1692 		/*
1693 		 * These should be no-ops from the pmap perspective since the
1694 		 * page is not yet entered into the pmap.
1695 		 */
1696 		largepage_protect(addr, ps[0], PROT_READ, EINVAL);
1697 		largepage_protect(addr, ps[i], PROT_READ, 0);
1698 		largepage_protect(addr, ps[0], PROT_NONE, EINVAL);
1699 		largepage_protect(addr, ps[i], PROT_NONE, 0);
1700 		largepage_protect(addr, ps[0],
1701 		    PROT_READ | PROT_WRITE | PROT_EXEC, EINVAL);
1702 		largepage_protect(addr, ps[i],
1703 		    PROT_READ | PROT_WRITE | PROT_EXEC, 0);
1704 
1705 		/* Trigger creation of a mapping and try again. */
1706 		*(volatile char *)addr = 0;
1707 		largepage_protect(addr, ps[0], PROT_READ, EINVAL);
1708 		largepage_protect(addr, ps[i], PROT_READ, 0);
1709 		largepage_protect(addr, ps[0], PROT_NONE, EINVAL);
1710 		largepage_protect(addr, ps[i], PROT_NONE, 0);
1711 		largepage_protect(addr, ps[0],
1712 		    PROT_READ | PROT_WRITE | PROT_EXEC, EINVAL);
1713 		largepage_protect(addr, ps[i],
1714 		    PROT_READ | PROT_WRITE | PROT_EXEC, 0);
1715 
1716 		memset(addr, 0, ps[i]);
1717 
1718 		/* Map two contiguous large pages and merge map entries. */
1719 		addr1 = mmap(addr + ps[i], ps[i], PROT_READ | PROT_WRITE,
1720 		    MAP_SHARED | MAP_FIXED | MAP_EXCL, fd, 0);
1721 		ATF_REQUIRE_MSG(addr1 != MAP_FAILED,
1722 		    "mmap(%zu bytes) failed; error=%d", ps[i], errno);
1723 
1724 		largepage_protect(addr1 - ps[0], ps[0] * 2,
1725 		    PROT_READ | PROT_WRITE, EINVAL);
1726 		largepage_protect(addr, ps[i] * 2, PROT_READ | PROT_WRITE, 0);
1727 
1728 		memset(addr, 0, ps[i] * 2);
1729 
1730 		ATF_REQUIRE(munmap(addr, ps[i]) == 0);
1731 		ATF_REQUIRE(munmap(addr1, ps[i]) == 0);
1732 		ATF_REQUIRE(close(fd) == 0);
1733 	}
1734 }
1735 
1736 ATF_TC_WITHOUT_HEAD(largepage_minherit);
1737 ATF_TC_BODY(largepage_minherit, tc)
1738 {
1739 	char *addr;
1740 	size_t ps[MAXPAGESIZES];
1741 	pid_t child;
1742 	int fd, pscnt, status;
1743 
1744 	pscnt = pagesizes(ps);
1745 	for (int i = 1; i < pscnt; i++) {
1746 		fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
1747 		addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1748 		    0);
1749 		ATF_REQUIRE_MSG(addr != MAP_FAILED,
1750 		    "mmap(%zu bytes) failed; error=%d", ps[i], errno);
1751 
1752 		ATF_REQUIRE(minherit(addr, ps[0], INHERIT_SHARE) != 0);
1753 
1754 		ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_SHARE) == 0,
1755 		    "minherit(%zu bytes) failed; error=%d", ps[i], errno);
1756 		child = fork();
1757 		ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno);
1758 		if (child == 0) {
1759 			char v;
1760 
1761 			*(volatile char *)addr = 0;
1762 			if (mincore(addr, ps[0], &v) != 0)
1763 				_exit(1);
1764 			if ((v & MINCORE_SUPER) == 0)
1765 				_exit(2);
1766 			_exit(0);
1767 		}
1768 		ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child,
1769 		    "waitpid failed; error=%d", errno);
1770 		ATF_REQUIRE_MSG(WIFEXITED(status),
1771 		    "child was killed by signal %d", WTERMSIG(status));
1772 		ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0,
1773 		    "child exited with status %d", WEXITSTATUS(status));
1774 
1775 		ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_NONE) == 0,
1776 		    "minherit(%zu bytes) failed; error=%d", ps[i], errno);
1777 		child = fork();
1778 		ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno);
1779 		if (child == 0) {
1780 			char v;
1781 
1782 			if (mincore(addr, ps[0], &v) == 0)
1783 				_exit(1);
1784 			_exit(0);
1785 		}
1786 		ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child,
1787 		    "waitpid failed; error=%d", errno);
1788 		ATF_REQUIRE_MSG(WIFEXITED(status),
1789 		    "child was killed by signal %d", WTERMSIG(status));
1790 		ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0,
1791 		    "child exited with status %d", WEXITSTATUS(status));
1792 
1793 		/* Copy-on-write is not supported for static large pages. */
1794 		ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_COPY) != 0,
1795 		    "minherit(%zu bytes) succeeded", ps[i]);
1796 
1797 		ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_ZERO) == 0,
1798 		    "minherit(%zu bytes) failed; error=%d", ps[i], errno);
1799 		child = fork();
1800 		ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno);
1801 		if (child == 0) {
1802 			char v;
1803 
1804 			*(volatile char *)addr = 0;
1805 			if (mincore(addr, ps[0], &v) != 0)
1806 				_exit(1);
1807 			if ((v & MINCORE_SUPER) != 0)
1808 				_exit(2);
1809 			_exit(0);
1810 		}
1811 		ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child,
1812 		    "waitpid failed; error=%d", errno);
1813 		ATF_REQUIRE_MSG(WIFEXITED(status),
1814 		    "child was killed by signal %d", WTERMSIG(status));
1815 		ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0,
1816 		    "child exited with status %d", WEXITSTATUS(status));
1817 
1818 		ATF_REQUIRE(munmap(addr, ps[i]) == 0);
1819 		ATF_REQUIRE(close(fd) == 0);
1820 	}
1821 }
1822 
1823 ATF_TC_WITHOUT_HEAD(largepage_pipe);
1824 ATF_TC_BODY(largepage_pipe, tc)
1825 {
1826 	size_t ps[MAXPAGESIZES];
1827 	char *addr;
1828 	ssize_t len;
1829 	int fd, pfd[2], pscnt, status;
1830 	pid_t child;
1831 
1832 	pscnt = pagesizes(ps);
1833 
1834 	for (int i = 1; i < pscnt; i++) {
1835 		fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
1836 		addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1837 		    0);
1838 		ATF_REQUIRE_MSG(addr != MAP_FAILED,
1839 		    "mmap(%zu bytes) failed; error=%d", ps[i], errno);
1840 
1841 		/* Trigger creation of a mapping. */
1842 		*(volatile char *)addr = '\0';
1843 
1844 		ATF_REQUIRE(pipe(pfd) == 0);
1845 		child = fork();
1846 		ATF_REQUIRE_MSG(child != -1, "fork() failed; error=%d", errno);
1847 		if (child == 0) {
1848 			char buf[BUFSIZ];
1849 			ssize_t resid;
1850 
1851 			(void)close(pfd[0]);
1852 			for (resid = (size_t)ps[i]; resid > 0; resid -= len) {
1853 				len = read(pfd[1], buf, sizeof(buf));
1854 				if (len < 0)
1855 					_exit(1);
1856 			}
1857 			_exit(0);
1858 		}
1859 		ATF_REQUIRE(close(pfd[1]) == 0);
1860 		len = write(pfd[0], addr, ps[i]);
1861 		ATF_REQUIRE_MSG(len >= 0, "write() failed; error=%d", errno);
1862 		ATF_REQUIRE_MSG(len == (ssize_t)ps[i],
1863 		    "short write; len=%zd", len);
1864 		ATF_REQUIRE(close(pfd[0]) == 0);
1865 
1866 		ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child,
1867 		    "waitpid() failed; error=%d", errno);
1868 		ATF_REQUIRE_MSG(WIFEXITED(status),
1869 		    "child was killed by signal %d", WTERMSIG(status));
1870 		ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0,
1871 		    "child exited with status %d", WEXITSTATUS(status));
1872 
1873 		ATF_REQUIRE(munmap(addr, ps[i]) == 0);
1874 		ATF_REQUIRE(close(fd) == 0);
1875 	}
1876 }
1877 
1878 ATF_TC_WITHOUT_HEAD(largepage_reopen);
1879 ATF_TC_BODY(largepage_reopen, tc)
1880 {
1881 	char *addr, *vec;
1882 	size_t ps[MAXPAGESIZES];
1883 	int fd, psind;
1884 
1885 	(void)pagesizes(ps);
1886 	psind = 1;
1887 
1888 	gen_test_path();
1889 	fd = shm_create_largepage(test_path, O_CREAT | O_RDWR, psind,
1890 	    SHM_LARGEPAGE_ALLOC_DEFAULT, 0600);
1891 	if (fd < 0 && errno == ENOTTY)
1892 		atf_tc_skip("no large page support");
1893 	ATF_REQUIRE_MSG(fd >= 0, "shm_create_largepage failed; error=%d", errno);
1894 
1895 	ATF_REQUIRE_MSG(ftruncate(fd, ps[psind]) == 0,
1896 	    "ftruncate failed; error=%d", errno);
1897 
1898 	ATF_REQUIRE_MSG(close(fd) == 0, "close failed; error=%d", errno);
1899 
1900 	fd = shm_open(test_path, O_RDWR, 0);
1901 	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; error=%d", errno);
1902 
1903 	addr = mmap(NULL, ps[psind], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1904 	ATF_REQUIRE_MSG(addr != MAP_FAILED, "mmap failed; error=%d", errno);
1905 
1906 	/* Trigger a fault and mapping creation. */
1907 	*(volatile char *)addr = 0;
1908 
1909 	vec = malloc(ps[psind] / ps[0]);
1910 	ATF_REQUIRE(vec != NULL);
1911 	ATF_REQUIRE_MSG(mincore(addr, ps[psind], vec) == 0,
1912 	    "mincore failed; error=%d", errno);
1913 	ATF_REQUIRE_MSG((vec[0] & MINCORE_SUPER) == MINCORE_PSIND(psind),
1914 	    "page not mapped into a %zu-byte superpage", ps[psind]);
1915 
1916 	ATF_REQUIRE_MSG(shm_unlink(test_path) == 0,
1917 	    "shm_unlink failed; errno=%d", errno);
1918 	ATF_REQUIRE_MSG(close(fd) == 0,
1919 	    "close failed; errno=%d", errno);
1920 }
1921 
1922 ATF_TP_ADD_TCS(tp)
1923 {
1924 
1925 	ATF_TP_ADD_TC(tp, remap_object);
1926 	ATF_TP_ADD_TC(tp, rename_from_anon);
1927 	ATF_TP_ADD_TC(tp, rename_bad_path_pointer);
1928 	ATF_TP_ADD_TC(tp, rename_from_nonexisting);
1929 	ATF_TP_ADD_TC(tp, rename_to_anon);
1930 	ATF_TP_ADD_TC(tp, rename_to_replace);
1931 	ATF_TP_ADD_TC(tp, rename_to_noreplace);
1932 	ATF_TP_ADD_TC(tp, rename_to_exchange);
1933 	ATF_TP_ADD_TC(tp, rename_to_exchange_nonexisting);
1934 	ATF_TP_ADD_TC(tp, rename_to_self);
1935 	ATF_TP_ADD_TC(tp, rename_bad_flag);
1936 	ATF_TP_ADD_TC(tp, reopen_object);
1937 	ATF_TP_ADD_TC(tp, readonly_mmap_write);
1938 	ATF_TP_ADD_TC(tp, open_after_link);
1939 	ATF_TP_ADD_TC(tp, open_invalid_path);
1940 	ATF_TP_ADD_TC(tp, open_write_only);
1941 	ATF_TP_ADD_TC(tp, open_extra_flags);
1942 	ATF_TP_ADD_TC(tp, open_anon);
1943 	ATF_TP_ADD_TC(tp, open_anon_readonly);
1944 	ATF_TP_ADD_TC(tp, open_bad_path_pointer);
1945 	ATF_TP_ADD_TC(tp, open_path_too_long);
1946 	ATF_TP_ADD_TC(tp, open_nonexisting_object);
1947 	ATF_TP_ADD_TC(tp, open_create_existing_object);
1948 	ATF_TP_ADD_TC(tp, shm_functionality_across_fork);
1949 	ATF_TP_ADD_TC(tp, trunc_resets_object);
1950 	ATF_TP_ADD_TC(tp, unlink_bad_path_pointer);
1951 	ATF_TP_ADD_TC(tp, unlink_path_too_long);
1952 	ATF_TP_ADD_TC(tp, object_resize);
1953 	ATF_TP_ADD_TC(tp, cloexec);
1954 	ATF_TP_ADD_TC(tp, mode);
1955 	ATF_TP_ADD_TC(tp, fallocate);
1956 	ATF_TP_ADD_TC(tp, fspacectl);
1957 	ATF_TP_ADD_TC(tp, accounting);
1958 	ATF_TP_ADD_TC(tp, largepage_basic);
1959 	ATF_TP_ADD_TC(tp, largepage_config);
1960 	ATF_TP_ADD_TC(tp, largepage_mmap);
1961 	ATF_TP_ADD_TC(tp, largepage_munmap);
1962 	ATF_TP_ADD_TC(tp, largepage_madvise);
1963 	ATF_TP_ADD_TC(tp, largepage_mlock);
1964 	ATF_TP_ADD_TC(tp, largepage_msync);
1965 	ATF_TP_ADD_TC(tp, largepage_mprotect);
1966 	ATF_TP_ADD_TC(tp, largepage_minherit);
1967 	ATF_TP_ADD_TC(tp, largepage_pipe);
1968 	ATF_TP_ADD_TC(tp, largepage_reopen);
1969 
1970 	return (atf_no_error());
1971 }
1972