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