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