1 // SPDX-License-Identifier: GPL-2.0-or-later 2 3 #define _GNU_SOURCE 4 #include "../kselftest_harness.h" 5 #include <asm-generic/mman.h> /* Force the import of the tools version. */ 6 #include <assert.h> 7 #include <errno.h> 8 #include <fcntl.h> 9 #include <linux/limits.h> 10 #include <linux/userfaultfd.h> 11 #include <setjmp.h> 12 #include <signal.h> 13 #include <stdbool.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <sys/ioctl.h> 18 #include <sys/mman.h> 19 #include <sys/syscall.h> 20 #include <sys/uio.h> 21 #include <unistd.h> 22 #include "vm_util.h" 23 24 #include "../pidfd/pidfd.h" 25 26 /* 27 * Ignore the checkpatch warning, as per the C99 standard, section 7.14.1.1: 28 * 29 * "If the signal occurs other than as the result of calling the abort or raise 30 * function, the behavior is undefined if the signal handler refers to any 31 * object with static storage duration other than by assigning a value to an 32 * object declared as volatile sig_atomic_t" 33 */ 34 static volatile sig_atomic_t signal_jump_set; 35 static sigjmp_buf signal_jmp_buf; 36 37 /* 38 * Ignore the checkpatch warning, we must read from x but don't want to do 39 * anything with it in order to trigger a read page fault. We therefore must use 40 * volatile to stop the compiler from optimising this away. 41 */ 42 #define FORCE_READ(x) (*(volatile typeof(x) *)x) 43 44 /* 45 * How is the test backing the mapping being tested? 46 */ 47 enum backing_type { 48 ANON_BACKED, 49 SHMEM_BACKED, 50 LOCAL_FILE_BACKED, 51 }; 52 53 FIXTURE(guard_regions) 54 { 55 unsigned long page_size; 56 char path[PATH_MAX]; 57 int fd; 58 }; 59 60 FIXTURE_VARIANT(guard_regions) 61 { 62 enum backing_type backing; 63 }; 64 65 FIXTURE_VARIANT_ADD(guard_regions, anon) 66 { 67 .backing = ANON_BACKED, 68 }; 69 70 FIXTURE_VARIANT_ADD(guard_regions, shmem) 71 { 72 .backing = SHMEM_BACKED, 73 }; 74 75 FIXTURE_VARIANT_ADD(guard_regions, file) 76 { 77 .backing = LOCAL_FILE_BACKED, 78 }; 79 80 static bool is_anon_backed(const FIXTURE_VARIANT(guard_regions) * variant) 81 { 82 switch (variant->backing) { 83 case ANON_BACKED: 84 case SHMEM_BACKED: 85 return true; 86 default: 87 return false; 88 } 89 } 90 91 static void *mmap_(FIXTURE_DATA(guard_regions) * self, 92 const FIXTURE_VARIANT(guard_regions) * variant, 93 void *addr, size_t length, int prot, int extra_flags, 94 off_t offset) 95 { 96 int fd; 97 int flags = extra_flags; 98 99 switch (variant->backing) { 100 case ANON_BACKED: 101 flags |= MAP_PRIVATE | MAP_ANON; 102 fd = -1; 103 break; 104 case SHMEM_BACKED: 105 case LOCAL_FILE_BACKED: 106 flags |= MAP_SHARED; 107 fd = self->fd; 108 break; 109 default: 110 ksft_exit_fail(); 111 break; 112 } 113 114 return mmap(addr, length, prot, flags, fd, offset); 115 } 116 117 static int userfaultfd(int flags) 118 { 119 return syscall(SYS_userfaultfd, flags); 120 } 121 122 static void handle_fatal(int c) 123 { 124 if (!signal_jump_set) 125 return; 126 127 siglongjmp(signal_jmp_buf, c); 128 } 129 130 static ssize_t sys_process_madvise(int pidfd, const struct iovec *iovec, 131 size_t n, int advice, unsigned int flags) 132 { 133 return syscall(__NR_process_madvise, pidfd, iovec, n, advice, flags); 134 } 135 136 /* 137 * Enable our signal catcher and try to read/write the specified buffer. The 138 * return value indicates whether the read/write succeeds without a fatal 139 * signal. 140 */ 141 static bool try_access_buf(char *ptr, bool write) 142 { 143 bool failed; 144 145 /* Tell signal handler to jump back here on fatal signal. */ 146 signal_jump_set = true; 147 /* If a fatal signal arose, we will jump back here and failed is set. */ 148 failed = sigsetjmp(signal_jmp_buf, 0) != 0; 149 150 if (!failed) { 151 if (write) 152 *ptr = 'x'; 153 else 154 FORCE_READ(ptr); 155 } 156 157 signal_jump_set = false; 158 return !failed; 159 } 160 161 /* Try and read from a buffer, return true if no fatal signal. */ 162 static bool try_read_buf(char *ptr) 163 { 164 return try_access_buf(ptr, false); 165 } 166 167 /* Try and write to a buffer, return true if no fatal signal. */ 168 static bool try_write_buf(char *ptr) 169 { 170 return try_access_buf(ptr, true); 171 } 172 173 /* 174 * Try and BOTH read from AND write to a buffer, return true if BOTH operations 175 * succeed. 176 */ 177 static bool try_read_write_buf(char *ptr) 178 { 179 return try_read_buf(ptr) && try_write_buf(ptr); 180 } 181 182 static void setup_sighandler(void) 183 { 184 struct sigaction act = { 185 .sa_handler = &handle_fatal, 186 .sa_flags = SA_NODEFER, 187 }; 188 189 sigemptyset(&act.sa_mask); 190 if (sigaction(SIGSEGV, &act, NULL)) 191 ksft_exit_fail_perror("sigaction"); 192 } 193 194 static void teardown_sighandler(void) 195 { 196 struct sigaction act = { 197 .sa_handler = SIG_DFL, 198 .sa_flags = SA_NODEFER, 199 }; 200 201 sigemptyset(&act.sa_mask); 202 sigaction(SIGSEGV, &act, NULL); 203 } 204 205 static int open_file(const char *prefix, char *path) 206 { 207 int fd; 208 209 snprintf(path, PATH_MAX, "%sguard_regions_test_file_XXXXXX", prefix); 210 fd = mkstemp(path); 211 if (fd < 0) 212 ksft_exit_fail_perror("mkstemp"); 213 214 return fd; 215 } 216 217 /* Establish a varying pattern in a buffer. */ 218 static void set_pattern(char *ptr, size_t num_pages, size_t page_size) 219 { 220 size_t i; 221 222 for (i = 0; i < num_pages; i++) { 223 char *ptr2 = &ptr[i * page_size]; 224 225 memset(ptr2, 'a' + (i % 26), page_size); 226 } 227 } 228 229 /* 230 * Check that a buffer contains the pattern set by set_pattern(), starting at a 231 * page offset of pgoff within the buffer. 232 */ 233 static bool check_pattern_offset(char *ptr, size_t num_pages, size_t page_size, 234 size_t pgoff) 235 { 236 size_t i; 237 238 for (i = 0; i < num_pages * page_size; i++) { 239 size_t offset = pgoff * page_size + i; 240 char actual = ptr[offset]; 241 char expected = 'a' + ((offset / page_size) % 26); 242 243 if (actual != expected) 244 return false; 245 } 246 247 return true; 248 } 249 250 /* Check that a buffer contains the pattern set by set_pattern(). */ 251 static bool check_pattern(char *ptr, size_t num_pages, size_t page_size) 252 { 253 return check_pattern_offset(ptr, num_pages, page_size, 0); 254 } 255 256 /* Determine if a buffer contains only repetitions of a specified char. */ 257 static bool is_buf_eq(char *buf, size_t size, char chr) 258 { 259 size_t i; 260 261 for (i = 0; i < size; i++) { 262 if (buf[i] != chr) 263 return false; 264 } 265 266 return true; 267 } 268 269 FIXTURE_SETUP(guard_regions) 270 { 271 self->page_size = (unsigned long)sysconf(_SC_PAGESIZE); 272 setup_sighandler(); 273 274 switch (variant->backing) { 275 case ANON_BACKED: 276 return; 277 case LOCAL_FILE_BACKED: 278 self->fd = open_file("", self->path); 279 break; 280 case SHMEM_BACKED: 281 self->fd = memfd_create(self->path, 0); 282 break; 283 } 284 285 /* We truncate file to at least 100 pages, tests can modify as needed. */ 286 ASSERT_EQ(ftruncate(self->fd, 100 * self->page_size), 0); 287 }; 288 289 FIXTURE_TEARDOWN_PARENT(guard_regions) 290 { 291 teardown_sighandler(); 292 293 if (variant->backing == ANON_BACKED) 294 return; 295 296 if (self->fd >= 0) 297 close(self->fd); 298 299 if (self->path[0] != '\0') 300 unlink(self->path); 301 } 302 303 TEST_F(guard_regions, basic) 304 { 305 const unsigned long NUM_PAGES = 10; 306 const unsigned long page_size = self->page_size; 307 char *ptr; 308 int i; 309 310 ptr = mmap_(self, variant, NULL, NUM_PAGES * page_size, 311 PROT_READ | PROT_WRITE, 0, 0); 312 ASSERT_NE(ptr, MAP_FAILED); 313 314 /* Trivially assert we can touch the first page. */ 315 ASSERT_TRUE(try_read_write_buf(ptr)); 316 317 ASSERT_EQ(madvise(ptr, page_size, MADV_GUARD_INSTALL), 0); 318 319 /* Establish that 1st page SIGSEGV's. */ 320 ASSERT_FALSE(try_read_write_buf(ptr)); 321 322 /* Ensure we can touch everything else.*/ 323 for (i = 1; i < NUM_PAGES; i++) { 324 char *curr = &ptr[i * page_size]; 325 326 ASSERT_TRUE(try_read_write_buf(curr)); 327 } 328 329 /* Establish a guard page at the end of the mapping. */ 330 ASSERT_EQ(madvise(&ptr[(NUM_PAGES - 1) * page_size], page_size, 331 MADV_GUARD_INSTALL), 0); 332 333 /* Check that both guard pages result in SIGSEGV. */ 334 ASSERT_FALSE(try_read_write_buf(ptr)); 335 ASSERT_FALSE(try_read_write_buf(&ptr[(NUM_PAGES - 1) * page_size])); 336 337 /* Remove the first guard page. */ 338 ASSERT_FALSE(madvise(ptr, page_size, MADV_GUARD_REMOVE)); 339 340 /* Make sure we can touch it. */ 341 ASSERT_TRUE(try_read_write_buf(ptr)); 342 343 /* Remove the last guard page. */ 344 ASSERT_FALSE(madvise(&ptr[(NUM_PAGES - 1) * page_size], page_size, 345 MADV_GUARD_REMOVE)); 346 347 /* Make sure we can touch it. */ 348 ASSERT_TRUE(try_read_write_buf(&ptr[(NUM_PAGES - 1) * page_size])); 349 350 /* 351 * Test setting a _range_ of pages, namely the first 3. The first of 352 * these be faulted in, so this also tests that we can install guard 353 * pages over backed pages. 354 */ 355 ASSERT_EQ(madvise(ptr, 3 * page_size, MADV_GUARD_INSTALL), 0); 356 357 /* Make sure they are all guard pages. */ 358 for (i = 0; i < 3; i++) { 359 char *curr = &ptr[i * page_size]; 360 361 ASSERT_FALSE(try_read_write_buf(curr)); 362 } 363 364 /* Make sure the rest are not. */ 365 for (i = 3; i < NUM_PAGES; i++) { 366 char *curr = &ptr[i * page_size]; 367 368 ASSERT_TRUE(try_read_write_buf(curr)); 369 } 370 371 /* Remove guard pages. */ 372 ASSERT_EQ(madvise(ptr, NUM_PAGES * page_size, MADV_GUARD_REMOVE), 0); 373 374 /* Now make sure we can touch everything. */ 375 for (i = 0; i < NUM_PAGES; i++) { 376 char *curr = &ptr[i * page_size]; 377 378 ASSERT_TRUE(try_read_write_buf(curr)); 379 } 380 381 /* 382 * Now remove all guard pages, make sure we don't remove existing 383 * entries. 384 */ 385 ASSERT_EQ(madvise(ptr, NUM_PAGES * page_size, MADV_GUARD_REMOVE), 0); 386 387 for (i = 0; i < NUM_PAGES * page_size; i += page_size) { 388 char chr = ptr[i]; 389 390 ASSERT_EQ(chr, 'x'); 391 } 392 393 ASSERT_EQ(munmap(ptr, NUM_PAGES * page_size), 0); 394 } 395 396 /* Assert that operations applied across multiple VMAs work as expected. */ 397 TEST_F(guard_regions, multi_vma) 398 { 399 const unsigned long page_size = self->page_size; 400 char *ptr_region, *ptr, *ptr1, *ptr2, *ptr3; 401 int i; 402 403 /* Reserve a 100 page region over which we can install VMAs. */ 404 ptr_region = mmap_(self, variant, NULL, 100 * page_size, 405 PROT_NONE, 0, 0); 406 ASSERT_NE(ptr_region, MAP_FAILED); 407 408 /* Place a VMA of 10 pages size at the start of the region. */ 409 ptr1 = mmap_(self, variant, ptr_region, 10 * page_size, 410 PROT_READ | PROT_WRITE, MAP_FIXED, 0); 411 ASSERT_NE(ptr1, MAP_FAILED); 412 413 /* Place a VMA of 5 pages size 50 pages into the region. */ 414 ptr2 = mmap_(self, variant, &ptr_region[50 * page_size], 5 * page_size, 415 PROT_READ | PROT_WRITE, MAP_FIXED, 0); 416 ASSERT_NE(ptr2, MAP_FAILED); 417 418 /* Place a VMA of 20 pages size at the end of the region. */ 419 ptr3 = mmap_(self, variant, &ptr_region[80 * page_size], 20 * page_size, 420 PROT_READ | PROT_WRITE, MAP_FIXED, 0); 421 ASSERT_NE(ptr3, MAP_FAILED); 422 423 /* Unmap gaps. */ 424 ASSERT_EQ(munmap(&ptr_region[10 * page_size], 40 * page_size), 0); 425 ASSERT_EQ(munmap(&ptr_region[55 * page_size], 25 * page_size), 0); 426 427 /* 428 * We end up with VMAs like this: 429 * 430 * 0 10 .. 50 55 .. 80 100 431 * [---] [---] [---] 432 */ 433 434 /* 435 * Now mark the whole range as guard pages and make sure all VMAs are as 436 * such. 437 */ 438 439 /* 440 * madvise() is certifiable and lets you perform operations over gaps, 441 * everything works, but it indicates an error and errno is set to 442 * -ENOMEM. Also if anything runs out of memory it is set to 443 * -ENOMEM. You are meant to guess which is which. 444 */ 445 ASSERT_EQ(madvise(ptr_region, 100 * page_size, MADV_GUARD_INSTALL), -1); 446 ASSERT_EQ(errno, ENOMEM); 447 448 for (i = 0; i < 10; i++) { 449 char *curr = &ptr1[i * page_size]; 450 451 ASSERT_FALSE(try_read_write_buf(curr)); 452 } 453 454 for (i = 0; i < 5; i++) { 455 char *curr = &ptr2[i * page_size]; 456 457 ASSERT_FALSE(try_read_write_buf(curr)); 458 } 459 460 for (i = 0; i < 20; i++) { 461 char *curr = &ptr3[i * page_size]; 462 463 ASSERT_FALSE(try_read_write_buf(curr)); 464 } 465 466 /* Now remove guar pages over range and assert the opposite. */ 467 468 ASSERT_EQ(madvise(ptr_region, 100 * page_size, MADV_GUARD_REMOVE), -1); 469 ASSERT_EQ(errno, ENOMEM); 470 471 for (i = 0; i < 10; i++) { 472 char *curr = &ptr1[i * page_size]; 473 474 ASSERT_TRUE(try_read_write_buf(curr)); 475 } 476 477 for (i = 0; i < 5; i++) { 478 char *curr = &ptr2[i * page_size]; 479 480 ASSERT_TRUE(try_read_write_buf(curr)); 481 } 482 483 for (i = 0; i < 20; i++) { 484 char *curr = &ptr3[i * page_size]; 485 486 ASSERT_TRUE(try_read_write_buf(curr)); 487 } 488 489 /* Now map incompatible VMAs in the gaps. */ 490 ptr = mmap_(self, variant, &ptr_region[10 * page_size], 40 * page_size, 491 PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED, 0); 492 ASSERT_NE(ptr, MAP_FAILED); 493 ptr = mmap_(self, variant, &ptr_region[55 * page_size], 25 * page_size, 494 PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED, 0); 495 ASSERT_NE(ptr, MAP_FAILED); 496 497 /* 498 * We end up with VMAs like this: 499 * 500 * 0 10 .. 50 55 .. 80 100 501 * [---][xxxx][---][xxxx][---] 502 * 503 * Where 'x' signifies VMAs that cannot be merged with those adjacent to 504 * them. 505 */ 506 507 /* Multiple VMAs adjacent to one another should result in no error. */ 508 ASSERT_EQ(madvise(ptr_region, 100 * page_size, MADV_GUARD_INSTALL), 0); 509 for (i = 0; i < 100; i++) { 510 char *curr = &ptr_region[i * page_size]; 511 512 ASSERT_FALSE(try_read_write_buf(curr)); 513 } 514 ASSERT_EQ(madvise(ptr_region, 100 * page_size, MADV_GUARD_REMOVE), 0); 515 for (i = 0; i < 100; i++) { 516 char *curr = &ptr_region[i * page_size]; 517 518 ASSERT_TRUE(try_read_write_buf(curr)); 519 } 520 521 /* Cleanup. */ 522 ASSERT_EQ(munmap(ptr_region, 100 * page_size), 0); 523 } 524 525 /* 526 * Assert that batched operations performed using process_madvise() work as 527 * expected. 528 */ 529 TEST_F(guard_regions, process_madvise) 530 { 531 const unsigned long page_size = self->page_size; 532 char *ptr_region, *ptr1, *ptr2, *ptr3; 533 ssize_t count; 534 struct iovec vec[6]; 535 536 /* Reserve region to map over. */ 537 ptr_region = mmap_(self, variant, NULL, 100 * page_size, 538 PROT_NONE, 0, 0); 539 ASSERT_NE(ptr_region, MAP_FAILED); 540 541 /* 542 * 10 pages offset 1 page into reserve region. We MAP_POPULATE so we 543 * overwrite existing entries and test this code path against 544 * overwriting existing entries. 545 */ 546 ptr1 = mmap_(self, variant, &ptr_region[page_size], 10 * page_size, 547 PROT_READ | PROT_WRITE, MAP_FIXED | MAP_POPULATE, 0); 548 ASSERT_NE(ptr1, MAP_FAILED); 549 /* We want guard markers at start/end of each VMA. */ 550 vec[0].iov_base = ptr1; 551 vec[0].iov_len = page_size; 552 vec[1].iov_base = &ptr1[9 * page_size]; 553 vec[1].iov_len = page_size; 554 555 /* 5 pages offset 50 pages into reserve region. */ 556 ptr2 = mmap_(self, variant, &ptr_region[50 * page_size], 5 * page_size, 557 PROT_READ | PROT_WRITE, MAP_FIXED, 0); 558 ASSERT_NE(ptr2, MAP_FAILED); 559 vec[2].iov_base = ptr2; 560 vec[2].iov_len = page_size; 561 vec[3].iov_base = &ptr2[4 * page_size]; 562 vec[3].iov_len = page_size; 563 564 /* 20 pages offset 79 pages into reserve region. */ 565 ptr3 = mmap_(self, variant, &ptr_region[79 * page_size], 20 * page_size, 566 PROT_READ | PROT_WRITE, MAP_FIXED, 0); 567 ASSERT_NE(ptr3, MAP_FAILED); 568 vec[4].iov_base = ptr3; 569 vec[4].iov_len = page_size; 570 vec[5].iov_base = &ptr3[19 * page_size]; 571 vec[5].iov_len = page_size; 572 573 /* Free surrounding VMAs. */ 574 ASSERT_EQ(munmap(ptr_region, page_size), 0); 575 ASSERT_EQ(munmap(&ptr_region[11 * page_size], 39 * page_size), 0); 576 ASSERT_EQ(munmap(&ptr_region[55 * page_size], 24 * page_size), 0); 577 ASSERT_EQ(munmap(&ptr_region[99 * page_size], page_size), 0); 578 579 /* Now guard in one step. */ 580 count = sys_process_madvise(PIDFD_SELF, vec, 6, MADV_GUARD_INSTALL, 0); 581 582 /* OK we don't have permission to do this, skip. */ 583 if (count == -1 && errno == EPERM) 584 ksft_exit_skip("No process_madvise() permissions, try running as root.\n"); 585 586 /* Returns the number of bytes advised. */ 587 ASSERT_EQ(count, 6 * page_size); 588 589 /* Now make sure the guarding was applied. */ 590 591 ASSERT_FALSE(try_read_write_buf(ptr1)); 592 ASSERT_FALSE(try_read_write_buf(&ptr1[9 * page_size])); 593 594 ASSERT_FALSE(try_read_write_buf(ptr2)); 595 ASSERT_FALSE(try_read_write_buf(&ptr2[4 * page_size])); 596 597 ASSERT_FALSE(try_read_write_buf(ptr3)); 598 ASSERT_FALSE(try_read_write_buf(&ptr3[19 * page_size])); 599 600 /* Now do the same with unguard... */ 601 count = sys_process_madvise(PIDFD_SELF, vec, 6, MADV_GUARD_REMOVE, 0); 602 603 /* ...and everything should now succeed. */ 604 605 ASSERT_TRUE(try_read_write_buf(ptr1)); 606 ASSERT_TRUE(try_read_write_buf(&ptr1[9 * page_size])); 607 608 ASSERT_TRUE(try_read_write_buf(ptr2)); 609 ASSERT_TRUE(try_read_write_buf(&ptr2[4 * page_size])); 610 611 ASSERT_TRUE(try_read_write_buf(ptr3)); 612 ASSERT_TRUE(try_read_write_buf(&ptr3[19 * page_size])); 613 614 /* Cleanup. */ 615 ASSERT_EQ(munmap(ptr1, 10 * page_size), 0); 616 ASSERT_EQ(munmap(ptr2, 5 * page_size), 0); 617 ASSERT_EQ(munmap(ptr3, 20 * page_size), 0); 618 } 619 620 /* Assert that unmapping ranges does not leave guard markers behind. */ 621 TEST_F(guard_regions, munmap) 622 { 623 const unsigned long page_size = self->page_size; 624 char *ptr, *ptr_new1, *ptr_new2; 625 626 ptr = mmap_(self, variant, NULL, 10 * page_size, 627 PROT_READ | PROT_WRITE, 0, 0); 628 ASSERT_NE(ptr, MAP_FAILED); 629 630 /* Guard first and last pages. */ 631 ASSERT_EQ(madvise(ptr, page_size, MADV_GUARD_INSTALL), 0); 632 ASSERT_EQ(madvise(&ptr[9 * page_size], page_size, MADV_GUARD_INSTALL), 0); 633 634 /* Assert that they are guarded. */ 635 ASSERT_FALSE(try_read_write_buf(ptr)); 636 ASSERT_FALSE(try_read_write_buf(&ptr[9 * page_size])); 637 638 /* Unmap them. */ 639 ASSERT_EQ(munmap(ptr, page_size), 0); 640 ASSERT_EQ(munmap(&ptr[9 * page_size], page_size), 0); 641 642 /* Map over them.*/ 643 ptr_new1 = mmap_(self, variant, ptr, page_size, PROT_READ | PROT_WRITE, 644 MAP_FIXED, 0); 645 ASSERT_NE(ptr_new1, MAP_FAILED); 646 ptr_new2 = mmap_(self, variant, &ptr[9 * page_size], page_size, 647 PROT_READ | PROT_WRITE, MAP_FIXED, 0); 648 ASSERT_NE(ptr_new2, MAP_FAILED); 649 650 /* Assert that they are now not guarded. */ 651 ASSERT_TRUE(try_read_write_buf(ptr_new1)); 652 ASSERT_TRUE(try_read_write_buf(ptr_new2)); 653 654 /* Cleanup. */ 655 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 656 } 657 658 /* Assert that mprotect() operations have no bearing on guard markers. */ 659 TEST_F(guard_regions, mprotect) 660 { 661 const unsigned long page_size = self->page_size; 662 char *ptr; 663 int i; 664 665 ptr = mmap_(self, variant, NULL, 10 * page_size, 666 PROT_READ | PROT_WRITE, 0, 0); 667 ASSERT_NE(ptr, MAP_FAILED); 668 669 /* Guard the middle of the range. */ 670 ASSERT_EQ(madvise(&ptr[5 * page_size], 2 * page_size, 671 MADV_GUARD_INSTALL), 0); 672 673 /* Assert that it is indeed guarded. */ 674 ASSERT_FALSE(try_read_write_buf(&ptr[5 * page_size])); 675 ASSERT_FALSE(try_read_write_buf(&ptr[6 * page_size])); 676 677 /* Now make these pages read-only. */ 678 ASSERT_EQ(mprotect(&ptr[5 * page_size], 2 * page_size, PROT_READ), 0); 679 680 /* Make sure the range is still guarded. */ 681 ASSERT_FALSE(try_read_buf(&ptr[5 * page_size])); 682 ASSERT_FALSE(try_read_buf(&ptr[6 * page_size])); 683 684 /* Make sure we can guard again without issue.*/ 685 ASSERT_EQ(madvise(&ptr[5 * page_size], 2 * page_size, 686 MADV_GUARD_INSTALL), 0); 687 688 /* Make sure the range is, yet again, still guarded. */ 689 ASSERT_FALSE(try_read_buf(&ptr[5 * page_size])); 690 ASSERT_FALSE(try_read_buf(&ptr[6 * page_size])); 691 692 /* Now unguard the whole range. */ 693 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0); 694 695 /* Make sure the whole range is readable. */ 696 for (i = 0; i < 10; i++) { 697 char *curr = &ptr[i * page_size]; 698 699 ASSERT_TRUE(try_read_buf(curr)); 700 } 701 702 /* Cleanup. */ 703 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 704 } 705 706 /* Split and merge VMAs and make sure guard pages still behave. */ 707 TEST_F(guard_regions, split_merge) 708 { 709 const unsigned long page_size = self->page_size; 710 char *ptr, *ptr_new; 711 int i; 712 713 ptr = mmap_(self, variant, NULL, 10 * page_size, 714 PROT_READ | PROT_WRITE, 0, 0); 715 ASSERT_NE(ptr, MAP_FAILED); 716 717 /* Guard the whole range. */ 718 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), 0); 719 720 /* Make sure the whole range is guarded. */ 721 for (i = 0; i < 10; i++) { 722 char *curr = &ptr[i * page_size]; 723 724 ASSERT_FALSE(try_read_write_buf(curr)); 725 } 726 727 /* Now unmap some pages in the range so we split. */ 728 ASSERT_EQ(munmap(&ptr[2 * page_size], page_size), 0); 729 ASSERT_EQ(munmap(&ptr[5 * page_size], page_size), 0); 730 ASSERT_EQ(munmap(&ptr[8 * page_size], page_size), 0); 731 732 /* Make sure the remaining ranges are guarded post-split. */ 733 for (i = 0; i < 2; i++) { 734 char *curr = &ptr[i * page_size]; 735 736 ASSERT_FALSE(try_read_write_buf(curr)); 737 } 738 for (i = 2; i < 5; i++) { 739 char *curr = &ptr[i * page_size]; 740 741 ASSERT_FALSE(try_read_write_buf(curr)); 742 } 743 for (i = 6; i < 8; i++) { 744 char *curr = &ptr[i * page_size]; 745 746 ASSERT_FALSE(try_read_write_buf(curr)); 747 } 748 for (i = 9; i < 10; i++) { 749 char *curr = &ptr[i * page_size]; 750 751 ASSERT_FALSE(try_read_write_buf(curr)); 752 } 753 754 /* Now map them again - the unmap will have cleared the guards. */ 755 ptr_new = mmap_(self, variant, &ptr[2 * page_size], page_size, 756 PROT_READ | PROT_WRITE, MAP_FIXED, 0); 757 ASSERT_NE(ptr_new, MAP_FAILED); 758 ptr_new = mmap_(self, variant, &ptr[5 * page_size], page_size, 759 PROT_READ | PROT_WRITE, MAP_FIXED, 0); 760 ASSERT_NE(ptr_new, MAP_FAILED); 761 ptr_new = mmap_(self, variant, &ptr[8 * page_size], page_size, 762 PROT_READ | PROT_WRITE, MAP_FIXED, 0); 763 ASSERT_NE(ptr_new, MAP_FAILED); 764 765 /* Now make sure guard pages are established. */ 766 for (i = 0; i < 10; i++) { 767 char *curr = &ptr[i * page_size]; 768 bool result = try_read_write_buf(curr); 769 bool expect_true = i == 2 || i == 5 || i == 8; 770 771 ASSERT_TRUE(expect_true ? result : !result); 772 } 773 774 /* Now guard everything again. */ 775 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), 0); 776 777 /* Make sure the whole range is guarded. */ 778 for (i = 0; i < 10; i++) { 779 char *curr = &ptr[i * page_size]; 780 781 ASSERT_FALSE(try_read_write_buf(curr)); 782 } 783 784 /* Now split the range into three. */ 785 ASSERT_EQ(mprotect(ptr, 3 * page_size, PROT_READ), 0); 786 ASSERT_EQ(mprotect(&ptr[7 * page_size], 3 * page_size, PROT_READ), 0); 787 788 /* Make sure the whole range is guarded for read. */ 789 for (i = 0; i < 10; i++) { 790 char *curr = &ptr[i * page_size]; 791 792 ASSERT_FALSE(try_read_buf(curr)); 793 } 794 795 /* Now reset protection bits so we merge the whole thing. */ 796 ASSERT_EQ(mprotect(ptr, 3 * page_size, PROT_READ | PROT_WRITE), 0); 797 ASSERT_EQ(mprotect(&ptr[7 * page_size], 3 * page_size, 798 PROT_READ | PROT_WRITE), 0); 799 800 /* Make sure the whole range is still guarded. */ 801 for (i = 0; i < 10; i++) { 802 char *curr = &ptr[i * page_size]; 803 804 ASSERT_FALSE(try_read_write_buf(curr)); 805 } 806 807 /* Split range into 3 again... */ 808 ASSERT_EQ(mprotect(ptr, 3 * page_size, PROT_READ), 0); 809 ASSERT_EQ(mprotect(&ptr[7 * page_size], 3 * page_size, PROT_READ), 0); 810 811 /* ...and unguard the whole range. */ 812 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0); 813 814 /* Make sure the whole range is remedied for read. */ 815 for (i = 0; i < 10; i++) { 816 char *curr = &ptr[i * page_size]; 817 818 ASSERT_TRUE(try_read_buf(curr)); 819 } 820 821 /* Merge them again. */ 822 ASSERT_EQ(mprotect(ptr, 3 * page_size, PROT_READ | PROT_WRITE), 0); 823 ASSERT_EQ(mprotect(&ptr[7 * page_size], 3 * page_size, 824 PROT_READ | PROT_WRITE), 0); 825 826 /* Now ensure the merged range is remedied for read/write. */ 827 for (i = 0; i < 10; i++) { 828 char *curr = &ptr[i * page_size]; 829 830 ASSERT_TRUE(try_read_write_buf(curr)); 831 } 832 833 /* Cleanup. */ 834 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 835 } 836 837 /* Assert that MADV_DONTNEED does not remove guard markers. */ 838 TEST_F(guard_regions, dontneed) 839 { 840 const unsigned long page_size = self->page_size; 841 char *ptr; 842 int i; 843 844 ptr = mmap_(self, variant, NULL, 10 * page_size, 845 PROT_READ | PROT_WRITE, 0, 0); 846 ASSERT_NE(ptr, MAP_FAILED); 847 848 /* Back the whole range. */ 849 for (i = 0; i < 10; i++) { 850 char *curr = &ptr[i * page_size]; 851 852 *curr = 'y'; 853 } 854 855 /* Guard every other page. */ 856 for (i = 0; i < 10; i += 2) { 857 char *curr = &ptr[i * page_size]; 858 int res = madvise(curr, page_size, MADV_GUARD_INSTALL); 859 860 ASSERT_EQ(res, 0); 861 } 862 863 /* Indicate that we don't need any of the range. */ 864 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_DONTNEED), 0); 865 866 /* Check to ensure guard markers are still in place. */ 867 for (i = 0; i < 10; i++) { 868 char *curr = &ptr[i * page_size]; 869 bool result = try_read_buf(curr); 870 871 if (i % 2 == 0) { 872 ASSERT_FALSE(result); 873 } else { 874 ASSERT_TRUE(result); 875 switch (variant->backing) { 876 case ANON_BACKED: 877 /* If anon, then we get a zero page. */ 878 ASSERT_EQ(*curr, '\0'); 879 break; 880 default: 881 /* Otherwise, we get the file data. */ 882 ASSERT_EQ(*curr, 'y'); 883 break; 884 } 885 } 886 887 /* Now write... */ 888 result = try_write_buf(&ptr[i * page_size]); 889 890 /* ...and make sure same result. */ 891 ASSERT_TRUE(i % 2 != 0 ? result : !result); 892 } 893 894 /* Cleanup. */ 895 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 896 } 897 898 /* Assert that mlock()'ed pages work correctly with guard markers. */ 899 TEST_F(guard_regions, mlock) 900 { 901 const unsigned long page_size = self->page_size; 902 char *ptr; 903 int i; 904 905 ptr = mmap_(self, variant, NULL, 10 * page_size, 906 PROT_READ | PROT_WRITE, 0, 0); 907 ASSERT_NE(ptr, MAP_FAILED); 908 909 /* Populate. */ 910 for (i = 0; i < 10; i++) { 911 char *curr = &ptr[i * page_size]; 912 913 *curr = 'y'; 914 } 915 916 /* Lock. */ 917 ASSERT_EQ(mlock(ptr, 10 * page_size), 0); 918 919 /* Now try to guard, should fail with EINVAL. */ 920 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), -1); 921 ASSERT_EQ(errno, EINVAL); 922 923 /* OK unlock. */ 924 ASSERT_EQ(munlock(ptr, 10 * page_size), 0); 925 926 /* Guard first half of range, should now succeed. */ 927 ASSERT_EQ(madvise(ptr, 5 * page_size, MADV_GUARD_INSTALL), 0); 928 929 /* Make sure guard works. */ 930 for (i = 0; i < 10; i++) { 931 char *curr = &ptr[i * page_size]; 932 bool result = try_read_write_buf(curr); 933 934 if (i < 5) { 935 ASSERT_FALSE(result); 936 } else { 937 ASSERT_TRUE(result); 938 ASSERT_EQ(*curr, 'x'); 939 } 940 } 941 942 /* 943 * Now lock the latter part of the range. We can't lock the guard pages, 944 * as this would result in the pages being populated and the guarding 945 * would cause this to error out. 946 */ 947 ASSERT_EQ(mlock(&ptr[5 * page_size], 5 * page_size), 0); 948 949 /* 950 * Now remove guard pages, we permit mlock()'d ranges to have guard 951 * pages removed as it is a non-destructive operation. 952 */ 953 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0); 954 955 /* Now check that no guard pages remain. */ 956 for (i = 0; i < 10; i++) { 957 char *curr = &ptr[i * page_size]; 958 959 ASSERT_TRUE(try_read_write_buf(curr)); 960 } 961 962 /* Cleanup. */ 963 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 964 } 965 966 /* 967 * Assert that moving, extending and shrinking memory via mremap() retains 968 * guard markers where possible. 969 * 970 * - Moving a mapping alone should retain markers as they are. 971 */ 972 TEST_F(guard_regions, mremap_move) 973 { 974 const unsigned long page_size = self->page_size; 975 char *ptr, *ptr_new; 976 977 /* Map 5 pages. */ 978 ptr = mmap_(self, variant, NULL, 5 * page_size, 979 PROT_READ | PROT_WRITE, 0, 0); 980 ASSERT_NE(ptr, MAP_FAILED); 981 982 /* Place guard markers at both ends of the 5 page span. */ 983 ASSERT_EQ(madvise(ptr, page_size, MADV_GUARD_INSTALL), 0); 984 ASSERT_EQ(madvise(&ptr[4 * page_size], page_size, MADV_GUARD_INSTALL), 0); 985 986 /* Make sure the guard pages are in effect. */ 987 ASSERT_FALSE(try_read_write_buf(ptr)); 988 ASSERT_FALSE(try_read_write_buf(&ptr[4 * page_size])); 989 990 /* Map a new region we will move this range into. Doing this ensures 991 * that we have reserved a range to map into. 992 */ 993 ptr_new = mmap_(self, variant, NULL, 5 * page_size, PROT_NONE, 0, 0); 994 ASSERT_NE(ptr_new, MAP_FAILED); 995 996 ASSERT_EQ(mremap(ptr, 5 * page_size, 5 * page_size, 997 MREMAP_MAYMOVE | MREMAP_FIXED, ptr_new), ptr_new); 998 999 /* Make sure the guard markers are retained. */ 1000 ASSERT_FALSE(try_read_write_buf(ptr_new)); 1001 ASSERT_FALSE(try_read_write_buf(&ptr_new[4 * page_size])); 1002 1003 /* 1004 * Clean up - we only need reference the new pointer as we overwrote the 1005 * PROT_NONE range and moved the existing one. 1006 */ 1007 munmap(ptr_new, 5 * page_size); 1008 } 1009 1010 /* 1011 * Assert that moving, extending and shrinking memory via mremap() retains 1012 * guard markers where possible. 1013 * 1014 * Expanding should retain guard pages, only now in different position. The user 1015 * will have to remove guard pages manually to fix up (they'd have to do the 1016 * same if it were a PROT_NONE mapping). 1017 */ 1018 TEST_F(guard_regions, mremap_expand) 1019 { 1020 const unsigned long page_size = self->page_size; 1021 char *ptr, *ptr_new; 1022 1023 /* Map 10 pages... */ 1024 ptr = mmap_(self, variant, NULL, 10 * page_size, 1025 PROT_READ | PROT_WRITE, 0, 0); 1026 ASSERT_NE(ptr, MAP_FAILED); 1027 /* ...But unmap the last 5 so we can ensure we can expand into them. */ 1028 ASSERT_EQ(munmap(&ptr[5 * page_size], 5 * page_size), 0); 1029 1030 /* Place guard markers at both ends of the 5 page span. */ 1031 ASSERT_EQ(madvise(ptr, page_size, MADV_GUARD_INSTALL), 0); 1032 ASSERT_EQ(madvise(&ptr[4 * page_size], page_size, MADV_GUARD_INSTALL), 0); 1033 1034 /* Make sure the guarding is in effect. */ 1035 ASSERT_FALSE(try_read_write_buf(ptr)); 1036 ASSERT_FALSE(try_read_write_buf(&ptr[4 * page_size])); 1037 1038 /* Now expand to 10 pages. */ 1039 ptr = mremap(ptr, 5 * page_size, 10 * page_size, 0); 1040 ASSERT_NE(ptr, MAP_FAILED); 1041 1042 /* 1043 * Make sure the guard markers are retained in their original positions. 1044 */ 1045 ASSERT_FALSE(try_read_write_buf(ptr)); 1046 ASSERT_FALSE(try_read_write_buf(&ptr[4 * page_size])); 1047 1048 /* Reserve a region which we can move to and expand into. */ 1049 ptr_new = mmap_(self, variant, NULL, 20 * page_size, PROT_NONE, 0, 0); 1050 ASSERT_NE(ptr_new, MAP_FAILED); 1051 1052 /* Now move and expand into it. */ 1053 ptr = mremap(ptr, 10 * page_size, 20 * page_size, 1054 MREMAP_MAYMOVE | MREMAP_FIXED, ptr_new); 1055 ASSERT_EQ(ptr, ptr_new); 1056 1057 /* 1058 * Again, make sure the guard markers are retained in their original positions. 1059 */ 1060 ASSERT_FALSE(try_read_write_buf(ptr)); 1061 ASSERT_FALSE(try_read_write_buf(&ptr[4 * page_size])); 1062 1063 /* 1064 * A real user would have to remove guard markers, but would reasonably 1065 * expect all characteristics of the mapping to be retained, including 1066 * guard markers. 1067 */ 1068 1069 /* Cleanup. */ 1070 munmap(ptr, 20 * page_size); 1071 } 1072 /* 1073 * Assert that moving, extending and shrinking memory via mremap() retains 1074 * guard markers where possible. 1075 * 1076 * Shrinking will result in markers that are shrunk over being removed. Again, 1077 * if the user were using a PROT_NONE mapping they'd have to manually fix this 1078 * up also so this is OK. 1079 */ 1080 TEST_F(guard_regions, mremap_shrink) 1081 { 1082 const unsigned long page_size = self->page_size; 1083 char *ptr; 1084 int i; 1085 1086 /* Map 5 pages. */ 1087 ptr = mmap_(self, variant, NULL, 5 * page_size, 1088 PROT_READ | PROT_WRITE, 0, 0); 1089 ASSERT_NE(ptr, MAP_FAILED); 1090 1091 /* Place guard markers at both ends of the 5 page span. */ 1092 ASSERT_EQ(madvise(ptr, page_size, MADV_GUARD_INSTALL), 0); 1093 ASSERT_EQ(madvise(&ptr[4 * page_size], page_size, MADV_GUARD_INSTALL), 0); 1094 1095 /* Make sure the guarding is in effect. */ 1096 ASSERT_FALSE(try_read_write_buf(ptr)); 1097 ASSERT_FALSE(try_read_write_buf(&ptr[4 * page_size])); 1098 1099 /* Now shrink to 3 pages. */ 1100 ptr = mremap(ptr, 5 * page_size, 3 * page_size, MREMAP_MAYMOVE); 1101 ASSERT_NE(ptr, MAP_FAILED); 1102 1103 /* We expect the guard marker at the start to be retained... */ 1104 ASSERT_FALSE(try_read_write_buf(ptr)); 1105 1106 /* ...But remaining pages will not have guard markers. */ 1107 for (i = 1; i < 3; i++) { 1108 char *curr = &ptr[i * page_size]; 1109 1110 ASSERT_TRUE(try_read_write_buf(curr)); 1111 } 1112 1113 /* 1114 * As with expansion, a real user would have to remove guard pages and 1115 * fixup. But you'd have to do similar manual things with PROT_NONE 1116 * mappings too. 1117 */ 1118 1119 /* 1120 * If we expand back to the original size, the end marker will, of 1121 * course, no longer be present. 1122 */ 1123 ptr = mremap(ptr, 3 * page_size, 5 * page_size, 0); 1124 ASSERT_NE(ptr, MAP_FAILED); 1125 1126 /* Again, we expect the guard marker at the start to be retained... */ 1127 ASSERT_FALSE(try_read_write_buf(ptr)); 1128 1129 /* ...But remaining pages will not have guard markers. */ 1130 for (i = 1; i < 5; i++) { 1131 char *curr = &ptr[i * page_size]; 1132 1133 ASSERT_TRUE(try_read_write_buf(curr)); 1134 } 1135 1136 /* Cleanup. */ 1137 munmap(ptr, 5 * page_size); 1138 } 1139 1140 /* 1141 * Assert that forking a process with VMAs that do not have VM_WIPEONFORK set 1142 * retain guard pages. 1143 */ 1144 TEST_F(guard_regions, fork) 1145 { 1146 const unsigned long page_size = self->page_size; 1147 char *ptr; 1148 pid_t pid; 1149 int i; 1150 1151 /* Map 10 pages. */ 1152 ptr = mmap_(self, variant, NULL, 10 * page_size, 1153 PROT_READ | PROT_WRITE, 0, 0); 1154 ASSERT_NE(ptr, MAP_FAILED); 1155 1156 /* Establish guard pages in the first 5 pages. */ 1157 ASSERT_EQ(madvise(ptr, 5 * page_size, MADV_GUARD_INSTALL), 0); 1158 1159 pid = fork(); 1160 ASSERT_NE(pid, -1); 1161 if (!pid) { 1162 /* This is the child process now. */ 1163 1164 /* Assert that the guarding is in effect. */ 1165 for (i = 0; i < 10; i++) { 1166 char *curr = &ptr[i * page_size]; 1167 bool result = try_read_write_buf(curr); 1168 1169 ASSERT_TRUE(i >= 5 ? result : !result); 1170 } 1171 1172 /* Now unguard the range.*/ 1173 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0); 1174 1175 exit(0); 1176 } 1177 1178 /* Parent process. */ 1179 1180 /* Parent simply waits on child. */ 1181 waitpid(pid, NULL, 0); 1182 1183 /* Child unguard does not impact parent page table state. */ 1184 for (i = 0; i < 10; i++) { 1185 char *curr = &ptr[i * page_size]; 1186 bool result = try_read_write_buf(curr); 1187 1188 ASSERT_TRUE(i >= 5 ? result : !result); 1189 } 1190 1191 /* Cleanup. */ 1192 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1193 } 1194 1195 /* 1196 * Assert expected behaviour after we fork populated ranges of anonymous memory 1197 * and then guard and unguard the range. 1198 */ 1199 TEST_F(guard_regions, fork_cow) 1200 { 1201 const unsigned long page_size = self->page_size; 1202 char *ptr; 1203 pid_t pid; 1204 int i; 1205 1206 if (variant->backing != ANON_BACKED) 1207 SKIP(return, "CoW only supported on anon mappings"); 1208 1209 /* Map 10 pages. */ 1210 ptr = mmap_(self, variant, NULL, 10 * page_size, 1211 PROT_READ | PROT_WRITE, 0, 0); 1212 ASSERT_NE(ptr, MAP_FAILED); 1213 1214 /* Populate range. */ 1215 for (i = 0; i < 10 * page_size; i++) { 1216 char chr = 'a' + (i % 26); 1217 1218 ptr[i] = chr; 1219 } 1220 1221 pid = fork(); 1222 ASSERT_NE(pid, -1); 1223 if (!pid) { 1224 /* This is the child process now. */ 1225 1226 /* Ensure the range is as expected. */ 1227 for (i = 0; i < 10 * page_size; i++) { 1228 char expected = 'a' + (i % 26); 1229 char actual = ptr[i]; 1230 1231 ASSERT_EQ(actual, expected); 1232 } 1233 1234 /* Establish guard pages across the whole range. */ 1235 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), 0); 1236 /* Remove it. */ 1237 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0); 1238 1239 /* 1240 * By removing the guard pages, the page tables will be 1241 * cleared. Assert that we are looking at the zero page now. 1242 */ 1243 for (i = 0; i < 10 * page_size; i++) { 1244 char actual = ptr[i]; 1245 1246 ASSERT_EQ(actual, '\0'); 1247 } 1248 1249 exit(0); 1250 } 1251 1252 /* Parent process. */ 1253 1254 /* Parent simply waits on child. */ 1255 waitpid(pid, NULL, 0); 1256 1257 /* Ensure the range is unchanged in parent anon range. */ 1258 for (i = 0; i < 10 * page_size; i++) { 1259 char expected = 'a' + (i % 26); 1260 char actual = ptr[i]; 1261 1262 ASSERT_EQ(actual, expected); 1263 } 1264 1265 /* Cleanup. */ 1266 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1267 } 1268 1269 /* 1270 * Assert that forking a process with VMAs that do have VM_WIPEONFORK set 1271 * behave as expected. 1272 */ 1273 TEST_F(guard_regions, fork_wipeonfork) 1274 { 1275 const unsigned long page_size = self->page_size; 1276 char *ptr; 1277 pid_t pid; 1278 int i; 1279 1280 if (variant->backing != ANON_BACKED) 1281 SKIP(return, "Wipe on fork only supported on anon mappings"); 1282 1283 /* Map 10 pages. */ 1284 ptr = mmap_(self, variant, NULL, 10 * page_size, 1285 PROT_READ | PROT_WRITE, 0, 0); 1286 ASSERT_NE(ptr, MAP_FAILED); 1287 1288 /* Mark wipe on fork. */ 1289 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_WIPEONFORK), 0); 1290 1291 /* Guard the first 5 pages. */ 1292 ASSERT_EQ(madvise(ptr, 5 * page_size, MADV_GUARD_INSTALL), 0); 1293 1294 pid = fork(); 1295 ASSERT_NE(pid, -1); 1296 if (!pid) { 1297 /* This is the child process now. */ 1298 1299 /* Guard will have been wiped. */ 1300 for (i = 0; i < 10; i++) { 1301 char *curr = &ptr[i * page_size]; 1302 1303 ASSERT_TRUE(try_read_write_buf(curr)); 1304 } 1305 1306 exit(0); 1307 } 1308 1309 /* Parent process. */ 1310 1311 waitpid(pid, NULL, 0); 1312 1313 /* Guard markers should be in effect.*/ 1314 for (i = 0; i < 10; i++) { 1315 char *curr = &ptr[i * page_size]; 1316 bool result = try_read_write_buf(curr); 1317 1318 ASSERT_TRUE(i >= 5 ? result : !result); 1319 } 1320 1321 /* Cleanup. */ 1322 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1323 } 1324 1325 /* Ensure that MADV_FREE retains guard entries as expected. */ 1326 TEST_F(guard_regions, lazyfree) 1327 { 1328 const unsigned long page_size = self->page_size; 1329 char *ptr; 1330 int i; 1331 1332 if (variant->backing != ANON_BACKED) 1333 SKIP(return, "MADV_FREE only supported on anon mappings"); 1334 1335 /* Map 10 pages. */ 1336 ptr = mmap_(self, variant, NULL, 10 * page_size, 1337 PROT_READ | PROT_WRITE, 0, 0); 1338 ASSERT_NE(ptr, MAP_FAILED); 1339 1340 /* Guard range. */ 1341 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), 0); 1342 1343 /* Ensure guarded. */ 1344 for (i = 0; i < 10; i++) { 1345 char *curr = &ptr[i * page_size]; 1346 1347 ASSERT_FALSE(try_read_write_buf(curr)); 1348 } 1349 1350 /* Lazyfree range. */ 1351 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_FREE), 0); 1352 1353 /* This should leave the guard markers in place. */ 1354 for (i = 0; i < 10; i++) { 1355 char *curr = &ptr[i * page_size]; 1356 1357 ASSERT_FALSE(try_read_write_buf(curr)); 1358 } 1359 1360 /* Cleanup. */ 1361 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1362 } 1363 1364 /* Ensure that MADV_POPULATE_READ, MADV_POPULATE_WRITE behave as expected. */ 1365 TEST_F(guard_regions, populate) 1366 { 1367 const unsigned long page_size = self->page_size; 1368 char *ptr; 1369 1370 /* Map 10 pages. */ 1371 ptr = mmap_(self, variant, NULL, 10 * page_size, 1372 PROT_READ | PROT_WRITE, 0, 0); 1373 ASSERT_NE(ptr, MAP_FAILED); 1374 1375 /* Guard range. */ 1376 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), 0); 1377 1378 /* Populate read should error out... */ 1379 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_POPULATE_READ), -1); 1380 ASSERT_EQ(errno, EFAULT); 1381 1382 /* ...as should populate write. */ 1383 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_POPULATE_WRITE), -1); 1384 ASSERT_EQ(errno, EFAULT); 1385 1386 /* Cleanup. */ 1387 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1388 } 1389 1390 /* Ensure that MADV_COLD, MADV_PAGEOUT do not remove guard markers. */ 1391 TEST_F(guard_regions, cold_pageout) 1392 { 1393 const unsigned long page_size = self->page_size; 1394 char *ptr; 1395 int i; 1396 1397 /* Map 10 pages. */ 1398 ptr = mmap_(self, variant, NULL, 10 * page_size, 1399 PROT_READ | PROT_WRITE, 0, 0); 1400 ASSERT_NE(ptr, MAP_FAILED); 1401 1402 /* Guard range. */ 1403 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), 0); 1404 1405 /* Ensured guarded. */ 1406 for (i = 0; i < 10; i++) { 1407 char *curr = &ptr[i * page_size]; 1408 1409 ASSERT_FALSE(try_read_write_buf(curr)); 1410 } 1411 1412 /* Now mark cold. This should have no impact on guard markers. */ 1413 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_COLD), 0); 1414 1415 /* Should remain guarded. */ 1416 for (i = 0; i < 10; i++) { 1417 char *curr = &ptr[i * page_size]; 1418 1419 ASSERT_FALSE(try_read_write_buf(curr)); 1420 } 1421 1422 /* OK, now page out. This should equally, have no effect on markers. */ 1423 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_PAGEOUT), 0); 1424 1425 /* Should remain guarded. */ 1426 for (i = 0; i < 10; i++) { 1427 char *curr = &ptr[i * page_size]; 1428 1429 ASSERT_FALSE(try_read_write_buf(curr)); 1430 } 1431 1432 /* Cleanup. */ 1433 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1434 } 1435 1436 /* Ensure that guard pages do not break userfaultd. */ 1437 TEST_F(guard_regions, uffd) 1438 { 1439 const unsigned long page_size = self->page_size; 1440 int uffd; 1441 char *ptr; 1442 int i; 1443 struct uffdio_api api = { 1444 .api = UFFD_API, 1445 .features = 0, 1446 }; 1447 struct uffdio_register reg; 1448 struct uffdio_range range; 1449 1450 if (!is_anon_backed(variant)) 1451 SKIP(return, "uffd only works on anon backing"); 1452 1453 /* Set up uffd. */ 1454 uffd = userfaultfd(0); 1455 if (uffd == -1 && errno == EPERM) 1456 ksft_exit_skip("No userfaultfd permissions, try running as root.\n"); 1457 ASSERT_NE(uffd, -1); 1458 1459 ASSERT_EQ(ioctl(uffd, UFFDIO_API, &api), 0); 1460 1461 /* Map 10 pages. */ 1462 ptr = mmap_(self, variant, NULL, 10 * page_size, 1463 PROT_READ | PROT_WRITE, 0, 0); 1464 ASSERT_NE(ptr, MAP_FAILED); 1465 1466 /* Register the range with uffd. */ 1467 range.start = (unsigned long)ptr; 1468 range.len = 10 * page_size; 1469 reg.range = range; 1470 reg.mode = UFFDIO_REGISTER_MODE_MISSING; 1471 ASSERT_EQ(ioctl(uffd, UFFDIO_REGISTER, ®), 0); 1472 1473 /* Guard the range. This should not trigger the uffd. */ 1474 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), 0); 1475 1476 /* The guarding should behave as usual with no uffd intervention. */ 1477 for (i = 0; i < 10; i++) { 1478 char *curr = &ptr[i * page_size]; 1479 1480 ASSERT_FALSE(try_read_write_buf(curr)); 1481 } 1482 1483 /* Cleanup. */ 1484 ASSERT_EQ(ioctl(uffd, UFFDIO_UNREGISTER, &range), 0); 1485 close(uffd); 1486 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1487 } 1488 1489 /* 1490 * Mark a region within a file-backed mapping using MADV_SEQUENTIAL so we 1491 * aggressively read-ahead, then install guard regions and assert that it 1492 * behaves correctly. 1493 * 1494 * We page out using MADV_PAGEOUT before checking guard regions so we drop page 1495 * cache folios, meaning we maximise the possibility of some broken readahead. 1496 */ 1497 TEST_F(guard_regions, madvise_sequential) 1498 { 1499 char *ptr; 1500 int i; 1501 const unsigned long page_size = self->page_size; 1502 1503 if (variant->backing == ANON_BACKED) 1504 SKIP(return, "MADV_SEQUENTIAL meaningful only for file-backed"); 1505 1506 ptr = mmap_(self, variant, NULL, 10 * page_size, 1507 PROT_READ | PROT_WRITE, 0, 0); 1508 ASSERT_NE(ptr, MAP_FAILED); 1509 1510 /* Establish a pattern of data in the file. */ 1511 set_pattern(ptr, 10, page_size); 1512 ASSERT_TRUE(check_pattern(ptr, 10, page_size)); 1513 1514 /* Mark it as being accessed sequentially. */ 1515 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_SEQUENTIAL), 0); 1516 1517 /* Mark every other page a guard page. */ 1518 for (i = 0; i < 10; i += 2) { 1519 char *ptr2 = &ptr[i * page_size]; 1520 1521 ASSERT_EQ(madvise(ptr2, page_size, MADV_GUARD_INSTALL), 0); 1522 } 1523 1524 /* Now page it out. */ 1525 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_PAGEOUT), 0); 1526 1527 /* Now make sure pages are as expected. */ 1528 for (i = 0; i < 10; i++) { 1529 char *chrp = &ptr[i * page_size]; 1530 1531 if (i % 2 == 0) { 1532 bool result = try_read_write_buf(chrp); 1533 1534 ASSERT_FALSE(result); 1535 } else { 1536 ASSERT_EQ(*chrp, 'a' + i); 1537 } 1538 } 1539 1540 /* Now remove guard pages. */ 1541 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0); 1542 1543 /* Now make sure all data is as expected. */ 1544 if (!check_pattern(ptr, 10, page_size)) 1545 ASSERT_TRUE(false); 1546 1547 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1548 } 1549 1550 /* 1551 * Check that file-backed mappings implement guard regions with MAP_PRIVATE 1552 * correctly. 1553 */ 1554 TEST_F(guard_regions, map_private) 1555 { 1556 const unsigned long page_size = self->page_size; 1557 char *ptr_shared, *ptr_private; 1558 int i; 1559 1560 if (variant->backing == ANON_BACKED) 1561 SKIP(return, "MAP_PRIVATE test specific to file-backed"); 1562 1563 ptr_shared = mmap_(self, variant, NULL, 10 * page_size, PROT_READ | PROT_WRITE, 0, 0); 1564 ASSERT_NE(ptr_shared, MAP_FAILED); 1565 1566 /* Manually mmap(), do not use mmap_() wrapper so we can force MAP_PRIVATE. */ 1567 ptr_private = mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, self->fd, 0); 1568 ASSERT_NE(ptr_private, MAP_FAILED); 1569 1570 /* Set pattern in shared mapping. */ 1571 set_pattern(ptr_shared, 10, page_size); 1572 1573 /* Install guard regions in every other page in the shared mapping. */ 1574 for (i = 0; i < 10; i += 2) { 1575 char *ptr = &ptr_shared[i * page_size]; 1576 1577 ASSERT_EQ(madvise(ptr, page_size, MADV_GUARD_INSTALL), 0); 1578 } 1579 1580 for (i = 0; i < 10; i++) { 1581 /* Every even shared page should be guarded. */ 1582 ASSERT_EQ(try_read_buf(&ptr_shared[i * page_size]), i % 2 != 0); 1583 /* Private mappings should always be readable. */ 1584 ASSERT_TRUE(try_read_buf(&ptr_private[i * page_size])); 1585 } 1586 1587 /* Install guard regions in every other page in the private mapping. */ 1588 for (i = 0; i < 10; i += 2) { 1589 char *ptr = &ptr_private[i * page_size]; 1590 1591 ASSERT_EQ(madvise(ptr, page_size, MADV_GUARD_INSTALL), 0); 1592 } 1593 1594 for (i = 0; i < 10; i++) { 1595 /* Every even shared page should be guarded. */ 1596 ASSERT_EQ(try_read_buf(&ptr_shared[i * page_size]), i % 2 != 0); 1597 /* Every odd private page should be guarded. */ 1598 ASSERT_EQ(try_read_buf(&ptr_private[i * page_size]), i % 2 != 0); 1599 } 1600 1601 /* Remove guard regions from shared mapping. */ 1602 ASSERT_EQ(madvise(ptr_shared, 10 * page_size, MADV_GUARD_REMOVE), 0); 1603 1604 for (i = 0; i < 10; i++) { 1605 /* Shared mappings should always be readable. */ 1606 ASSERT_TRUE(try_read_buf(&ptr_shared[i * page_size])); 1607 /* Every even private page should be guarded. */ 1608 ASSERT_EQ(try_read_buf(&ptr_private[i * page_size]), i % 2 != 0); 1609 } 1610 1611 /* Remove guard regions from private mapping. */ 1612 ASSERT_EQ(madvise(ptr_private, 10 * page_size, MADV_GUARD_REMOVE), 0); 1613 1614 for (i = 0; i < 10; i++) { 1615 /* Shared mappings should always be readable. */ 1616 ASSERT_TRUE(try_read_buf(&ptr_shared[i * page_size])); 1617 /* Private mappings should always be readable. */ 1618 ASSERT_TRUE(try_read_buf(&ptr_private[i * page_size])); 1619 } 1620 1621 /* Ensure patterns are intact. */ 1622 ASSERT_TRUE(check_pattern(ptr_shared, 10, page_size)); 1623 ASSERT_TRUE(check_pattern(ptr_private, 10, page_size)); 1624 1625 /* Now write out every other page to MAP_PRIVATE. */ 1626 for (i = 0; i < 10; i += 2) { 1627 char *ptr = &ptr_private[i * page_size]; 1628 1629 memset(ptr, 'a' + i, page_size); 1630 } 1631 1632 /* 1633 * At this point the mapping is: 1634 * 1635 * 0123456789 1636 * SPSPSPSPSP 1637 * 1638 * Where S = shared, P = private mappings. 1639 */ 1640 1641 /* Now mark the beginning of the mapping guarded. */ 1642 ASSERT_EQ(madvise(ptr_private, 5 * page_size, MADV_GUARD_INSTALL), 0); 1643 1644 /* 1645 * This renders the mapping: 1646 * 1647 * 0123456789 1648 * xxxxxPSPSP 1649 */ 1650 1651 for (i = 0; i < 10; i++) { 1652 char *ptr = &ptr_private[i * page_size]; 1653 1654 /* Ensure guard regions as expected. */ 1655 ASSERT_EQ(try_read_buf(ptr), i >= 5); 1656 /* The shared mapping should always succeed. */ 1657 ASSERT_TRUE(try_read_buf(&ptr_shared[i * page_size])); 1658 } 1659 1660 /* Remove the guard regions altogether. */ 1661 ASSERT_EQ(madvise(ptr_private, 10 * page_size, MADV_GUARD_REMOVE), 0); 1662 1663 /* 1664 * 1665 * We now expect the mapping to be: 1666 * 1667 * 0123456789 1668 * SSSSSPSPSP 1669 * 1670 * As we removed guard regions, the private pages from the first 5 will 1671 * have been zapped, so on fault will reestablish the shared mapping. 1672 */ 1673 1674 for (i = 0; i < 10; i++) { 1675 char *ptr = &ptr_private[i * page_size]; 1676 1677 /* 1678 * Assert that shared mappings in the MAP_PRIVATE mapping match 1679 * the shared mapping. 1680 */ 1681 if (i < 5 || i % 2 == 0) { 1682 char *ptr_s = &ptr_shared[i * page_size]; 1683 1684 ASSERT_EQ(memcmp(ptr, ptr_s, page_size), 0); 1685 continue; 1686 } 1687 1688 /* Everything else is a private mapping. */ 1689 ASSERT_TRUE(is_buf_eq(ptr, page_size, 'a' + i)); 1690 } 1691 1692 ASSERT_EQ(munmap(ptr_shared, 10 * page_size), 0); 1693 ASSERT_EQ(munmap(ptr_private, 10 * page_size), 0); 1694 } 1695 1696 /* Test that guard regions established over a read-only mapping function correctly. */ 1697 TEST_F(guard_regions, readonly_file) 1698 { 1699 const unsigned long page_size = self->page_size; 1700 char *ptr; 1701 int i; 1702 1703 if (variant->backing != LOCAL_FILE_BACKED) 1704 SKIP(return, "Read-only test specific to file-backed"); 1705 1706 /* Map shared so we can populate with pattern, populate it, unmap. */ 1707 ptr = mmap_(self, variant, NULL, 10 * page_size, 1708 PROT_READ | PROT_WRITE, 0, 0); 1709 ASSERT_NE(ptr, MAP_FAILED); 1710 set_pattern(ptr, 10, page_size); 1711 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1712 /* Close the fd so we can re-open read-only. */ 1713 ASSERT_EQ(close(self->fd), 0); 1714 1715 /* Re-open read-only. */ 1716 self->fd = open(self->path, O_RDONLY); 1717 ASSERT_NE(self->fd, -1); 1718 /* Re-map read-only. */ 1719 ptr = mmap_(self, variant, NULL, 10 * page_size, PROT_READ, 0, 0); 1720 ASSERT_NE(ptr, MAP_FAILED); 1721 1722 /* Mark every other page guarded. */ 1723 for (i = 0; i < 10; i += 2) { 1724 char *ptr_pg = &ptr[i * page_size]; 1725 1726 ASSERT_EQ(madvise(ptr_pg, page_size, MADV_GUARD_INSTALL), 0); 1727 } 1728 1729 /* Assert that the guard regions are in place.*/ 1730 for (i = 0; i < 10; i++) { 1731 char *ptr_pg = &ptr[i * page_size]; 1732 1733 ASSERT_EQ(try_read_buf(ptr_pg), i % 2 != 0); 1734 } 1735 1736 /* Remove guard regions. */ 1737 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0); 1738 1739 /* Ensure the data is as expected. */ 1740 ASSERT_TRUE(check_pattern(ptr, 10, page_size)); 1741 1742 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1743 } 1744 1745 TEST_F(guard_regions, fault_around) 1746 { 1747 const unsigned long page_size = self->page_size; 1748 char *ptr; 1749 int i; 1750 1751 if (variant->backing == ANON_BACKED) 1752 SKIP(return, "Fault-around test specific to file-backed"); 1753 1754 ptr = mmap_(self, variant, NULL, 10 * page_size, 1755 PROT_READ | PROT_WRITE, 0, 0); 1756 ASSERT_NE(ptr, MAP_FAILED); 1757 1758 /* Establish a pattern in the backing file. */ 1759 set_pattern(ptr, 10, page_size); 1760 1761 /* 1762 * Now drop it from the page cache so we get major faults when next we 1763 * map it. 1764 */ 1765 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_PAGEOUT), 0); 1766 1767 /* Unmap and remap 'to be sure'. */ 1768 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1769 ptr = mmap_(self, variant, NULL, 10 * page_size, 1770 PROT_READ | PROT_WRITE, 0, 0); 1771 ASSERT_NE(ptr, MAP_FAILED); 1772 1773 /* Now make every even page guarded. */ 1774 for (i = 0; i < 10; i += 2) { 1775 char *ptr_p = &ptr[i * page_size]; 1776 1777 ASSERT_EQ(madvise(ptr_p, page_size, MADV_GUARD_INSTALL), 0); 1778 } 1779 1780 /* Now fault in every odd page. This should trigger fault-around. */ 1781 for (i = 1; i < 10; i += 2) { 1782 char *ptr_p = &ptr[i * page_size]; 1783 1784 ASSERT_TRUE(try_read_buf(ptr_p)); 1785 } 1786 1787 /* Finally, ensure that guard regions are intact as expected. */ 1788 for (i = 0; i < 10; i++) { 1789 char *ptr_p = &ptr[i * page_size]; 1790 1791 ASSERT_EQ(try_read_buf(ptr_p), i % 2 != 0); 1792 } 1793 1794 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1795 } 1796 1797 TEST_F(guard_regions, truncation) 1798 { 1799 const unsigned long page_size = self->page_size; 1800 char *ptr; 1801 int i; 1802 1803 if (variant->backing == ANON_BACKED) 1804 SKIP(return, "Truncation test specific to file-backed"); 1805 1806 ptr = mmap_(self, variant, NULL, 10 * page_size, 1807 PROT_READ | PROT_WRITE, 0, 0); 1808 ASSERT_NE(ptr, MAP_FAILED); 1809 1810 /* 1811 * Establish a pattern in the backing file, just so there is data 1812 * there. 1813 */ 1814 set_pattern(ptr, 10, page_size); 1815 1816 /* Now make every even page guarded. */ 1817 for (i = 0; i < 10; i += 2) { 1818 char *ptr_p = &ptr[i * page_size]; 1819 1820 ASSERT_EQ(madvise(ptr_p, page_size, MADV_GUARD_INSTALL), 0); 1821 } 1822 1823 /* Now assert things are as expected. */ 1824 for (i = 0; i < 10; i++) { 1825 char *ptr_p = &ptr[i * page_size]; 1826 1827 ASSERT_EQ(try_read_write_buf(ptr_p), i % 2 != 0); 1828 } 1829 1830 /* Now truncate to actually used size (initialised to 100). */ 1831 ASSERT_EQ(ftruncate(self->fd, 10 * page_size), 0); 1832 1833 /* Here the guard regions will remain intact. */ 1834 for (i = 0; i < 10; i++) { 1835 char *ptr_p = &ptr[i * page_size]; 1836 1837 ASSERT_EQ(try_read_write_buf(ptr_p), i % 2 != 0); 1838 } 1839 1840 /* Now truncate to half the size, then truncate again to the full size. */ 1841 ASSERT_EQ(ftruncate(self->fd, 5 * page_size), 0); 1842 ASSERT_EQ(ftruncate(self->fd, 10 * page_size), 0); 1843 1844 /* Again, guard pages will remain intact. */ 1845 for (i = 0; i < 10; i++) { 1846 char *ptr_p = &ptr[i * page_size]; 1847 1848 ASSERT_EQ(try_read_write_buf(ptr_p), i % 2 != 0); 1849 } 1850 1851 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1852 } 1853 1854 TEST_F(guard_regions, hole_punch) 1855 { 1856 const unsigned long page_size = self->page_size; 1857 char *ptr; 1858 int i; 1859 1860 if (variant->backing == ANON_BACKED) 1861 SKIP(return, "Truncation test specific to file-backed"); 1862 1863 /* Establish pattern in mapping. */ 1864 ptr = mmap_(self, variant, NULL, 10 * page_size, 1865 PROT_READ | PROT_WRITE, 0, 0); 1866 ASSERT_NE(ptr, MAP_FAILED); 1867 set_pattern(ptr, 10, page_size); 1868 1869 /* Install a guard region in the middle of the mapping. */ 1870 ASSERT_EQ(madvise(&ptr[3 * page_size], 4 * page_size, 1871 MADV_GUARD_INSTALL), 0); 1872 1873 /* 1874 * The buffer will now be: 1875 * 1876 * 0123456789 1877 * ***xxxx*** 1878 * 1879 * Where * is data and x is the guard region. 1880 */ 1881 1882 /* Ensure established. */ 1883 for (i = 0; i < 10; i++) { 1884 char *ptr_p = &ptr[i * page_size]; 1885 1886 ASSERT_EQ(try_read_buf(ptr_p), i < 3 || i >= 7); 1887 } 1888 1889 /* Now hole punch the guarded region. */ 1890 ASSERT_EQ(madvise(&ptr[3 * page_size], 4 * page_size, 1891 MADV_REMOVE), 0); 1892 1893 /* Ensure guard regions remain. */ 1894 for (i = 0; i < 10; i++) { 1895 char *ptr_p = &ptr[i * page_size]; 1896 1897 ASSERT_EQ(try_read_buf(ptr_p), i < 3 || i >= 7); 1898 } 1899 1900 /* Now remove guard region throughout. */ 1901 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0); 1902 1903 /* Check that the pattern exists in non-hole punched region. */ 1904 ASSERT_TRUE(check_pattern(ptr, 3, page_size)); 1905 /* Check that hole punched region is zeroed. */ 1906 ASSERT_TRUE(is_buf_eq(&ptr[3 * page_size], 4 * page_size, '\0')); 1907 /* Check that the pattern exists in the remainder of the file. */ 1908 ASSERT_TRUE(check_pattern_offset(ptr, 3, page_size, 7)); 1909 1910 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1911 } 1912 1913 /* 1914 * Ensure that a memfd works correctly with guard regions, that we can write 1915 * seal it then open the mapping read-only and still establish guard regions 1916 * within, remove those guard regions and have everything work correctly. 1917 */ 1918 TEST_F(guard_regions, memfd_write_seal) 1919 { 1920 const unsigned long page_size = self->page_size; 1921 char *ptr; 1922 int i; 1923 1924 if (variant->backing != SHMEM_BACKED) 1925 SKIP(return, "memfd write seal test specific to shmem"); 1926 1927 /* OK, we need a memfd, so close existing one. */ 1928 ASSERT_EQ(close(self->fd), 0); 1929 1930 /* Create and truncate memfd. */ 1931 self->fd = memfd_create("guard_regions_memfd_seals_test", 1932 MFD_ALLOW_SEALING); 1933 ASSERT_NE(self->fd, -1); 1934 ASSERT_EQ(ftruncate(self->fd, 10 * page_size), 0); 1935 1936 /* Map, set pattern, unmap. */ 1937 ptr = mmap_(self, variant, NULL, 10 * page_size, PROT_READ | PROT_WRITE, 0, 0); 1938 ASSERT_NE(ptr, MAP_FAILED); 1939 set_pattern(ptr, 10, page_size); 1940 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1941 1942 /* Write-seal the memfd. */ 1943 ASSERT_EQ(fcntl(self->fd, F_ADD_SEALS, F_SEAL_WRITE), 0); 1944 1945 /* Now map the memfd readonly. */ 1946 ptr = mmap_(self, variant, NULL, 10 * page_size, PROT_READ, 0, 0); 1947 ASSERT_NE(ptr, MAP_FAILED); 1948 1949 /* Ensure pattern is as expected. */ 1950 ASSERT_TRUE(check_pattern(ptr, 10, page_size)); 1951 1952 /* Now make every even page guarded. */ 1953 for (i = 0; i < 10; i += 2) { 1954 char *ptr_p = &ptr[i * page_size]; 1955 1956 ASSERT_EQ(madvise(ptr_p, page_size, MADV_GUARD_INSTALL), 0); 1957 } 1958 1959 /* Now assert things are as expected. */ 1960 for (i = 0; i < 10; i++) { 1961 char *ptr_p = &ptr[i * page_size]; 1962 1963 ASSERT_EQ(try_read_buf(ptr_p), i % 2 != 0); 1964 } 1965 1966 /* Now remove guard regions. */ 1967 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0); 1968 1969 /* Ensure pattern is as expected. */ 1970 ASSERT_TRUE(check_pattern(ptr, 10, page_size)); 1971 1972 /* Ensure write seal intact. */ 1973 for (i = 0; i < 10; i++) { 1974 char *ptr_p = &ptr[i * page_size]; 1975 1976 ASSERT_FALSE(try_write_buf(ptr_p)); 1977 } 1978 1979 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1980 } 1981 1982 1983 /* 1984 * Since we are now permitted to establish guard regions in read-only anonymous 1985 * mappings, for the sake of thoroughness, though it probably has no practical 1986 * use, test that guard regions function with a mapping to the anonymous zero 1987 * page. 1988 */ 1989 TEST_F(guard_regions, anon_zeropage) 1990 { 1991 const unsigned long page_size = self->page_size; 1992 char *ptr; 1993 int i; 1994 1995 if (!is_anon_backed(variant)) 1996 SKIP(return, "anon zero page test specific to anon/shmem"); 1997 1998 /* Obtain a read-only i.e. anon zero page mapping. */ 1999 ptr = mmap_(self, variant, NULL, 10 * page_size, PROT_READ, 0, 0); 2000 ASSERT_NE(ptr, MAP_FAILED); 2001 2002 /* Now make every even page guarded. */ 2003 for (i = 0; i < 10; i += 2) { 2004 char *ptr_p = &ptr[i * page_size]; 2005 2006 ASSERT_EQ(madvise(ptr_p, page_size, MADV_GUARD_INSTALL), 0); 2007 } 2008 2009 /* Now assert things are as expected. */ 2010 for (i = 0; i < 10; i++) { 2011 char *ptr_p = &ptr[i * page_size]; 2012 2013 ASSERT_EQ(try_read_buf(ptr_p), i % 2 != 0); 2014 } 2015 2016 /* Now remove all guard regions. */ 2017 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0); 2018 2019 /* Now assert things are as expected. */ 2020 for (i = 0; i < 10; i++) { 2021 char *ptr_p = &ptr[i * page_size]; 2022 2023 ASSERT_TRUE(try_read_buf(ptr_p)); 2024 } 2025 2026 /* Ensure zero page...*/ 2027 ASSERT_TRUE(is_buf_eq(ptr, 10 * page_size, '\0')); 2028 2029 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 2030 } 2031 2032 /* 2033 * Assert that /proc/$pid/pagemap correctly identifies guard region ranges. 2034 */ 2035 TEST_F(guard_regions, pagemap) 2036 { 2037 const unsigned long page_size = self->page_size; 2038 int proc_fd; 2039 char *ptr; 2040 int i; 2041 2042 proc_fd = open("/proc/self/pagemap", O_RDONLY); 2043 ASSERT_NE(proc_fd, -1); 2044 2045 ptr = mmap_(self, variant, NULL, 10 * page_size, 2046 PROT_READ | PROT_WRITE, 0, 0); 2047 ASSERT_NE(ptr, MAP_FAILED); 2048 2049 /* Read from pagemap, and assert no guard regions are detected. */ 2050 for (i = 0; i < 10; i++) { 2051 char *ptr_p = &ptr[i * page_size]; 2052 unsigned long entry = pagemap_get_entry(proc_fd, ptr_p); 2053 unsigned long masked = entry & PM_GUARD_REGION; 2054 2055 ASSERT_EQ(masked, 0); 2056 } 2057 2058 /* Install a guard region in every other page. */ 2059 for (i = 0; i < 10; i += 2) { 2060 char *ptr_p = &ptr[i * page_size]; 2061 2062 ASSERT_EQ(madvise(ptr_p, page_size, MADV_GUARD_INSTALL), 0); 2063 } 2064 2065 /* Re-read from pagemap, and assert guard regions are detected. */ 2066 for (i = 0; i < 10; i++) { 2067 char *ptr_p = &ptr[i * page_size]; 2068 unsigned long entry = pagemap_get_entry(proc_fd, ptr_p); 2069 unsigned long masked = entry & PM_GUARD_REGION; 2070 2071 ASSERT_EQ(masked, i % 2 == 0 ? PM_GUARD_REGION : 0); 2072 } 2073 2074 ASSERT_EQ(close(proc_fd), 0); 2075 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 2076 } 2077 2078 TEST_HARNESS_MAIN 2079