1 /*- 2 * Copyright (c) 2006 Robert N. M. Watson 3 * All rights reserved. 4 * 5 * Copyright (c) 2021 The FreeBSD Foundation 6 * 7 * Portions of this software were developed by Ka Ho Ng 8 * under sponsorship from the FreeBSD Foundation. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/param.h> 33 #include <sys/ioctl.h> 34 #include <sys/mman.h> 35 #include <sys/resource.h> 36 #include <sys/stat.h> 37 #include <sys/syscall.h> 38 #include <sys/sysctl.h> 39 #include <sys/wait.h> 40 41 #include <ctype.h> 42 #include <errno.h> 43 #include <fcntl.h> 44 #include <signal.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <unistd.h> 49 50 #include <atf-c.h> 51 52 #define TEST_PATH_LEN 256 53 static char test_path[TEST_PATH_LEN]; 54 static char test_path2[TEST_PATH_LEN]; 55 static unsigned int test_path_idx = 0; 56 57 static void 58 gen_a_test_path(char *path) 59 { 60 snprintf(path, TEST_PATH_LEN, "/%s/tmp.XXXXXX%d", 61 getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR"), 62 test_path_idx); 63 64 test_path_idx++; 65 66 ATF_REQUIRE_MSG(mkstemp(path) != -1, 67 "mkstemp failed; errno=%d", errno); 68 ATF_REQUIRE_MSG(unlink(path) == 0, 69 "unlink failed; errno=%d", errno); 70 } 71 72 static void 73 gen_test_path(void) 74 { 75 gen_a_test_path(test_path); 76 } 77 78 static void 79 gen_test_path2(void) 80 { 81 gen_a_test_path(test_path2); 82 } 83 84 /* 85 * Attempt a shm_open() that should fail with an expected error of 'error'. 86 */ 87 static void 88 shm_open_should_fail(const char *path, int flags, mode_t mode, int error) 89 { 90 int fd; 91 92 fd = shm_open(path, flags, mode); 93 ATF_CHECK_MSG(fd == -1, "shm_open didn't fail"); 94 ATF_CHECK_MSG(error == errno, 95 "shm_open didn't fail with expected errno; errno=%d; expected " 96 "errno=%d", errno, error); 97 } 98 99 /* 100 * Attempt a shm_unlink() that should fail with an expected error of 'error'. 101 */ 102 static void 103 shm_unlink_should_fail(const char *path, int error) 104 { 105 106 ATF_CHECK_MSG(shm_unlink(path) == -1, "shm_unlink didn't fail"); 107 ATF_CHECK_MSG(error == errno, 108 "shm_unlink didn't fail with expected errno; errno=%d; expected " 109 "errno=%d", errno, error); 110 } 111 112 /* 113 * Open the test object and write a value to the first byte. Returns valid fd 114 * on success and -1 on failure. 115 */ 116 static int 117 scribble_object(const char *path, char value) 118 { 119 char *page; 120 int fd, pagesize; 121 122 ATF_REQUIRE(0 < (pagesize = getpagesize())); 123 124 fd = shm_open(path, O_CREAT|O_EXCL|O_RDWR, 0777); 125 if (fd < 0 && errno == EEXIST) { 126 if (shm_unlink(test_path) < 0) 127 atf_tc_fail("shm_unlink"); 128 fd = shm_open(test_path, O_CREAT | O_EXCL | O_RDWR, 0777); 129 } 130 if (fd < 0) 131 atf_tc_fail("shm_open failed; errno=%d", errno); 132 if (ftruncate(fd, pagesize) < 0) 133 atf_tc_fail("ftruncate failed; errno=%d", errno); 134 135 page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 136 if (page == MAP_FAILED) 137 atf_tc_fail("mmap failed; errno=%d", errno); 138 139 page[0] = value; 140 ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 141 errno); 142 143 return (fd); 144 } 145 146 /* 147 * Fail the test case if the 'path' does not refer to an shm whose first byte 148 * is equal to expected_value 149 */ 150 static void 151 verify_object(const char *path, char expected_value) 152 { 153 int fd; 154 int pagesize; 155 char *page; 156 157 ATF_REQUIRE(0 < (pagesize = getpagesize())); 158 159 fd = shm_open(path, O_RDONLY, 0777); 160 if (fd < 0) 161 atf_tc_fail("shm_open failed in verify_object; errno=%d, path=%s", 162 errno, path); 163 164 page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0); 165 if (page == MAP_FAILED) 166 atf_tc_fail("mmap(1)"); 167 if (page[0] != expected_value) 168 atf_tc_fail("Renamed object has incorrect value; has" 169 "%d (0x%x, '%c'), expected %d (0x%x, '%c')\n", 170 page[0], page[0], isprint(page[0]) ? page[0] : ' ', 171 expected_value, expected_value, 172 isprint(expected_value) ? expected_value : ' '); 173 ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 174 errno); 175 close(fd); 176 } 177 178 static off_t shm_max_pages = 32; 179 static const char byte_to_fill = 0x5f; 180 181 static int 182 shm_fill(int fd, off_t offset, off_t len) 183 { 184 int error; 185 size_t blen, page_size; 186 char *buf; 187 188 error = 0; 189 page_size = getpagesize(); 190 buf = malloc(page_size); 191 if (buf == NULL) 192 return (1); 193 194 while (len > 0) { 195 blen = len < (off_t)page_size ? (size_t)len : page_size; 196 memset(buf, byte_to_fill, blen); 197 if (pwrite(fd, buf, blen, offset) != (ssize_t)blen) { 198 error = 1; 199 break; 200 } 201 len -= blen; 202 offset += blen; 203 } 204 205 free(buf); 206 return (error); 207 } 208 209 static int 210 check_content_dealloc(int fd, off_t hole_start, off_t hole_len, off_t shm_sz) 211 { 212 int error; 213 size_t blen, page_size; 214 off_t offset, resid; 215 struct stat statbuf; 216 char *buf, *sblk; 217 218 error = 0; 219 page_size = getpagesize(); 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 ? (size_t)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 ? (size_t)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 ? (size_t)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 size_t page_size; 1092 int fd, error; 1093 1094 page_size = getpagesize(); 1095 shm_sz = shm_max_pages * page_size; 1096 1097 fd = shm_open("/testtest", O_RDWR | O_CREAT, 0666); 1098 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno:%d", errno); 1099 ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, shm_sz)) == 0, 1100 "posix_fallocate failed; error=%d", error); 1101 1102 /* Aligned fspacectl(fd, SPACECTL_DEALLOC, ...) */ 1103 ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0); 1104 range.r_offset = offset = page_size; 1105 range.r_len = length = ((shm_max_pages - 1) * page_size) - 1106 range.r_offset; 1107 ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0, 1108 "Aligned fspacectl failed; errno=%d", errno); 1109 ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0, 1110 "Aligned fspacectl content checking failed"); 1111 1112 /* Unaligned fspacectl(fd, SPACECTL_DEALLOC, ...) */ 1113 ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0); 1114 range.r_offset = offset = page_size / 2; 1115 range.r_len = length = (shm_max_pages - 1) * page_size + 1116 (page_size / 2) - offset; 1117 ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0, 1118 "Unaligned fspacectl failed; errno=%d", errno); 1119 ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0, 1120 "Unaligned fspacectl content checking failed"); 1121 1122 /* Aligned fspacectl(fd, SPACECTL_DEALLOC, ...) to OFF_MAX */ 1123 ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0); 1124 range.r_offset = offset = page_size; 1125 range.r_len = length = OFF_MAX - offset; 1126 ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0, 1127 "Aligned fspacectl to OFF_MAX failed; errno=%d", errno); 1128 ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0, 1129 "Aligned fspacectl to OFF_MAX content checking failed"); 1130 1131 /* Unaligned fspacectl(fd, SPACECTL_DEALLOC, ...) to OFF_MAX */ 1132 ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0); 1133 range.r_offset = offset = page_size / 2; 1134 range.r_len = length = OFF_MAX - offset; 1135 ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0, 1136 "Unaligned fspacectl to OFF_MAX failed; errno=%d", errno); 1137 ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0, 1138 "Unaligned fspacectl to OFF_MAX content checking failed"); 1139 1140 /* Aligned fspacectl(fd, SPACECTL_DEALLOC, ...) past shm_sz */ 1141 ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0); 1142 range.r_offset = offset = page_size; 1143 range.r_len = length = (shm_max_pages + 1) * page_size - offset; 1144 ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0, 1145 "Aligned fspacectl past shm_sz failed; errno=%d", errno); 1146 ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0, 1147 "Aligned fspacectl past shm_sz content checking failed"); 1148 1149 /* Unaligned fspacectl(fd, SPACECTL_DEALLOC, ...) past shm_sz */ 1150 ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0); 1151 range.r_offset = offset = page_size / 2; 1152 range.r_len = length = (shm_max_pages + 1) * page_size - offset; 1153 ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0, 1154 "Unaligned fspacectl past shm_sz failed; errno=%d", errno); 1155 ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0, 1156 "Unaligned fspacectl past shm_sz content checking failed"); 1157 1158 ATF_REQUIRE(close(fd) == 0); 1159 } 1160 1161 ATF_TC_WITHOUT_HEAD(accounting); 1162 ATF_TC_BODY(accounting, tc) 1163 { 1164 struct spacectl_range range; 1165 struct stat st; 1166 off_t shm_sz, len; 1167 size_t page_size; 1168 int fd, error; 1169 1170 page_size = getpagesize(); 1171 shm_sz = shm_max_pages * page_size; 1172 1173 fd = shm_open("/testtest1", O_RDWR | O_CREAT, 0666); 1174 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno:%d", errno); 1175 ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, shm_sz)) == 0, 1176 "posix_fallocate failed; error=%d", error); 1177 1178 ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0); 1179 ATF_REQUIRE(fstat(fd, &st) == 0); 1180 ATF_REQUIRE(st.st_blksize * st.st_blocks == (blkcnt_t)shm_sz); 1181 1182 range.r_offset = page_size; 1183 range.r_len = len = (shm_max_pages - 1) * page_size - 1184 range.r_offset; 1185 ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0, 1186 "SPACECTL_DEALLOC failed; errno=%d", errno); 1187 ATF_REQUIRE(fstat(fd, &st) == 0); 1188 ATF_REQUIRE(st.st_blksize * st.st_blocks == (blkcnt_t)(shm_sz - len)); 1189 1190 ATF_REQUIRE(close(fd) == 0); 1191 } 1192 1193 static int 1194 shm_open_large(int psind, int policy, size_t sz) 1195 { 1196 int error, fd; 1197 1198 fd = shm_create_largepage(SHM_ANON, O_CREAT | O_RDWR, psind, policy, 0); 1199 if (fd < 0 && errno == ENOTTY) 1200 atf_tc_skip("no large page support"); 1201 ATF_REQUIRE_MSG(fd >= 0, "shm_create_largepage failed; errno=%d", errno); 1202 1203 error = ftruncate(fd, sz); 1204 if (error != 0 && errno == ENOMEM) 1205 /* 1206 * The test system might not have enough memory to accommodate 1207 * the request. 1208 */ 1209 atf_tc_skip("failed to allocate %zu-byte superpage", sz); 1210 ATF_REQUIRE_MSG(error == 0, "ftruncate failed; errno=%d", errno); 1211 1212 return (fd); 1213 } 1214 1215 static int 1216 pagesizes(size_t ps[MAXPAGESIZES]) 1217 { 1218 int pscnt; 1219 1220 pscnt = getpagesizes(ps, MAXPAGESIZES); 1221 ATF_REQUIRE_MSG(pscnt != -1, "getpagesizes failed; errno=%d", errno); 1222 ATF_REQUIRE_MSG(ps[0] != 0, "psind 0 is %zu", ps[0]); 1223 ATF_REQUIRE_MSG(pscnt <= MAXPAGESIZES, "invalid pscnt %d", pscnt); 1224 if (pscnt == 1) 1225 atf_tc_skip("no large page support"); 1226 return (pscnt); 1227 } 1228 1229 ATF_TC_WITHOUT_HEAD(largepage_basic); 1230 ATF_TC_BODY(largepage_basic, tc) 1231 { 1232 char *zeroes; 1233 char *addr, *vec; 1234 size_t ps[MAXPAGESIZES]; 1235 int error, fd, pscnt; 1236 1237 pscnt = pagesizes(ps); 1238 zeroes = calloc(1, ps[0]); 1239 ATF_REQUIRE(zeroes != NULL); 1240 for (int i = 1; i < pscnt; i++) { 1241 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1242 1243 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1244 0); 1245 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1246 "mmap(%zu bytes) failed; errno=%d", ps[i], errno); 1247 ATF_REQUIRE_MSG(((uintptr_t)addr & (ps[i] - 1)) == 0, 1248 "mmap(%zu bytes) returned unaligned mapping; addr=%p", 1249 ps[i], addr); 1250 1251 /* Force a page fault. */ 1252 *(volatile char *)addr = 0; 1253 1254 vec = malloc(ps[i] / ps[0]); 1255 ATF_REQUIRE(vec != NULL); 1256 error = mincore(addr, ps[i], vec); 1257 ATF_REQUIRE_MSG(error == 0, "mincore failed; errno=%d", errno); 1258 1259 /* Verify that all pages in the run are mapped. */ 1260 for (size_t p = 0; p < ps[i] / ps[0]; p++) { 1261 ATF_REQUIRE_MSG((vec[p] & MINCORE_INCORE) != 0, 1262 "page %zu is not mapped", p); 1263 ATF_REQUIRE_MSG((vec[p] & MINCORE_SUPER) == 1264 MINCORE_PSIND(i), 1265 "page %zu is not in a %zu-byte superpage", 1266 p, ps[i]); 1267 } 1268 1269 /* Validate zeroing. */ 1270 for (size_t p = 0; p < ps[i] / ps[0]; p++) { 1271 ATF_REQUIRE_MSG(memcmp(addr + p * ps[0], zeroes, 1272 ps[0]) == 0, "page %zu miscompare", p); 1273 } 1274 1275 free(vec); 1276 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1277 ATF_REQUIRE(close(fd) == 0); 1278 } 1279 1280 free(zeroes); 1281 } 1282 1283 extern int __sys_shm_open2(const char *, int, mode_t, int, const char *); 1284 1285 ATF_TC_WITHOUT_HEAD(largepage_config); 1286 ATF_TC_BODY(largepage_config, tc) 1287 { 1288 struct shm_largepage_conf lpc; 1289 char *addr, *buf; 1290 size_t ps[MAXPAGESIZES + 1]; /* silence warnings if MAXPAGESIZES == 1 */ 1291 int error, fd; 1292 1293 (void)pagesizes(ps); 1294 1295 fd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0); 1296 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; error=%d", errno); 1297 1298 /* 1299 * Configure a large page policy for an object created without 1300 * SHM_LARGEPAGE. 1301 */ 1302 lpc.psind = 1; 1303 lpc.alloc_policy = SHM_LARGEPAGE_ALLOC_DEFAULT; 1304 error = ioctl(fd, FIOSSHMLPGCNF, &lpc); 1305 ATF_REQUIRE(error != 0); 1306 ATF_REQUIRE_MSG(errno == ENOTTY, "ioctl(FIOSSHMLPGCNF) returned %d", 1307 errno); 1308 ATF_REQUIRE(close(fd) == 0); 1309 1310 /* 1311 * Create a largepage object and try to use it without actually 1312 * configuring anything. 1313 */ 1314 fd = __sys_shm_open2(SHM_ANON, O_CREAT | O_RDWR, 0, SHM_LARGEPAGE, 1315 NULL); 1316 if (fd < 0 && errno == ENOTTY) 1317 atf_tc_skip("no large page support"); 1318 ATF_REQUIRE_MSG(fd >= 0, "shm_open2 failed; error=%d", errno); 1319 1320 error = ftruncate(fd, ps[1]); 1321 ATF_REQUIRE(error != 0); 1322 ATF_REQUIRE_MSG(errno == EINVAL, "ftruncate returned %d", errno); 1323 1324 addr = mmap(NULL, ps[1], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1325 ATF_REQUIRE(addr == MAP_FAILED); 1326 ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno); 1327 addr = mmap(NULL, 0, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1328 ATF_REQUIRE(addr == MAP_FAILED); 1329 ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno); 1330 1331 buf = calloc(1, ps[0]); 1332 ATF_REQUIRE(buf != NULL); 1333 ATF_REQUIRE(write(fd, buf, ps[0]) == -1); 1334 ATF_REQUIRE_MSG(errno == EINVAL, "write returned %d", errno); 1335 free(buf); 1336 buf = calloc(1, ps[1]); 1337 ATF_REQUIRE(buf != NULL); 1338 ATF_REQUIRE(write(fd, buf, ps[1]) == -1); 1339 ATF_REQUIRE_MSG(errno == EINVAL, "write returned %d", errno); 1340 free(buf); 1341 1342 error = posix_fallocate(fd, 0, ps[0]); 1343 ATF_REQUIRE_MSG(error == EINVAL, "posix_fallocate returned %d", error); 1344 1345 ATF_REQUIRE(close(fd) == 0); 1346 } 1347 1348 ATF_TC_WITHOUT_HEAD(largepage_mmap); 1349 ATF_TC_BODY(largepage_mmap, tc) 1350 { 1351 char *addr, *addr1, *vec; 1352 size_t ps[MAXPAGESIZES]; 1353 int fd, pscnt; 1354 1355 pscnt = pagesizes(ps); 1356 for (int i = 1; i < pscnt; i++) { 1357 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1358 1359 /* For mincore(). */ 1360 vec = malloc(ps[i]); 1361 ATF_REQUIRE(vec != NULL); 1362 1363 /* 1364 * Wrong mapping size. 1365 */ 1366 addr = mmap(NULL, ps[i - 1], PROT_READ | PROT_WRITE, MAP_SHARED, 1367 fd, 0); 1368 ATF_REQUIRE_MSG(addr == MAP_FAILED, 1369 "mmap(%zu bytes) succeeded", ps[i - 1]); 1370 ATF_REQUIRE_MSG(errno == EINVAL, 1371 "mmap(%zu bytes) failed; error=%d", ps[i - 1], errno); 1372 1373 /* 1374 * Fixed mappings. 1375 */ 1376 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1377 0); 1378 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1379 "mmap(%zu bytes) failed; errno=%d", ps[i], errno); 1380 ATF_REQUIRE_MSG(((uintptr_t)addr & (ps[i] - 1)) == 0, 1381 "mmap(%zu bytes) returned unaligned mapping; addr=%p", 1382 ps[i], addr); 1383 1384 /* Try mapping a small page with anonymous memory. */ 1385 addr1 = mmap(addr, ps[i - 1], PROT_READ | PROT_WRITE, 1386 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); 1387 ATF_REQUIRE_MSG(addr1 == MAP_FAILED, 1388 "anon mmap(%zu bytes) succeeded", ps[i - 1]); 1389 ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno); 1390 1391 /* Check MAP_EXCL when creating a second largepage mapping. */ 1392 addr1 = mmap(addr, ps[i], PROT_READ | PROT_WRITE, 1393 MAP_SHARED | MAP_FIXED | MAP_EXCL, fd, 0); 1394 ATF_REQUIRE_MSG(addr1 == MAP_FAILED, 1395 "mmap(%zu bytes) succeeded", ps[i]); 1396 /* XXX wrong errno */ 1397 ATF_REQUIRE_MSG(errno == ENOSPC, "mmap returned %d", errno); 1398 1399 /* Overwrite a largepage mapping with a lagepage mapping. */ 1400 addr1 = mmap(addr, ps[i], PROT_READ | PROT_WRITE, 1401 MAP_SHARED | MAP_FIXED, fd, 0); 1402 ATF_REQUIRE_MSG(addr1 != MAP_FAILED, 1403 "mmap(%zu bytes) failed; errno=%d", ps[i], errno); 1404 ATF_REQUIRE_MSG(addr == addr1, 1405 "mmap(%zu bytes) moved from %p to %p", ps[i], addr, addr1); 1406 1407 ATF_REQUIRE(munmap(addr, ps[i] == 0)); 1408 1409 /* Clobber an anonymous mapping with a superpage. */ 1410 addr1 = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, 1411 MAP_ANON | MAP_PRIVATE | MAP_ALIGNED(ffsl(ps[i]) - 1), -1, 1412 0); 1413 ATF_REQUIRE_MSG(addr1 != MAP_FAILED, 1414 "mmap failed; error=%d", errno); 1415 *(volatile char *)addr1 = '\0'; 1416 addr = mmap(addr1, ps[i], PROT_READ | PROT_WRITE, 1417 MAP_SHARED | MAP_FIXED, fd, 0); 1418 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1419 "mmap failed; error=%d", errno); 1420 ATF_REQUIRE_MSG(addr == addr1, 1421 "mmap disobeyed MAP_FIXED, %p %p", addr, addr1); 1422 *(volatile char *)addr = 0; /* fault */ 1423 ATF_REQUIRE(mincore(addr, ps[i], vec) == 0); 1424 for (size_t p = 0; p < ps[i] / ps[0]; p++) { 1425 ATF_REQUIRE_MSG((vec[p] & MINCORE_INCORE) != 0, 1426 "page %zu is not resident", p); 1427 ATF_REQUIRE_MSG((vec[p] & MINCORE_SUPER) == 1428 MINCORE_PSIND(i), 1429 "page %zu is not resident", p); 1430 } 1431 1432 /* 1433 * Copy-on-write mappings are not permitted. 1434 */ 1435 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_PRIVATE, 1436 fd, 0); 1437 ATF_REQUIRE_MSG(addr == MAP_FAILED, 1438 "mmap(%zu bytes) succeeded", ps[i]); 1439 1440 ATF_REQUIRE(close(fd) == 0); 1441 } 1442 } 1443 1444 ATF_TC_WITHOUT_HEAD(largepage_munmap); 1445 ATF_TC_BODY(largepage_munmap, tc) 1446 { 1447 char *addr; 1448 size_t ps[MAXPAGESIZES], ps1; 1449 int fd, pscnt; 1450 1451 pscnt = pagesizes(ps); 1452 for (int i = 1; i < pscnt; i++) { 1453 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1454 ps1 = ps[i - 1]; 1455 1456 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1457 0); 1458 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1459 "mmap(%zu bytes) failed; errno=%d", ps[i], errno); 1460 1461 /* Try several unaligned munmap() requests. */ 1462 ATF_REQUIRE(munmap(addr, ps1) != 0); 1463 ATF_REQUIRE_MSG(errno == EINVAL, 1464 "unexpected error %d from munmap", errno); 1465 ATF_REQUIRE(munmap(addr, ps[i] - ps1)); 1466 ATF_REQUIRE_MSG(errno == EINVAL, 1467 "unexpected error %d from munmap", errno); 1468 ATF_REQUIRE(munmap(addr + ps1, ps1) != 0); 1469 ATF_REQUIRE_MSG(errno == EINVAL, 1470 "unexpected error %d from munmap", errno); 1471 ATF_REQUIRE(munmap(addr, 0)); 1472 ATF_REQUIRE_MSG(errno == EINVAL, 1473 "unexpected error %d from munmap", errno); 1474 1475 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1476 ATF_REQUIRE(close(fd) == 0); 1477 } 1478 } 1479 1480 static void 1481 largepage_madvise(char *addr, size_t sz, int advice, int error) 1482 { 1483 if (error == 0) { 1484 ATF_REQUIRE_MSG(madvise(addr, sz, advice) == 0, 1485 "madvise(%zu, %d) failed; error=%d", sz, advice, errno); 1486 } else { 1487 ATF_REQUIRE_MSG(madvise(addr, sz, advice) != 0, 1488 "madvise(%zu, %d) succeeded", sz, advice); 1489 ATF_REQUIRE_MSG(errno == error, 1490 "unexpected error %d from madvise(%zu, %d)", 1491 errno, sz, advice); 1492 } 1493 } 1494 1495 ATF_TC_WITHOUT_HEAD(largepage_madvise); 1496 ATF_TC_BODY(largepage_madvise, tc) 1497 { 1498 char *addr; 1499 size_t ps[MAXPAGESIZES]; 1500 int fd, pscnt; 1501 1502 pscnt = pagesizes(ps); 1503 for (int i = 1; i < pscnt; i++) { 1504 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1505 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1506 0); 1507 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1508 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1509 1510 memset(addr, 0, ps[i]); 1511 1512 /* Advice that requires clipping. */ 1513 largepage_madvise(addr, ps[0], MADV_NORMAL, EINVAL); 1514 largepage_madvise(addr, ps[i], MADV_NORMAL, 0); 1515 largepage_madvise(addr, ps[0], MADV_RANDOM, EINVAL); 1516 largepage_madvise(addr, ps[i], MADV_RANDOM, 0); 1517 largepage_madvise(addr, ps[0], MADV_SEQUENTIAL, EINVAL); 1518 largepage_madvise(addr, ps[i], MADV_SEQUENTIAL, 0); 1519 largepage_madvise(addr, ps[0], MADV_NOSYNC, EINVAL); 1520 largepage_madvise(addr, ps[i], MADV_NOSYNC, 0); 1521 largepage_madvise(addr, ps[0], MADV_AUTOSYNC, EINVAL); 1522 largepage_madvise(addr, ps[i], MADV_AUTOSYNC, 0); 1523 largepage_madvise(addr, ps[0], MADV_CORE, EINVAL); 1524 largepage_madvise(addr, ps[i], MADV_CORE, 0); 1525 largepage_madvise(addr, ps[0], MADV_NOCORE, EINVAL); 1526 largepage_madvise(addr, ps[i], MADV_NOCORE, 0); 1527 1528 /* Advice that does not result in clipping. */ 1529 largepage_madvise(addr, ps[0], MADV_DONTNEED, 0); 1530 largepage_madvise(addr, ps[i], MADV_DONTNEED, 0); 1531 largepage_madvise(addr, ps[0], MADV_WILLNEED, 0); 1532 largepage_madvise(addr, ps[i], MADV_WILLNEED, 0); 1533 largepage_madvise(addr, ps[0], MADV_FREE, 0); 1534 largepage_madvise(addr, ps[i], MADV_FREE, 0); 1535 1536 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1537 ATF_REQUIRE(close(fd) == 0); 1538 } 1539 } 1540 1541 ATF_TC(largepage_mlock); 1542 ATF_TC_HEAD(largepage_mlock, tc) 1543 { 1544 /* Needed to set rlimit. */ 1545 atf_tc_set_md_var(tc, "require.user", "root"); 1546 } 1547 ATF_TC_BODY(largepage_mlock, tc) 1548 { 1549 struct rlimit rl; 1550 char *addr; 1551 size_t ps[MAXPAGESIZES], sz; 1552 u_long max_wired, wired; 1553 int fd, error, pscnt; 1554 1555 rl.rlim_cur = rl.rlim_max = RLIM_INFINITY; 1556 ATF_REQUIRE_MSG(setrlimit(RLIMIT_MEMLOCK, &rl) == 0, 1557 "setrlimit failed; error=%d", errno); 1558 1559 sz = sizeof(max_wired); 1560 error = sysctlbyname("vm.max_user_wired", &max_wired, &sz, NULL, 0); 1561 ATF_REQUIRE_MSG(error == 0, 1562 "sysctlbyname(vm.max_user_wired) failed; error=%d", errno); 1563 1564 sz = sizeof(wired); 1565 error = sysctlbyname("vm.stats.vm.v_user_wire_count", &wired, &sz, NULL, 1566 0); 1567 ATF_REQUIRE_MSG(error == 0, 1568 "sysctlbyname(vm.stats.vm.v_user_wire_count) failed; error=%d", 1569 errno); 1570 1571 pscnt = pagesizes(ps); 1572 for (int i = 1; i < pscnt; i++) { 1573 if (ps[i] / ps[0] > max_wired - wired) { 1574 /* Cannot wire past the limit. */ 1575 atf_tc_skip("test would exceed wiring limit"); 1576 } 1577 1578 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1579 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1580 0); 1581 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1582 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1583 1584 ATF_REQUIRE(mlock(addr, ps[0]) != 0); 1585 ATF_REQUIRE_MSG(errno == EINVAL, 1586 "unexpected error %d from mlock(%zu bytes)", errno, ps[i]); 1587 ATF_REQUIRE(mlock(addr, ps[i] - ps[0]) != 0); 1588 ATF_REQUIRE_MSG(errno == EINVAL, 1589 "unexpected error %d from mlock(%zu bytes)", errno, ps[i]); 1590 1591 ATF_REQUIRE_MSG(mlock(addr, ps[i]) == 0, 1592 "mlock failed; error=%d", errno); 1593 1594 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1595 1596 ATF_REQUIRE(mlockall(MCL_FUTURE) == 0); 1597 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1598 0); 1599 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1600 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1601 1602 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1603 ATF_REQUIRE(close(fd) == 0); 1604 } 1605 } 1606 1607 ATF_TC_WITHOUT_HEAD(largepage_msync); 1608 ATF_TC_BODY(largepage_msync, tc) 1609 { 1610 char *addr; 1611 size_t ps[MAXPAGESIZES]; 1612 int fd, pscnt; 1613 1614 pscnt = pagesizes(ps); 1615 for (int i = 1; i < pscnt; i++) { 1616 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1617 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1618 0); 1619 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1620 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1621 1622 memset(addr, 0, ps[i]); 1623 1624 /* 1625 * "Sync" requests are no-ops for SHM objects, so small 1626 * PAGE_SIZE-sized requests succeed. 1627 */ 1628 ATF_REQUIRE_MSG(msync(addr, ps[0], MS_ASYNC) == 0, 1629 "msync(MS_ASYNC) failed; error=%d", errno); 1630 ATF_REQUIRE_MSG(msync(addr, ps[i], MS_ASYNC) == 0, 1631 "msync(MS_ASYNC) failed; error=%d", errno); 1632 ATF_REQUIRE_MSG(msync(addr, ps[0], MS_SYNC) == 0, 1633 "msync(MS_SYNC) failed; error=%d", errno); 1634 ATF_REQUIRE_MSG(msync(addr, ps[i], MS_SYNC) == 0, 1635 "msync(MS_SYNC) failed; error=%d", errno); 1636 1637 ATF_REQUIRE_MSG(msync(addr, ps[0], MS_INVALIDATE) != 0, 1638 "msync(MS_INVALIDATE) succeeded"); 1639 /* XXX wrong errno */ 1640 ATF_REQUIRE_MSG(errno == EBUSY, 1641 "unexpected error %d from msync(MS_INVALIDATE)", errno); 1642 ATF_REQUIRE_MSG(msync(addr, ps[i], MS_INVALIDATE) == 0, 1643 "msync(MS_INVALIDATE) failed; error=%d", errno); 1644 memset(addr, 0, ps[i]); 1645 1646 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1647 ATF_REQUIRE(close(fd) == 0); 1648 } 1649 } 1650 1651 static void 1652 largepage_protect(char *addr, size_t sz, int prot, int error) 1653 { 1654 if (error == 0) { 1655 ATF_REQUIRE_MSG(mprotect(addr, sz, prot) == 0, 1656 "mprotect(%zu, %x) failed; error=%d", sz, prot, errno); 1657 } else { 1658 ATF_REQUIRE_MSG(mprotect(addr, sz, prot) != 0, 1659 "mprotect(%zu, %x) succeeded", sz, prot); 1660 ATF_REQUIRE_MSG(errno == error, 1661 "unexpected error %d from mprotect(%zu, %x)", 1662 errno, sz, prot); 1663 } 1664 } 1665 1666 ATF_TC_WITHOUT_HEAD(largepage_mprotect); 1667 ATF_TC_BODY(largepage_mprotect, tc) 1668 { 1669 char *addr, *addr1; 1670 size_t ps[MAXPAGESIZES]; 1671 int fd, pscnt; 1672 1673 pscnt = pagesizes(ps); 1674 for (int i = 1; i < pscnt; i++) { 1675 /* 1676 * Reserve a contiguous region in the address space to avoid 1677 * spurious failures in the face of ASLR. 1678 */ 1679 addr = mmap(NULL, ps[i] * 2, PROT_NONE, 1680 MAP_ANON | MAP_ALIGNED(ffsl(ps[i]) - 1), -1, 0); 1681 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1682 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1683 ATF_REQUIRE(munmap(addr, ps[i] * 2) == 0); 1684 1685 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1686 addr = mmap(addr, ps[i], PROT_READ | PROT_WRITE, 1687 MAP_SHARED | MAP_FIXED, fd, 0); 1688 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1689 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1690 1691 /* 1692 * These should be no-ops from the pmap perspective since the 1693 * page is not yet entered into the pmap. 1694 */ 1695 largepage_protect(addr, ps[0], PROT_READ, EINVAL); 1696 largepage_protect(addr, ps[i], PROT_READ, 0); 1697 largepage_protect(addr, ps[0], PROT_NONE, EINVAL); 1698 largepage_protect(addr, ps[i], PROT_NONE, 0); 1699 largepage_protect(addr, ps[0], 1700 PROT_READ | PROT_WRITE | PROT_EXEC, EINVAL); 1701 largepage_protect(addr, ps[i], 1702 PROT_READ | PROT_WRITE | PROT_EXEC, 0); 1703 1704 /* Trigger creation of a mapping and try again. */ 1705 *(volatile char *)addr = 0; 1706 largepage_protect(addr, ps[0], PROT_READ, EINVAL); 1707 largepage_protect(addr, ps[i], PROT_READ, 0); 1708 largepage_protect(addr, ps[0], PROT_NONE, EINVAL); 1709 largepage_protect(addr, ps[i], PROT_NONE, 0); 1710 largepage_protect(addr, ps[0], 1711 PROT_READ | PROT_WRITE | PROT_EXEC, EINVAL); 1712 largepage_protect(addr, ps[i], 1713 PROT_READ | PROT_WRITE | PROT_EXEC, 0); 1714 1715 memset(addr, 0, ps[i]); 1716 1717 /* Map two contiguous large pages and merge map entries. */ 1718 addr1 = mmap(addr + ps[i], ps[i], PROT_READ | PROT_WRITE, 1719 MAP_SHARED | MAP_FIXED | MAP_EXCL, fd, 0); 1720 ATF_REQUIRE_MSG(addr1 != MAP_FAILED, 1721 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1722 1723 largepage_protect(addr1 - ps[0], ps[0] * 2, 1724 PROT_READ | PROT_WRITE, EINVAL); 1725 largepage_protect(addr, ps[i] * 2, PROT_READ | PROT_WRITE, 0); 1726 1727 memset(addr, 0, ps[i] * 2); 1728 1729 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1730 ATF_REQUIRE(munmap(addr1, ps[i]) == 0); 1731 ATF_REQUIRE(close(fd) == 0); 1732 } 1733 } 1734 1735 ATF_TC_WITHOUT_HEAD(largepage_minherit); 1736 ATF_TC_BODY(largepage_minherit, tc) 1737 { 1738 char *addr; 1739 size_t ps[MAXPAGESIZES]; 1740 pid_t child; 1741 int fd, pscnt, status; 1742 1743 pscnt = pagesizes(ps); 1744 for (int i = 1; i < pscnt; i++) { 1745 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1746 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1747 0); 1748 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1749 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1750 1751 ATF_REQUIRE(minherit(addr, ps[0], INHERIT_SHARE) != 0); 1752 1753 ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_SHARE) == 0, 1754 "minherit(%zu bytes) failed; error=%d", ps[i], errno); 1755 child = fork(); 1756 ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno); 1757 if (child == 0) { 1758 char v; 1759 1760 *(volatile char *)addr = 0; 1761 if (mincore(addr, ps[0], &v) != 0) 1762 _exit(1); 1763 if ((v & MINCORE_SUPER) == 0) 1764 _exit(2); 1765 _exit(0); 1766 } 1767 ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child, 1768 "waitpid failed; error=%d", errno); 1769 ATF_REQUIRE_MSG(WIFEXITED(status), 1770 "child was killed by signal %d", WTERMSIG(status)); 1771 ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0, 1772 "child exited with status %d", WEXITSTATUS(status)); 1773 1774 ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_NONE) == 0, 1775 "minherit(%zu bytes) failed; error=%d", ps[i], errno); 1776 child = fork(); 1777 ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno); 1778 if (child == 0) { 1779 char v; 1780 1781 if (mincore(addr, ps[0], &v) == 0) 1782 _exit(1); 1783 _exit(0); 1784 } 1785 ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child, 1786 "waitpid failed; error=%d", errno); 1787 ATF_REQUIRE_MSG(WIFEXITED(status), 1788 "child was killed by signal %d", WTERMSIG(status)); 1789 ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0, 1790 "child exited with status %d", WEXITSTATUS(status)); 1791 1792 /* Copy-on-write is not supported for static large pages. */ 1793 ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_COPY) != 0, 1794 "minherit(%zu bytes) succeeded", ps[i]); 1795 1796 ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_ZERO) == 0, 1797 "minherit(%zu bytes) failed; error=%d", ps[i], errno); 1798 child = fork(); 1799 ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno); 1800 if (child == 0) { 1801 char v; 1802 1803 *(volatile char *)addr = 0; 1804 if (mincore(addr, ps[0], &v) != 0) 1805 _exit(1); 1806 if ((v & MINCORE_SUPER) != 0) 1807 _exit(2); 1808 _exit(0); 1809 } 1810 ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child, 1811 "waitpid failed; error=%d", errno); 1812 ATF_REQUIRE_MSG(WIFEXITED(status), 1813 "child was killed by signal %d", WTERMSIG(status)); 1814 ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0, 1815 "child exited with status %d", WEXITSTATUS(status)); 1816 1817 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1818 ATF_REQUIRE(close(fd) == 0); 1819 } 1820 } 1821 1822 ATF_TC_WITHOUT_HEAD(largepage_pipe); 1823 ATF_TC_BODY(largepage_pipe, tc) 1824 { 1825 size_t ps[MAXPAGESIZES]; 1826 char *addr; 1827 ssize_t len; 1828 int fd, pfd[2], pscnt, status; 1829 pid_t child; 1830 1831 pscnt = pagesizes(ps); 1832 1833 for (int i = 1; i < pscnt; i++) { 1834 fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1835 addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1836 0); 1837 ATF_REQUIRE_MSG(addr != MAP_FAILED, 1838 "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1839 1840 /* Trigger creation of a mapping. */ 1841 *(volatile char *)addr = '\0'; 1842 1843 ATF_REQUIRE(pipe(pfd) == 0); 1844 child = fork(); 1845 ATF_REQUIRE_MSG(child != -1, "fork() failed; error=%d", errno); 1846 if (child == 0) { 1847 char buf[BUFSIZ]; 1848 ssize_t resid; 1849 1850 (void)close(pfd[0]); 1851 for (resid = (size_t)ps[i]; resid > 0; resid -= len) { 1852 len = read(pfd[1], buf, sizeof(buf)); 1853 if (len < 0) 1854 _exit(1); 1855 } 1856 _exit(0); 1857 } 1858 ATF_REQUIRE(close(pfd[1]) == 0); 1859 len = write(pfd[0], addr, ps[i]); 1860 ATF_REQUIRE_MSG(len >= 0, "write() failed; error=%d", errno); 1861 ATF_REQUIRE_MSG(len == (ssize_t)ps[i], 1862 "short write; len=%zd", len); 1863 ATF_REQUIRE(close(pfd[0]) == 0); 1864 1865 ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child, 1866 "waitpid() failed; error=%d", errno); 1867 ATF_REQUIRE_MSG(WIFEXITED(status), 1868 "child was killed by signal %d", WTERMSIG(status)); 1869 ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0, 1870 "child exited with status %d", WEXITSTATUS(status)); 1871 1872 ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1873 ATF_REQUIRE(close(fd) == 0); 1874 } 1875 } 1876 1877 ATF_TC_WITHOUT_HEAD(largepage_reopen); 1878 ATF_TC_BODY(largepage_reopen, tc) 1879 { 1880 char *addr, *vec; 1881 size_t ps[MAXPAGESIZES]; 1882 int fd, psind; 1883 1884 (void)pagesizes(ps); 1885 psind = 1; 1886 1887 gen_test_path(); 1888 fd = shm_create_largepage(test_path, O_CREAT | O_RDWR, psind, 1889 SHM_LARGEPAGE_ALLOC_DEFAULT, 0600); 1890 if (fd < 0 && errno == ENOTTY) 1891 atf_tc_skip("no large page support"); 1892 ATF_REQUIRE_MSG(fd >= 0, "shm_create_largepage failed; error=%d", errno); 1893 1894 ATF_REQUIRE_MSG(ftruncate(fd, ps[psind]) == 0, 1895 "ftruncate failed; error=%d", errno); 1896 1897 ATF_REQUIRE_MSG(close(fd) == 0, "close failed; error=%d", errno); 1898 1899 fd = shm_open(test_path, O_RDWR, 0); 1900 ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; error=%d", errno); 1901 1902 addr = mmap(NULL, ps[psind], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1903 ATF_REQUIRE_MSG(addr != MAP_FAILED, "mmap failed; error=%d", errno); 1904 1905 /* Trigger a fault and mapping creation. */ 1906 *(volatile char *)addr = 0; 1907 1908 vec = malloc(ps[psind] / ps[0]); 1909 ATF_REQUIRE(vec != NULL); 1910 ATF_REQUIRE_MSG(mincore(addr, ps[psind], vec) == 0, 1911 "mincore failed; error=%d", errno); 1912 ATF_REQUIRE_MSG((vec[0] & MINCORE_SUPER) == MINCORE_PSIND(psind), 1913 "page not mapped into a %zu-byte superpage", ps[psind]); 1914 1915 ATF_REQUIRE_MSG(shm_unlink(test_path) == 0, 1916 "shm_unlink failed; errno=%d", errno); 1917 ATF_REQUIRE_MSG(close(fd) == 0, 1918 "close failed; errno=%d", errno); 1919 } 1920 1921 ATF_TP_ADD_TCS(tp) 1922 { 1923 1924 ATF_TP_ADD_TC(tp, remap_object); 1925 ATF_TP_ADD_TC(tp, rename_from_anon); 1926 ATF_TP_ADD_TC(tp, rename_bad_path_pointer); 1927 ATF_TP_ADD_TC(tp, rename_from_nonexisting); 1928 ATF_TP_ADD_TC(tp, rename_to_anon); 1929 ATF_TP_ADD_TC(tp, rename_to_replace); 1930 ATF_TP_ADD_TC(tp, rename_to_noreplace); 1931 ATF_TP_ADD_TC(tp, rename_to_exchange); 1932 ATF_TP_ADD_TC(tp, rename_to_exchange_nonexisting); 1933 ATF_TP_ADD_TC(tp, rename_to_self); 1934 ATF_TP_ADD_TC(tp, rename_bad_flag); 1935 ATF_TP_ADD_TC(tp, reopen_object); 1936 ATF_TP_ADD_TC(tp, readonly_mmap_write); 1937 ATF_TP_ADD_TC(tp, open_after_link); 1938 ATF_TP_ADD_TC(tp, open_invalid_path); 1939 ATF_TP_ADD_TC(tp, open_write_only); 1940 ATF_TP_ADD_TC(tp, open_extra_flags); 1941 ATF_TP_ADD_TC(tp, open_anon); 1942 ATF_TP_ADD_TC(tp, open_anon_readonly); 1943 ATF_TP_ADD_TC(tp, open_bad_path_pointer); 1944 ATF_TP_ADD_TC(tp, open_path_too_long); 1945 ATF_TP_ADD_TC(tp, open_nonexisting_object); 1946 ATF_TP_ADD_TC(tp, open_create_existing_object); 1947 ATF_TP_ADD_TC(tp, shm_functionality_across_fork); 1948 ATF_TP_ADD_TC(tp, trunc_resets_object); 1949 ATF_TP_ADD_TC(tp, unlink_bad_path_pointer); 1950 ATF_TP_ADD_TC(tp, unlink_path_too_long); 1951 ATF_TP_ADD_TC(tp, object_resize); 1952 ATF_TP_ADD_TC(tp, cloexec); 1953 ATF_TP_ADD_TC(tp, mode); 1954 ATF_TP_ADD_TC(tp, fallocate); 1955 ATF_TP_ADD_TC(tp, fspacectl); 1956 ATF_TP_ADD_TC(tp, accounting); 1957 ATF_TP_ADD_TC(tp, largepage_basic); 1958 ATF_TP_ADD_TC(tp, largepage_config); 1959 ATF_TP_ADD_TC(tp, largepage_mmap); 1960 ATF_TP_ADD_TC(tp, largepage_munmap); 1961 ATF_TP_ADD_TC(tp, largepage_madvise); 1962 ATF_TP_ADD_TC(tp, largepage_mlock); 1963 ATF_TP_ADD_TC(tp, largepage_msync); 1964 ATF_TP_ADD_TC(tp, largepage_mprotect); 1965 ATF_TP_ADD_TC(tp, largepage_minherit); 1966 ATF_TP_ADD_TC(tp, largepage_pipe); 1967 ATF_TP_ADD_TC(tp, largepage_reopen); 1968 1969 return (atf_no_error()); 1970 } 1971