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