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", errno); 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", errno); 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", errno); 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", errno); 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", errno); 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", errno); 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, pscnt; 1255 1256 pscnt = pagesizes(ps); 1257 1258 fd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0); 1259 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; error=%d", errno); 1260 1261 /* 1262 * Configure a large page policy for an object created without 1263 * SHM_LARGEPAGE. 1264 */ 1265 lpc.psind = 1; 1266 lpc.alloc_policy = SHM_LARGEPAGE_ALLOC_DEFAULT; 1267 error = ioctl(fd, FIOSSHMLPGCNF, &lpc); 1268 ATF_REQUIRE(error != 0); 1269 ATF_REQUIRE_MSG(errno == ENOTTY, "ioctl(FIOSSHMLPGCNF) returned %d", 1270 errno); 1271 ATF_REQUIRE(close(fd) == 0); 1272 1273 /* 1274 * Create a largepage object and try to use it without actually 1275 * configuring anything. 1276 */ 1277 fd = __sys_shm_open2(SHM_ANON, O_CREAT | O_RDWR, 0, SHM_LARGEPAGE, 1278 NULL); 1279 if (fd < 0 && errno == ENOTTY) 1280 atf_tc_skip("no large page support"); 1281 ATF_REQUIRE_MSG(fd >= 0, "shm_open2 failed; error=%d", errno); 1282 1283 error = ftruncate(fd, ps[1]); 1284 ATF_REQUIRE(error != 0); 1285 ATF_REQUIRE_MSG(errno == EINVAL, "ftruncate returned %d", errno); 1286 1287 addr = mmap(NULL, ps[1], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1288 ATF_REQUIRE(addr == MAP_FAILED); 1289 ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno); 1290 addr = mmap(NULL, 0, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1291 ATF_REQUIRE(addr == MAP_FAILED); 1292 ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno); 1293 1294 buf = calloc(1, PAGE_SIZE); 1295 ATF_REQUIRE(buf != NULL); 1296 ATF_REQUIRE(write(fd, buf, PAGE_SIZE) == -1); 1297 ATF_REQUIRE_MSG(errno == EINVAL, "write returned %d", errno); 1298 free(buf); 1299 buf = calloc(1, ps[1]); 1300 ATF_REQUIRE(buf != NULL); 1301 ATF_REQUIRE(write(fd, buf, ps[1]) == -1); 1302 ATF_REQUIRE_MSG(errno == EINVAL, "write returned %d", errno); 1303 free(buf); 1304 1305 error = posix_fallocate(fd, 0, PAGE_SIZE); 1306 ATF_REQUIRE_MSG(error == EINVAL, "posix_fallocate returned %d", error); 1307 1308 ATF_REQUIRE(close(fd) == 0); 1309 } 1310 1311 ATF_TC_WITHOUT_HEAD(largepage_mmap); 1312 ATF_TC_BODY(largepage_mmap, tc) 1313 { 1314 char *addr, *addr1, *vec; 1315 size_t ps[MAXPAGESIZES]; 1316 int fd, pscnt; 1317 1318 pscnt = pagesizes(ps); 1319 for (int i = 1; i < pscnt; i++) { 1320 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1321 1322 /* For mincore(). */ 1323 vec = malloc(ps[i]); 1324 ATF_REQUIRE(vec != NULL); 1325 1326 /* 1327 * Wrong mapping size. 1328 */ 1329 addr = mmap(NULL, ps[i - 1], PROT_READ | PROT_WRITE, MAP_SHARED, 1330 fd, 0); 1331 ATF_REQUIRE_MSG(addr == MAP_FAILED, 1332 "mmap(%zu bytes) succeeded", ps[i - 1]); 1333 ATF_REQUIRE_MSG(errno == EINVAL, 1334 "mmap(%zu bytes) failed; error=%d", ps[i - 1], errno); 1335 1336 /* 1337 * Fixed mappings. 1338 */ 1339 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1340 0); 1341 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1342 "mmap(%zu bytes) failed; errno=%d", ps[i], errno); 1343 ATF_REQUIRE_MSG(((uintptr_t)addr & (ps[i] - 1)) == 0, 1344 "mmap(%zu bytes) returned unaligned mapping; addr=%p", 1345 ps[i], addr); 1346 1347 /* Try mapping a small page with anonymous memory. */ 1348 addr1 = mmap(addr, ps[i - 1], PROT_READ | PROT_WRITE, 1349 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); 1350 ATF_REQUIRE_MSG(addr1 == MAP_FAILED, 1351 "anon mmap(%zu bytes) succeeded", ps[i - 1]); 1352 ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno); 1353 1354 /* Check MAP_EXCL when creating a second largepage mapping. */ 1355 addr1 = mmap(addr, ps[i], PROT_READ | PROT_WRITE, 1356 MAP_SHARED | MAP_FIXED | MAP_EXCL, fd, 0); 1357 ATF_REQUIRE_MSG(addr1 == MAP_FAILED, 1358 "mmap(%zu bytes) succeeded", ps[i]); 1359 /* XXX wrong errno */ 1360 ATF_REQUIRE_MSG(errno == ENOSPC, "mmap returned %d", errno); 1361 1362 /* Overwrite a largepage mapping with a lagepage mapping. */ 1363 addr1 = mmap(addr, ps[i], PROT_READ | PROT_WRITE, 1364 MAP_SHARED | MAP_FIXED, fd, 0); 1365 ATF_REQUIRE_MSG(addr1 != MAP_FAILED, 1366 "mmap(%zu bytes) failed; errno=%d", ps[i], errno); 1367 ATF_REQUIRE_MSG(addr == addr1, 1368 "mmap(%zu bytes) moved from %p to %p", ps[i], addr, addr1); 1369 1370 ATF_REQUIRE(munmap(addr, ps[i] == 0)); 1371 1372 /* Clobber an anonymous mapping with a superpage. */ 1373 addr1 = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, 1374 MAP_ANON | MAP_PRIVATE | MAP_ALIGNED(ffsl(ps[i]) - 1), -1, 1375 0); 1376 ATF_REQUIRE_MSG(addr1 != MAP_FAILED, 1377 "mmap failed; error=%d", errno); 1378 *(volatile char *)addr1 = '\0'; 1379 addr = mmap(addr1, ps[i], PROT_READ | PROT_WRITE, 1380 MAP_SHARED | MAP_FIXED, fd, 0); 1381 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1382 "mmap failed; error=%d", errno); 1383 ATF_REQUIRE_MSG(addr == addr1, 1384 "mmap disobeyed MAP_FIXED, %p %p", addr, addr1); 1385 *(volatile char *)addr = 0; /* fault */ 1386 ATF_REQUIRE(mincore(addr, ps[i], vec) == 0); 1387 for (size_t p = 0; p < ps[i] / PAGE_SIZE; p++) { 1388 ATF_REQUIRE_MSG((vec[p] & MINCORE_INCORE) != 0, 1389 "page %zu is not resident", p); 1390 ATF_REQUIRE_MSG((vec[p] & MINCORE_PSIND(i)) != 0, 1391 "page %zu is not resident", p); 1392 } 1393 1394 /* 1395 * Copy-on-write mappings are not permitted. 1396 */ 1397 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_PRIVATE, 1398 fd, 0); 1399 ATF_REQUIRE_MSG(addr == MAP_FAILED, 1400 "mmap(%zu bytes) succeeded", ps[i]); 1401 1402 ATF_REQUIRE(close(fd) == 0); 1403 } 1404 } 1405 1406 ATF_TC_WITHOUT_HEAD(largepage_munmap); 1407 ATF_TC_BODY(largepage_munmap, tc) 1408 { 1409 char *addr; 1410 size_t ps[MAXPAGESIZES], ps1; 1411 int fd, pscnt; 1412 1413 pscnt = pagesizes(ps); 1414 for (int i = 1; i < pscnt; i++) { 1415 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1416 ps1 = ps[i - 1]; 1417 1418 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1419 0); 1420 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1421 "mmap(%zu bytes) failed; errno=%d", ps[i], errno); 1422 1423 /* Try several unaligned munmap() requests. */ 1424 ATF_REQUIRE(munmap(addr, ps1) != 0); 1425 ATF_REQUIRE_MSG(errno == EINVAL, 1426 "unexpected error %d from munmap", errno); 1427 ATF_REQUIRE(munmap(addr, ps[i] - ps1)); 1428 ATF_REQUIRE_MSG(errno == EINVAL, 1429 "unexpected error %d from munmap", errno); 1430 ATF_REQUIRE(munmap(addr + ps1, ps1) != 0); 1431 ATF_REQUIRE_MSG(errno == EINVAL, 1432 "unexpected error %d from munmap", errno); 1433 ATF_REQUIRE(munmap(addr, 0)); 1434 ATF_REQUIRE_MSG(errno == EINVAL, 1435 "unexpected error %d from munmap", errno); 1436 1437 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1438 ATF_REQUIRE(close(fd) == 0); 1439 } 1440 } 1441 1442 static void 1443 largepage_madvise(char *addr, size_t sz, int advice, int error) 1444 { 1445 if (error == 0) { 1446 ATF_REQUIRE_MSG(madvise(addr, sz, advice) == 0, 1447 "madvise(%zu, %d) failed; error=%d", sz, advice, errno); 1448 } else { 1449 ATF_REQUIRE_MSG(madvise(addr, sz, advice) != 0, 1450 "madvise(%zu, %d) succeeded", sz, advice); 1451 ATF_REQUIRE_MSG(errno == error, 1452 "unexpected error %d from madvise(%zu, %d)", 1453 errno, sz, advice); 1454 } 1455 } 1456 1457 ATF_TC_WITHOUT_HEAD(largepage_madvise); 1458 ATF_TC_BODY(largepage_madvise, tc) 1459 { 1460 char *addr; 1461 size_t ps[MAXPAGESIZES]; 1462 int fd, pscnt; 1463 1464 pscnt = pagesizes(ps); 1465 for (int i = 1; i < pscnt; i++) { 1466 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1467 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1468 0); 1469 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1470 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1471 1472 /* Advice that requires clipping. */ 1473 largepage_madvise(addr, PAGE_SIZE, MADV_NORMAL, EINVAL); 1474 largepage_madvise(addr, ps[i], MADV_NORMAL, 0); 1475 largepage_madvise(addr, PAGE_SIZE, MADV_RANDOM, EINVAL); 1476 largepage_madvise(addr, ps[i], MADV_RANDOM, 0); 1477 largepage_madvise(addr, PAGE_SIZE, MADV_SEQUENTIAL, EINVAL); 1478 largepage_madvise(addr, ps[i], MADV_SEQUENTIAL, 0); 1479 largepage_madvise(addr, PAGE_SIZE, MADV_NOSYNC, EINVAL); 1480 largepage_madvise(addr, ps[i], MADV_NOSYNC, 0); 1481 largepage_madvise(addr, PAGE_SIZE, MADV_AUTOSYNC, EINVAL); 1482 largepage_madvise(addr, ps[i], MADV_AUTOSYNC, 0); 1483 largepage_madvise(addr, PAGE_SIZE, MADV_CORE, EINVAL); 1484 largepage_madvise(addr, ps[i], MADV_CORE, 0); 1485 largepage_madvise(addr, PAGE_SIZE, MADV_NOCORE, EINVAL); 1486 largepage_madvise(addr, ps[i], MADV_NOCORE, 0); 1487 1488 /* Advice that does not result in clipping. */ 1489 largepage_madvise(addr, PAGE_SIZE, MADV_DONTNEED, 0); 1490 largepage_madvise(addr, ps[i], MADV_DONTNEED, 0); 1491 largepage_madvise(addr, PAGE_SIZE, MADV_WILLNEED, 0); 1492 largepage_madvise(addr, ps[i], MADV_WILLNEED, 0); 1493 largepage_madvise(addr, PAGE_SIZE, MADV_FREE, 0); 1494 largepage_madvise(addr, ps[i], MADV_FREE, 0); 1495 1496 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1497 ATF_REQUIRE(close(fd) == 0); 1498 } 1499 } 1500 1501 ATF_TC(largepage_mlock); 1502 ATF_TC_HEAD(largepage_mlock, tc) 1503 { 1504 /* Needed to set rlimit. */ 1505 atf_tc_set_md_var(tc, "require.user", "root"); 1506 } 1507 ATF_TC_BODY(largepage_mlock, tc) 1508 { 1509 struct rlimit rl; 1510 char *addr; 1511 size_t ps[MAXPAGESIZES], sz; 1512 u_long max_wired, wired; 1513 int fd, error, pscnt; 1514 1515 rl.rlim_cur = rl.rlim_max = RLIM_INFINITY; 1516 ATF_REQUIRE_MSG(setrlimit(RLIMIT_MEMLOCK, &rl) == 0, 1517 "setrlimit failed; error=%d", errno); 1518 1519 sz = sizeof(max_wired); 1520 error = sysctlbyname("vm.max_user_wired", &max_wired, &sz, NULL, 0); 1521 ATF_REQUIRE_MSG(error == 0, 1522 "sysctlbyname(vm.max_user_wired) failed; error=%d", errno); 1523 1524 sz = sizeof(wired); 1525 error = sysctlbyname("vm.stats.vm.v_user_wire_count", &wired, &sz, NULL, 1526 0); 1527 ATF_REQUIRE_MSG(error == 0, 1528 "sysctlbyname(vm.stats.vm.v_user_wire_count) failed; error=%d", 1529 errno); 1530 1531 pscnt = pagesizes(ps); 1532 for (int i = 1; i < pscnt; i++) { 1533 if (ps[i] / PAGE_SIZE > max_wired - wired) { 1534 /* Cannot wire past the limit. */ 1535 atf_tc_skip("test would exceed wiring limit"); 1536 } 1537 1538 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1539 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1540 0); 1541 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1542 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1543 1544 ATF_REQUIRE(mlock(addr, PAGE_SIZE) != 0); 1545 ATF_REQUIRE_MSG(errno == EINVAL, 1546 "unexpected error %d from mlock(%zu bytes)", errno, ps[i]); 1547 ATF_REQUIRE(mlock(addr, ps[i] - PAGE_SIZE) != 0); 1548 ATF_REQUIRE_MSG(errno == EINVAL, 1549 "unexpected error %d from mlock(%zu bytes)", errno, ps[i]); 1550 1551 ATF_REQUIRE_MSG(mlock(addr, ps[i]) == 0, 1552 "mlock failed; error=%d", errno); 1553 1554 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1555 1556 ATF_REQUIRE(mlockall(MCL_FUTURE) == 0); 1557 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1558 0); 1559 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1560 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1561 1562 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1563 ATF_REQUIRE(close(fd) == 0); 1564 } 1565 } 1566 1567 ATF_TC_WITHOUT_HEAD(largepage_msync); 1568 ATF_TC_BODY(largepage_msync, tc) 1569 { 1570 char *addr; 1571 size_t ps[MAXPAGESIZES]; 1572 int fd, pscnt; 1573 1574 pscnt = pagesizes(ps); 1575 for (int i = 1; i < pscnt; i++) { 1576 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1577 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1578 0); 1579 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1580 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1581 1582 memset(addr, 0, ps[i]); 1583 1584 /* 1585 * "Sync" requests are no-ops for SHM objects, so small 1586 * PAGE_SIZE-sized requests succeed. 1587 */ 1588 ATF_REQUIRE_MSG(msync(addr, PAGE_SIZE, MS_ASYNC) == 0, 1589 "msync(MS_ASYNC) failed; error=%d", errno); 1590 ATF_REQUIRE_MSG(msync(addr, ps[i], MS_ASYNC) == 0, 1591 "msync(MS_ASYNC) failed; error=%d", errno); 1592 ATF_REQUIRE_MSG(msync(addr, PAGE_SIZE, MS_SYNC) == 0, 1593 "msync(MS_SYNC) failed; error=%d", errno); 1594 ATF_REQUIRE_MSG(msync(addr, ps[i], MS_SYNC) == 0, 1595 "msync(MS_SYNC) failed; error=%d", errno); 1596 1597 ATF_REQUIRE_MSG(msync(addr, PAGE_SIZE, MS_INVALIDATE) != 0, 1598 "msync(MS_INVALIDATE) succeeded"); 1599 /* XXX wrong errno */ 1600 ATF_REQUIRE_MSG(errno == EBUSY, 1601 "unexpected error %d from msync(MS_INVALIDATE)", errno); 1602 ATF_REQUIRE_MSG(msync(addr, ps[i], MS_INVALIDATE) == 0, 1603 "msync(MS_INVALIDATE) failed; error=%d", errno); 1604 memset(addr, 0, ps[i]); 1605 1606 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1607 ATF_REQUIRE(close(fd) == 0); 1608 } 1609 } 1610 1611 static void 1612 largepage_protect(char *addr, size_t sz, int prot, int error) 1613 { 1614 if (error == 0) { 1615 ATF_REQUIRE_MSG(mprotect(addr, sz, prot) == 0, 1616 "mprotect(%zu, %x) failed; error=%d", sz, prot, errno); 1617 } else { 1618 ATF_REQUIRE_MSG(mprotect(addr, sz, prot) != 0, 1619 "mprotect(%zu, %x) succeeded", sz, prot); 1620 ATF_REQUIRE_MSG(errno == error, 1621 "unexpected error %d from mprotect(%zu, %x)", 1622 errno, sz, prot); 1623 } 1624 } 1625 1626 ATF_TC_WITHOUT_HEAD(largepage_mprotect); 1627 ATF_TC_BODY(largepage_mprotect, tc) 1628 { 1629 char *addr, *addr1; 1630 size_t ps[MAXPAGESIZES]; 1631 int fd, pscnt; 1632 1633 pscnt = pagesizes(ps); 1634 for (int i = 1; i < pscnt; i++) { 1635 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1636 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1637 0); 1638 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1639 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1640 1641 /* 1642 * These should be no-ops from the pmap perspective since the 1643 * page is not yet entered into the pmap. 1644 */ 1645 largepage_protect(addr, PAGE_SIZE, PROT_READ, EINVAL); 1646 largepage_protect(addr, ps[i], PROT_READ, 0); 1647 largepage_protect(addr, PAGE_SIZE, PROT_NONE, EINVAL); 1648 largepage_protect(addr, ps[i], PROT_NONE, 0); 1649 largepage_protect(addr, PAGE_SIZE, 1650 PROT_READ | PROT_WRITE | PROT_EXEC, EINVAL); 1651 largepage_protect(addr, ps[i], 1652 PROT_READ | PROT_WRITE | PROT_EXEC, 0); 1653 1654 /* Trigger creation of a mapping and try again. */ 1655 *(volatile char *)addr = 0; 1656 largepage_protect(addr, PAGE_SIZE, PROT_READ, EINVAL); 1657 largepage_protect(addr, ps[i], PROT_READ, 0); 1658 largepage_protect(addr, PAGE_SIZE, PROT_NONE, EINVAL); 1659 largepage_protect(addr, ps[i], PROT_NONE, 0); 1660 largepage_protect(addr, PAGE_SIZE, 1661 PROT_READ | PROT_WRITE | PROT_EXEC, EINVAL); 1662 largepage_protect(addr, ps[i], 1663 PROT_READ | PROT_WRITE | PROT_EXEC, 0); 1664 1665 memset(addr, 0, ps[i]); 1666 1667 /* Map two contiguous large pages and merge map entries. */ 1668 addr1 = mmap(addr + ps[i], ps[i], PROT_READ | PROT_WRITE, 1669 MAP_SHARED | MAP_FIXED | MAP_EXCL, fd, 0); 1670 ATF_REQUIRE_MSG(addr1 != MAP_FAILED, 1671 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1672 1673 largepage_protect(addr1 - PAGE_SIZE, PAGE_SIZE * 2, 1674 PROT_READ | PROT_WRITE, EINVAL); 1675 largepage_protect(addr, ps[i] * 2, PROT_READ | PROT_WRITE, 0); 1676 1677 memset(addr, 0, ps[i] * 2); 1678 1679 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1680 ATF_REQUIRE(munmap(addr1, ps[i]) == 0); 1681 ATF_REQUIRE(close(fd) == 0); 1682 } 1683 } 1684 1685 ATF_TC_WITHOUT_HEAD(largepage_minherit); 1686 ATF_TC_BODY(largepage_minherit, tc) 1687 { 1688 char *addr; 1689 size_t ps[MAXPAGESIZES]; 1690 pid_t child; 1691 int fd, pscnt, status; 1692 1693 pscnt = pagesizes(ps); 1694 for (int i = 1; i < pscnt; i++) { 1695 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1696 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1697 0); 1698 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1699 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1700 1701 ATF_REQUIRE(minherit(addr, PAGE_SIZE, INHERIT_SHARE) != 0); 1702 1703 ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_SHARE) == 0, 1704 "minherit(%zu bytes) failed; error=%d", ps[i], errno); 1705 child = fork(); 1706 ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno); 1707 if (child == 0) { 1708 char v; 1709 1710 *(volatile char *)addr = 0; 1711 if (mincore(addr, PAGE_SIZE, &v) != 0) 1712 _exit(1); 1713 if ((v & MINCORE_PSIND(i)) == 0) 1714 _exit(2); 1715 _exit(0); 1716 } 1717 ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child, 1718 "waitpid failed; error=%d", errno); 1719 ATF_REQUIRE_MSG(WIFEXITED(status), 1720 "child was killed by signal %d", WTERMSIG(status)); 1721 ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0, 1722 "child exited with status %d", WEXITSTATUS(status)); 1723 1724 ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_NONE) == 0, 1725 "minherit(%zu bytes) failed; error=%d", ps[i], errno); 1726 child = fork(); 1727 ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno); 1728 if (child == 0) { 1729 char v; 1730 1731 if (mincore(addr, PAGE_SIZE, &v) == 0) 1732 _exit(1); 1733 _exit(0); 1734 } 1735 ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child, 1736 "waitpid failed; error=%d", errno); 1737 ATF_REQUIRE_MSG(WIFEXITED(status), 1738 "child was killed by signal %d", WTERMSIG(status)); 1739 ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0, 1740 "child exited with status %d", WEXITSTATUS(status)); 1741 1742 /* Copy-on-write is not supported for static large pages. */ 1743 ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_COPY) != 0, 1744 "minherit(%zu bytes) succeeded", ps[i]); 1745 1746 ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_ZERO) == 0, 1747 "minherit(%zu bytes) failed; error=%d", ps[i], errno); 1748 child = fork(); 1749 ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno); 1750 if (child == 0) { 1751 char v; 1752 1753 *(volatile char *)addr = 0; 1754 if (mincore(addr, PAGE_SIZE, &v) != 0) 1755 _exit(1); 1756 if ((v & MINCORE_SUPER) != 0) 1757 _exit(2); 1758 _exit(0); 1759 } 1760 ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child, 1761 "waitpid failed; error=%d", errno); 1762 ATF_REQUIRE_MSG(WIFEXITED(status), 1763 "child was killed by signal %d", WTERMSIG(status)); 1764 ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0, 1765 "child exited with status %d", WEXITSTATUS(status)); 1766 1767 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1768 ATF_REQUIRE(close(fd) == 0); 1769 } 1770 } 1771 1772 ATF_TC_WITHOUT_HEAD(largepage_pipe); 1773 ATF_TC_BODY(largepage_pipe, tc) 1774 { 1775 size_t ps[MAXPAGESIZES]; 1776 char *addr; 1777 ssize_t len; 1778 int fd, pfd[2], pscnt, status; 1779 pid_t child; 1780 1781 pscnt = pagesizes(ps); 1782 1783 for (int i = 1; i < pscnt; i++) { 1784 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1785 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1786 0); 1787 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1788 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1789 1790 /* Trigger creation of a mapping. */ 1791 *(volatile char *)addr = '\0'; 1792 1793 ATF_REQUIRE(pipe(pfd) == 0); 1794 child = fork(); 1795 ATF_REQUIRE_MSG(child != -1, "fork() failed; error=%d", errno); 1796 if (child == 0) { 1797 char buf[BUFSIZ]; 1798 ssize_t resid; 1799 1800 (void)close(pfd[0]); 1801 for (resid = (size_t)ps[i]; resid > 0; resid -= len) { 1802 len = read(pfd[1], buf, sizeof(buf)); 1803 if (len < 0) 1804 _exit(1); 1805 } 1806 _exit(0); 1807 } 1808 ATF_REQUIRE(close(pfd[1]) == 0); 1809 len = write(pfd[0], addr, ps[i]); 1810 ATF_REQUIRE_MSG(len >= 0, "write() failed; error=%d", errno); 1811 ATF_REQUIRE_MSG(len == (ssize_t)ps[i], 1812 "short write; len=%zd", len); 1813 ATF_REQUIRE(close(pfd[0]) == 0); 1814 1815 ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child, 1816 "waitpid() failed; error=%d", errno); 1817 ATF_REQUIRE_MSG(WIFEXITED(status), 1818 "child was killed by signal %d", WTERMSIG(status)); 1819 ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0, 1820 "child exited with status %d", WEXITSTATUS(status)); 1821 1822 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1823 ATF_REQUIRE(close(fd) == 0); 1824 } 1825 } 1826 1827 ATF_TC_WITHOUT_HEAD(largepage_reopen); 1828 ATF_TC_BODY(largepage_reopen, tc) 1829 { 1830 char *addr, *vec; 1831 size_t ps[MAXPAGESIZES]; 1832 int fd, psind; 1833 1834 (void)pagesizes(ps); 1835 psind = 1; 1836 1837 gen_test_path(); 1838 fd = shm_create_largepage(test_path, O_CREAT | O_RDWR, psind, 1839 SHM_LARGEPAGE_ALLOC_DEFAULT, 0600); 1840 if (fd < 0 && errno == ENOTTY) 1841 atf_tc_skip("no large page support"); 1842 ATF_REQUIRE_MSG(fd >= 0, "shm_create_largepage failed; error=%d", errno); 1843 1844 ATF_REQUIRE_MSG(ftruncate(fd, ps[psind]) == 0, 1845 "ftruncate failed; error=%d", errno); 1846 1847 ATF_REQUIRE_MSG(close(fd) == 0, "close failed; error=%d", errno); 1848 1849 fd = shm_open(test_path, O_RDWR, 0); 1850 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; error=%d", errno); 1851 1852 addr = mmap(NULL, ps[psind], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1853 ATF_REQUIRE_MSG(addr != MAP_FAILED, "mmap failed; error=%d", errno); 1854 1855 /* Trigger a fault and mapping creation. */ 1856 *(volatile char *)addr = 0; 1857 1858 vec = malloc(ps[psind] / PAGE_SIZE); 1859 ATF_REQUIRE(vec != NULL); 1860 ATF_REQUIRE_MSG(mincore(addr, ps[psind], vec) == 0, 1861 "mincore failed; error=%d", errno); 1862 ATF_REQUIRE_MSG((vec[0] & MINCORE_PSIND(psind)) != 0, 1863 "page not mapped into a %zu-byte superpage", ps[psind]); 1864 1865 ATF_REQUIRE_MSG(shm_unlink(test_path) == 0, 1866 "shm_unlink failed; errno=%d", errno); 1867 ATF_REQUIRE_MSG(close(fd) == 0, 1868 "close failed; errno=%d", errno); 1869 } 1870 1871 ATF_TP_ADD_TCS(tp) 1872 { 1873 1874 ATF_TP_ADD_TC(tp, remap_object); 1875 ATF_TP_ADD_TC(tp, rename_from_anon); 1876 ATF_TP_ADD_TC(tp, rename_bad_path_pointer); 1877 ATF_TP_ADD_TC(tp, rename_from_nonexisting); 1878 ATF_TP_ADD_TC(tp, rename_to_anon); 1879 ATF_TP_ADD_TC(tp, rename_to_replace); 1880 ATF_TP_ADD_TC(tp, rename_to_noreplace); 1881 ATF_TP_ADD_TC(tp, rename_to_exchange); 1882 ATF_TP_ADD_TC(tp, rename_to_exchange_nonexisting); 1883 ATF_TP_ADD_TC(tp, rename_to_self); 1884 ATF_TP_ADD_TC(tp, rename_bad_flag); 1885 ATF_TP_ADD_TC(tp, reopen_object); 1886 ATF_TP_ADD_TC(tp, readonly_mmap_write); 1887 ATF_TP_ADD_TC(tp, open_after_link); 1888 ATF_TP_ADD_TC(tp, open_invalid_path); 1889 ATF_TP_ADD_TC(tp, open_write_only); 1890 ATF_TP_ADD_TC(tp, open_extra_flags); 1891 ATF_TP_ADD_TC(tp, open_anon); 1892 ATF_TP_ADD_TC(tp, open_anon_readonly); 1893 ATF_TP_ADD_TC(tp, open_bad_path_pointer); 1894 ATF_TP_ADD_TC(tp, open_path_too_long); 1895 ATF_TP_ADD_TC(tp, open_nonexisting_object); 1896 ATF_TP_ADD_TC(tp, open_create_existing_object); 1897 ATF_TP_ADD_TC(tp, shm_functionality_across_fork); 1898 ATF_TP_ADD_TC(tp, trunc_resets_object); 1899 ATF_TP_ADD_TC(tp, unlink_bad_path_pointer); 1900 ATF_TP_ADD_TC(tp, unlink_path_too_long); 1901 ATF_TP_ADD_TC(tp, object_resize); 1902 ATF_TP_ADD_TC(tp, cloexec); 1903 ATF_TP_ADD_TC(tp, mode); 1904 ATF_TP_ADD_TC(tp, fallocate); 1905 ATF_TP_ADD_TC(tp, fspacectl); 1906 ATF_TP_ADD_TC(tp, largepage_basic); 1907 ATF_TP_ADD_TC(tp, largepage_config); 1908 ATF_TP_ADD_TC(tp, largepage_mmap); 1909 ATF_TP_ADD_TC(tp, largepage_munmap); 1910 ATF_TP_ADD_TC(tp, largepage_madvise); 1911 ATF_TP_ADD_TC(tp, largepage_mlock); 1912 ATF_TP_ADD_TC(tp, largepage_msync); 1913 ATF_TP_ADD_TC(tp, largepage_mprotect); 1914 ATF_TP_ADD_TC(tp, largepage_minherit); 1915 ATF_TP_ADD_TC(tp, largepage_pipe); 1916 ATF_TP_ADD_TC(tp, largepage_reopen); 1917 1918 return (atf_no_error()); 1919 } 1920