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