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