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