Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.14-rc6 1320 lines 36 kB view raw
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/userfaultfd.h> 10#include <setjmp.h> 11#include <signal.h> 12#include <stdbool.h> 13#include <stdio.h> 14#include <stdlib.h> 15#include <string.h> 16#include <sys/ioctl.h> 17#include <sys/mman.h> 18#include <sys/syscall.h> 19#include <sys/uio.h> 20#include <unistd.h> 21 22/* 23 * Ignore the checkpatch warning, as per the C99 standard, section 7.14.1.1: 24 * 25 * "If the signal occurs other than as the result of calling the abort or raise 26 * function, the behavior is undefined if the signal handler refers to any 27 * object with static storage duration other than by assigning a value to an 28 * object declared as volatile sig_atomic_t" 29 */ 30static volatile sig_atomic_t signal_jump_set; 31static sigjmp_buf signal_jmp_buf; 32 33/* 34 * Ignore the checkpatch warning, we must read from x but don't want to do 35 * anything with it in order to trigger a read page fault. We therefore must use 36 * volatile to stop the compiler from optimising this away. 37 */ 38#define FORCE_READ(x) (*(volatile typeof(x) *)x) 39 40static int userfaultfd(int flags) 41{ 42 return syscall(SYS_userfaultfd, flags); 43} 44 45static void handle_fatal(int c) 46{ 47 if (!signal_jump_set) 48 return; 49 50 siglongjmp(signal_jmp_buf, c); 51} 52 53static int pidfd_open(pid_t pid, unsigned int flags) 54{ 55 return syscall(SYS_pidfd_open, pid, flags); 56} 57 58static ssize_t sys_process_madvise(int pidfd, const struct iovec *iovec, 59 size_t n, int advice, unsigned int flags) 60{ 61 return syscall(__NR_process_madvise, pidfd, iovec, n, advice, flags); 62} 63 64/* 65 * Enable our signal catcher and try to read/write the specified buffer. The 66 * return value indicates whether the read/write succeeds without a fatal 67 * signal. 68 */ 69static bool try_access_buf(char *ptr, bool write) 70{ 71 bool failed; 72 73 /* Tell signal handler to jump back here on fatal signal. */ 74 signal_jump_set = true; 75 /* If a fatal signal arose, we will jump back here and failed is set. */ 76 failed = sigsetjmp(signal_jmp_buf, 0) != 0; 77 78 if (!failed) { 79 if (write) 80 *ptr = 'x'; 81 else 82 FORCE_READ(ptr); 83 } 84 85 signal_jump_set = false; 86 return !failed; 87} 88 89/* Try and read from a buffer, return true if no fatal signal. */ 90static bool try_read_buf(char *ptr) 91{ 92 return try_access_buf(ptr, false); 93} 94 95/* Try and write to a buffer, return true if no fatal signal. */ 96static bool try_write_buf(char *ptr) 97{ 98 return try_access_buf(ptr, true); 99} 100 101/* 102 * Try and BOTH read from AND write to a buffer, return true if BOTH operations 103 * succeed. 104 */ 105static bool try_read_write_buf(char *ptr) 106{ 107 return try_read_buf(ptr) && try_write_buf(ptr); 108} 109 110FIXTURE(guard_pages) 111{ 112 unsigned long page_size; 113}; 114 115FIXTURE_SETUP(guard_pages) 116{ 117 struct sigaction act = { 118 .sa_handler = &handle_fatal, 119 .sa_flags = SA_NODEFER, 120 }; 121 122 sigemptyset(&act.sa_mask); 123 if (sigaction(SIGSEGV, &act, NULL)) 124 ksft_exit_fail_perror("sigaction"); 125 126 self->page_size = (unsigned long)sysconf(_SC_PAGESIZE); 127}; 128 129FIXTURE_TEARDOWN(guard_pages) 130{ 131 struct sigaction act = { 132 .sa_handler = SIG_DFL, 133 .sa_flags = SA_NODEFER, 134 }; 135 136 sigemptyset(&act.sa_mask); 137 sigaction(SIGSEGV, &act, NULL); 138} 139 140TEST_F(guard_pages, basic) 141{ 142 const unsigned long NUM_PAGES = 10; 143 const unsigned long page_size = self->page_size; 144 char *ptr; 145 int i; 146 147 ptr = mmap(NULL, NUM_PAGES * page_size, PROT_READ | PROT_WRITE, 148 MAP_PRIVATE | MAP_ANON, -1, 0); 149 ASSERT_NE(ptr, MAP_FAILED); 150 151 /* Trivially assert we can touch the first page. */ 152 ASSERT_TRUE(try_read_write_buf(ptr)); 153 154 ASSERT_EQ(madvise(ptr, page_size, MADV_GUARD_INSTALL), 0); 155 156 /* Establish that 1st page SIGSEGV's. */ 157 ASSERT_FALSE(try_read_write_buf(ptr)); 158 159 /* Ensure we can touch everything else.*/ 160 for (i = 1; i < NUM_PAGES; i++) { 161 char *curr = &ptr[i * page_size]; 162 163 ASSERT_TRUE(try_read_write_buf(curr)); 164 } 165 166 /* Establish a guard page at the end of the mapping. */ 167 ASSERT_EQ(madvise(&ptr[(NUM_PAGES - 1) * page_size], page_size, 168 MADV_GUARD_INSTALL), 0); 169 170 /* Check that both guard pages result in SIGSEGV. */ 171 ASSERT_FALSE(try_read_write_buf(ptr)); 172 ASSERT_FALSE(try_read_write_buf(&ptr[(NUM_PAGES - 1) * page_size])); 173 174 /* Remove the first guard page. */ 175 ASSERT_FALSE(madvise(ptr, page_size, MADV_GUARD_REMOVE)); 176 177 /* Make sure we can touch it. */ 178 ASSERT_TRUE(try_read_write_buf(ptr)); 179 180 /* Remove the last guard page. */ 181 ASSERT_FALSE(madvise(&ptr[(NUM_PAGES - 1) * page_size], page_size, 182 MADV_GUARD_REMOVE)); 183 184 /* Make sure we can touch it. */ 185 ASSERT_TRUE(try_read_write_buf(&ptr[(NUM_PAGES - 1) * page_size])); 186 187 /* 188 * Test setting a _range_ of pages, namely the first 3. The first of 189 * these be faulted in, so this also tests that we can install guard 190 * pages over backed pages. 191 */ 192 ASSERT_EQ(madvise(ptr, 3 * page_size, MADV_GUARD_INSTALL), 0); 193 194 /* Make sure they are all guard pages. */ 195 for (i = 0; i < 3; i++) { 196 char *curr = &ptr[i * page_size]; 197 198 ASSERT_FALSE(try_read_write_buf(curr)); 199 } 200 201 /* Make sure the rest are not. */ 202 for (i = 3; i < NUM_PAGES; i++) { 203 char *curr = &ptr[i * page_size]; 204 205 ASSERT_TRUE(try_read_write_buf(curr)); 206 } 207 208 /* Remove guard pages. */ 209 ASSERT_EQ(madvise(ptr, NUM_PAGES * page_size, MADV_GUARD_REMOVE), 0); 210 211 /* Now make sure we can touch everything. */ 212 for (i = 0; i < NUM_PAGES; i++) { 213 char *curr = &ptr[i * page_size]; 214 215 ASSERT_TRUE(try_read_write_buf(curr)); 216 } 217 218 /* 219 * Now remove all guard pages, make sure we don't remove existing 220 * entries. 221 */ 222 ASSERT_EQ(madvise(ptr, NUM_PAGES * page_size, MADV_GUARD_REMOVE), 0); 223 224 for (i = 0; i < NUM_PAGES * page_size; i += page_size) { 225 char chr = ptr[i]; 226 227 ASSERT_EQ(chr, 'x'); 228 } 229 230 ASSERT_EQ(munmap(ptr, NUM_PAGES * page_size), 0); 231} 232 233/* Assert that operations applied across multiple VMAs work as expected. */ 234TEST_F(guard_pages, multi_vma) 235{ 236 const unsigned long page_size = self->page_size; 237 char *ptr_region, *ptr, *ptr1, *ptr2, *ptr3; 238 int i; 239 240 /* Reserve a 100 page region over which we can install VMAs. */ 241 ptr_region = mmap(NULL, 100 * page_size, PROT_NONE, 242 MAP_ANON | MAP_PRIVATE, -1, 0); 243 ASSERT_NE(ptr_region, MAP_FAILED); 244 245 /* Place a VMA of 10 pages size at the start of the region. */ 246 ptr1 = mmap(ptr_region, 10 * page_size, PROT_READ | PROT_WRITE, 247 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 248 ASSERT_NE(ptr1, MAP_FAILED); 249 250 /* Place a VMA of 5 pages size 50 pages into the region. */ 251 ptr2 = mmap(&ptr_region[50 * page_size], 5 * page_size, 252 PROT_READ | PROT_WRITE, 253 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 254 ASSERT_NE(ptr2, MAP_FAILED); 255 256 /* Place a VMA of 20 pages size at the end of the region. */ 257 ptr3 = mmap(&ptr_region[80 * page_size], 20 * page_size, 258 PROT_READ | PROT_WRITE, 259 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 260 ASSERT_NE(ptr3, MAP_FAILED); 261 262 /* Unmap gaps. */ 263 ASSERT_EQ(munmap(&ptr_region[10 * page_size], 40 * page_size), 0); 264 ASSERT_EQ(munmap(&ptr_region[55 * page_size], 25 * page_size), 0); 265 266 /* 267 * We end up with VMAs like this: 268 * 269 * 0 10 .. 50 55 .. 80 100 270 * [---] [---] [---] 271 */ 272 273 /* 274 * Now mark the whole range as guard pages and make sure all VMAs are as 275 * such. 276 */ 277 278 /* 279 * madvise() is certifiable and lets you perform operations over gaps, 280 * everything works, but it indicates an error and errno is set to 281 * -ENOMEM. Also if anything runs out of memory it is set to 282 * -ENOMEM. You are meant to guess which is which. 283 */ 284 ASSERT_EQ(madvise(ptr_region, 100 * page_size, MADV_GUARD_INSTALL), -1); 285 ASSERT_EQ(errno, ENOMEM); 286 287 for (i = 0; i < 10; i++) { 288 char *curr = &ptr1[i * page_size]; 289 290 ASSERT_FALSE(try_read_write_buf(curr)); 291 } 292 293 for (i = 0; i < 5; i++) { 294 char *curr = &ptr2[i * page_size]; 295 296 ASSERT_FALSE(try_read_write_buf(curr)); 297 } 298 299 for (i = 0; i < 20; i++) { 300 char *curr = &ptr3[i * page_size]; 301 302 ASSERT_FALSE(try_read_write_buf(curr)); 303 } 304 305 /* Now remove guar pages over range and assert the opposite. */ 306 307 ASSERT_EQ(madvise(ptr_region, 100 * page_size, MADV_GUARD_REMOVE), -1); 308 ASSERT_EQ(errno, ENOMEM); 309 310 for (i = 0; i < 10; i++) { 311 char *curr = &ptr1[i * page_size]; 312 313 ASSERT_TRUE(try_read_write_buf(curr)); 314 } 315 316 for (i = 0; i < 5; i++) { 317 char *curr = &ptr2[i * page_size]; 318 319 ASSERT_TRUE(try_read_write_buf(curr)); 320 } 321 322 for (i = 0; i < 20; i++) { 323 char *curr = &ptr3[i * page_size]; 324 325 ASSERT_TRUE(try_read_write_buf(curr)); 326 } 327 328 /* Now map incompatible VMAs in the gaps. */ 329 ptr = mmap(&ptr_region[10 * page_size], 40 * page_size, 330 PROT_READ | PROT_WRITE | PROT_EXEC, 331 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 332 ASSERT_NE(ptr, MAP_FAILED); 333 ptr = mmap(&ptr_region[55 * page_size], 25 * page_size, 334 PROT_READ | PROT_WRITE | PROT_EXEC, 335 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 336 ASSERT_NE(ptr, MAP_FAILED); 337 338 /* 339 * We end up with VMAs like this: 340 * 341 * 0 10 .. 50 55 .. 80 100 342 * [---][xxxx][---][xxxx][---] 343 * 344 * Where 'x' signifies VMAs that cannot be merged with those adjacent to 345 * them. 346 */ 347 348 /* Multiple VMAs adjacent to one another should result in no error. */ 349 ASSERT_EQ(madvise(ptr_region, 100 * page_size, MADV_GUARD_INSTALL), 0); 350 for (i = 0; i < 100; i++) { 351 char *curr = &ptr_region[i * page_size]; 352 353 ASSERT_FALSE(try_read_write_buf(curr)); 354 } 355 ASSERT_EQ(madvise(ptr_region, 100 * page_size, MADV_GUARD_REMOVE), 0); 356 for (i = 0; i < 100; i++) { 357 char *curr = &ptr_region[i * page_size]; 358 359 ASSERT_TRUE(try_read_write_buf(curr)); 360 } 361 362 /* Cleanup. */ 363 ASSERT_EQ(munmap(ptr_region, 100 * page_size), 0); 364} 365 366/* 367 * Assert that batched operations performed using process_madvise() work as 368 * expected. 369 */ 370TEST_F(guard_pages, process_madvise) 371{ 372 const unsigned long page_size = self->page_size; 373 pid_t pid = getpid(); 374 int pidfd = pidfd_open(pid, 0); 375 char *ptr_region, *ptr1, *ptr2, *ptr3; 376 ssize_t count; 377 struct iovec vec[6]; 378 379 ASSERT_NE(pidfd, -1); 380 381 /* Reserve region to map over. */ 382 ptr_region = mmap(NULL, 100 * page_size, PROT_NONE, 383 MAP_ANON | MAP_PRIVATE, -1, 0); 384 ASSERT_NE(ptr_region, MAP_FAILED); 385 386 /* 387 * 10 pages offset 1 page into reserve region. We MAP_POPULATE so we 388 * overwrite existing entries and test this code path against 389 * overwriting existing entries. 390 */ 391 ptr1 = mmap(&ptr_region[page_size], 10 * page_size, 392 PROT_READ | PROT_WRITE, 393 MAP_FIXED | MAP_ANON | MAP_PRIVATE | MAP_POPULATE, -1, 0); 394 ASSERT_NE(ptr1, MAP_FAILED); 395 /* We want guard markers at start/end of each VMA. */ 396 vec[0].iov_base = ptr1; 397 vec[0].iov_len = page_size; 398 vec[1].iov_base = &ptr1[9 * page_size]; 399 vec[1].iov_len = page_size; 400 401 /* 5 pages offset 50 pages into reserve region. */ 402 ptr2 = mmap(&ptr_region[50 * page_size], 5 * page_size, 403 PROT_READ | PROT_WRITE, 404 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 405 ASSERT_NE(ptr2, MAP_FAILED); 406 vec[2].iov_base = ptr2; 407 vec[2].iov_len = page_size; 408 vec[3].iov_base = &ptr2[4 * page_size]; 409 vec[3].iov_len = page_size; 410 411 /* 20 pages offset 79 pages into reserve region. */ 412 ptr3 = mmap(&ptr_region[79 * page_size], 20 * page_size, 413 PROT_READ | PROT_WRITE, 414 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 415 ASSERT_NE(ptr3, MAP_FAILED); 416 vec[4].iov_base = ptr3; 417 vec[4].iov_len = page_size; 418 vec[5].iov_base = &ptr3[19 * page_size]; 419 vec[5].iov_len = page_size; 420 421 /* Free surrounding VMAs. */ 422 ASSERT_EQ(munmap(ptr_region, page_size), 0); 423 ASSERT_EQ(munmap(&ptr_region[11 * page_size], 39 * page_size), 0); 424 ASSERT_EQ(munmap(&ptr_region[55 * page_size], 24 * page_size), 0); 425 ASSERT_EQ(munmap(&ptr_region[99 * page_size], page_size), 0); 426 427 /* Now guard in one step. */ 428 count = sys_process_madvise(pidfd, vec, 6, MADV_GUARD_INSTALL, 0); 429 430 /* OK we don't have permission to do this, skip. */ 431 if (count == -1 && errno == EPERM) 432 ksft_exit_skip("No process_madvise() permissions, try running as root.\n"); 433 434 /* Returns the number of bytes advised. */ 435 ASSERT_EQ(count, 6 * page_size); 436 437 /* Now make sure the guarding was applied. */ 438 439 ASSERT_FALSE(try_read_write_buf(ptr1)); 440 ASSERT_FALSE(try_read_write_buf(&ptr1[9 * page_size])); 441 442 ASSERT_FALSE(try_read_write_buf(ptr2)); 443 ASSERT_FALSE(try_read_write_buf(&ptr2[4 * page_size])); 444 445 ASSERT_FALSE(try_read_write_buf(ptr3)); 446 ASSERT_FALSE(try_read_write_buf(&ptr3[19 * page_size])); 447 448 /* Now do the same with unguard... */ 449 count = sys_process_madvise(pidfd, vec, 6, MADV_GUARD_REMOVE, 0); 450 451 /* ...and everything should now succeed. */ 452 453 ASSERT_TRUE(try_read_write_buf(ptr1)); 454 ASSERT_TRUE(try_read_write_buf(&ptr1[9 * page_size])); 455 456 ASSERT_TRUE(try_read_write_buf(ptr2)); 457 ASSERT_TRUE(try_read_write_buf(&ptr2[4 * page_size])); 458 459 ASSERT_TRUE(try_read_write_buf(ptr3)); 460 ASSERT_TRUE(try_read_write_buf(&ptr3[19 * page_size])); 461 462 /* Cleanup. */ 463 ASSERT_EQ(munmap(ptr1, 10 * page_size), 0); 464 ASSERT_EQ(munmap(ptr2, 5 * page_size), 0); 465 ASSERT_EQ(munmap(ptr3, 20 * page_size), 0); 466 close(pidfd); 467} 468 469/* Assert that unmapping ranges does not leave guard markers behind. */ 470TEST_F(guard_pages, munmap) 471{ 472 const unsigned long page_size = self->page_size; 473 char *ptr, *ptr_new1, *ptr_new2; 474 475 ptr = mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE, 476 MAP_ANON | MAP_PRIVATE, -1, 0); 477 ASSERT_NE(ptr, MAP_FAILED); 478 479 /* Guard first and last pages. */ 480 ASSERT_EQ(madvise(ptr, page_size, MADV_GUARD_INSTALL), 0); 481 ASSERT_EQ(madvise(&ptr[9 * page_size], page_size, MADV_GUARD_INSTALL), 0); 482 483 /* Assert that they are guarded. */ 484 ASSERT_FALSE(try_read_write_buf(ptr)); 485 ASSERT_FALSE(try_read_write_buf(&ptr[9 * page_size])); 486 487 /* Unmap them. */ 488 ASSERT_EQ(munmap(ptr, page_size), 0); 489 ASSERT_EQ(munmap(&ptr[9 * page_size], page_size), 0); 490 491 /* Map over them.*/ 492 ptr_new1 = mmap(ptr, page_size, PROT_READ | PROT_WRITE, 493 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 494 ASSERT_NE(ptr_new1, MAP_FAILED); 495 ptr_new2 = mmap(&ptr[9 * page_size], page_size, PROT_READ | PROT_WRITE, 496 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 497 ASSERT_NE(ptr_new2, MAP_FAILED); 498 499 /* Assert that they are now not guarded. */ 500 ASSERT_TRUE(try_read_write_buf(ptr_new1)); 501 ASSERT_TRUE(try_read_write_buf(ptr_new2)); 502 503 /* Cleanup. */ 504 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 505} 506 507/* Assert that mprotect() operations have no bearing on guard markers. */ 508TEST_F(guard_pages, mprotect) 509{ 510 const unsigned long page_size = self->page_size; 511 char *ptr; 512 int i; 513 514 ptr = mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE, 515 MAP_ANON | MAP_PRIVATE, -1, 0); 516 ASSERT_NE(ptr, MAP_FAILED); 517 518 /* Guard the middle of the range. */ 519 ASSERT_EQ(madvise(&ptr[5 * page_size], 2 * page_size, 520 MADV_GUARD_INSTALL), 0); 521 522 /* Assert that it is indeed guarded. */ 523 ASSERT_FALSE(try_read_write_buf(&ptr[5 * page_size])); 524 ASSERT_FALSE(try_read_write_buf(&ptr[6 * page_size])); 525 526 /* Now make these pages read-only. */ 527 ASSERT_EQ(mprotect(&ptr[5 * page_size], 2 * page_size, PROT_READ), 0); 528 529 /* Make sure the range is still guarded. */ 530 ASSERT_FALSE(try_read_buf(&ptr[5 * page_size])); 531 ASSERT_FALSE(try_read_buf(&ptr[6 * page_size])); 532 533 /* Make sure we can guard again without issue.*/ 534 ASSERT_EQ(madvise(&ptr[5 * page_size], 2 * page_size, 535 MADV_GUARD_INSTALL), 0); 536 537 /* Make sure the range is, yet again, still guarded. */ 538 ASSERT_FALSE(try_read_buf(&ptr[5 * page_size])); 539 ASSERT_FALSE(try_read_buf(&ptr[6 * page_size])); 540 541 /* Now unguard the whole range. */ 542 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0); 543 544 /* Make sure the whole range is readable. */ 545 for (i = 0; i < 10; i++) { 546 char *curr = &ptr[i * page_size]; 547 548 ASSERT_TRUE(try_read_buf(curr)); 549 } 550 551 /* Cleanup. */ 552 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 553} 554 555/* Split and merge VMAs and make sure guard pages still behave. */ 556TEST_F(guard_pages, split_merge) 557{ 558 const unsigned long page_size = self->page_size; 559 char *ptr, *ptr_new; 560 int i; 561 562 ptr = mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE, 563 MAP_ANON | MAP_PRIVATE, -1, 0); 564 ASSERT_NE(ptr, MAP_FAILED); 565 566 /* Guard the whole range. */ 567 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), 0); 568 569 /* Make sure the whole range is guarded. */ 570 for (i = 0; i < 10; i++) { 571 char *curr = &ptr[i * page_size]; 572 573 ASSERT_FALSE(try_read_write_buf(curr)); 574 } 575 576 /* Now unmap some pages in the range so we split. */ 577 ASSERT_EQ(munmap(&ptr[2 * page_size], page_size), 0); 578 ASSERT_EQ(munmap(&ptr[5 * page_size], page_size), 0); 579 ASSERT_EQ(munmap(&ptr[8 * page_size], page_size), 0); 580 581 /* Make sure the remaining ranges are guarded post-split. */ 582 for (i = 0; i < 2; i++) { 583 char *curr = &ptr[i * page_size]; 584 585 ASSERT_FALSE(try_read_write_buf(curr)); 586 } 587 for (i = 2; i < 5; i++) { 588 char *curr = &ptr[i * page_size]; 589 590 ASSERT_FALSE(try_read_write_buf(curr)); 591 } 592 for (i = 6; i < 8; i++) { 593 char *curr = &ptr[i * page_size]; 594 595 ASSERT_FALSE(try_read_write_buf(curr)); 596 } 597 for (i = 9; i < 10; i++) { 598 char *curr = &ptr[i * page_size]; 599 600 ASSERT_FALSE(try_read_write_buf(curr)); 601 } 602 603 /* Now map them again - the unmap will have cleared the guards. */ 604 ptr_new = mmap(&ptr[2 * page_size], page_size, PROT_READ | PROT_WRITE, 605 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 606 ASSERT_NE(ptr_new, MAP_FAILED); 607 ptr_new = mmap(&ptr[5 * page_size], page_size, PROT_READ | PROT_WRITE, 608 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 609 ASSERT_NE(ptr_new, MAP_FAILED); 610 ptr_new = mmap(&ptr[8 * page_size], page_size, PROT_READ | PROT_WRITE, 611 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 612 ASSERT_NE(ptr_new, MAP_FAILED); 613 614 /* Now make sure guard pages are established. */ 615 for (i = 0; i < 10; i++) { 616 char *curr = &ptr[i * page_size]; 617 bool result = try_read_write_buf(curr); 618 bool expect_true = i == 2 || i == 5 || i == 8; 619 620 ASSERT_TRUE(expect_true ? result : !result); 621 } 622 623 /* Now guard everything again. */ 624 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), 0); 625 626 /* Make sure the whole range is guarded. */ 627 for (i = 0; i < 10; i++) { 628 char *curr = &ptr[i * page_size]; 629 630 ASSERT_FALSE(try_read_write_buf(curr)); 631 } 632 633 /* Now split the range into three. */ 634 ASSERT_EQ(mprotect(ptr, 3 * page_size, PROT_READ), 0); 635 ASSERT_EQ(mprotect(&ptr[7 * page_size], 3 * page_size, PROT_READ), 0); 636 637 /* Make sure the whole range is guarded for read. */ 638 for (i = 0; i < 10; i++) { 639 char *curr = &ptr[i * page_size]; 640 641 ASSERT_FALSE(try_read_buf(curr)); 642 } 643 644 /* Now reset protection bits so we merge the whole thing. */ 645 ASSERT_EQ(mprotect(ptr, 3 * page_size, PROT_READ | PROT_WRITE), 0); 646 ASSERT_EQ(mprotect(&ptr[7 * page_size], 3 * page_size, 647 PROT_READ | PROT_WRITE), 0); 648 649 /* Make sure the whole range is still guarded. */ 650 for (i = 0; i < 10; i++) { 651 char *curr = &ptr[i * page_size]; 652 653 ASSERT_FALSE(try_read_write_buf(curr)); 654 } 655 656 /* Split range into 3 again... */ 657 ASSERT_EQ(mprotect(ptr, 3 * page_size, PROT_READ), 0); 658 ASSERT_EQ(mprotect(&ptr[7 * page_size], 3 * page_size, PROT_READ), 0); 659 660 /* ...and unguard the whole range. */ 661 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0); 662 663 /* Make sure the whole range is remedied for read. */ 664 for (i = 0; i < 10; i++) { 665 char *curr = &ptr[i * page_size]; 666 667 ASSERT_TRUE(try_read_buf(curr)); 668 } 669 670 /* Merge them again. */ 671 ASSERT_EQ(mprotect(ptr, 3 * page_size, PROT_READ | PROT_WRITE), 0); 672 ASSERT_EQ(mprotect(&ptr[7 * page_size], 3 * page_size, 673 PROT_READ | PROT_WRITE), 0); 674 675 /* Now ensure the merged range is remedied for read/write. */ 676 for (i = 0; i < 10; i++) { 677 char *curr = &ptr[i * page_size]; 678 679 ASSERT_TRUE(try_read_write_buf(curr)); 680 } 681 682 /* Cleanup. */ 683 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 684} 685 686/* Assert that MADV_DONTNEED does not remove guard markers. */ 687TEST_F(guard_pages, dontneed) 688{ 689 const unsigned long page_size = self->page_size; 690 char *ptr; 691 int i; 692 693 ptr = mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE, 694 MAP_ANON | MAP_PRIVATE, -1, 0); 695 ASSERT_NE(ptr, MAP_FAILED); 696 697 /* Back the whole range. */ 698 for (i = 0; i < 10; i++) { 699 char *curr = &ptr[i * page_size]; 700 701 *curr = 'y'; 702 } 703 704 /* Guard every other page. */ 705 for (i = 0; i < 10; i += 2) { 706 char *curr = &ptr[i * page_size]; 707 int res = madvise(curr, page_size, MADV_GUARD_INSTALL); 708 709 ASSERT_EQ(res, 0); 710 } 711 712 /* Indicate that we don't need any of the range. */ 713 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_DONTNEED), 0); 714 715 /* Check to ensure guard markers are still in place. */ 716 for (i = 0; i < 10; i++) { 717 char *curr = &ptr[i * page_size]; 718 bool result = try_read_buf(curr); 719 720 if (i % 2 == 0) { 721 ASSERT_FALSE(result); 722 } else { 723 ASSERT_TRUE(result); 724 /* Make sure we really did get reset to zero page. */ 725 ASSERT_EQ(*curr, '\0'); 726 } 727 728 /* Now write... */ 729 result = try_write_buf(&ptr[i * page_size]); 730 731 /* ...and make sure same result. */ 732 ASSERT_TRUE(i % 2 != 0 ? result : !result); 733 } 734 735 /* Cleanup. */ 736 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 737} 738 739/* Assert that mlock()'ed pages work correctly with guard markers. */ 740TEST_F(guard_pages, mlock) 741{ 742 const unsigned long page_size = self->page_size; 743 char *ptr; 744 int i; 745 746 ptr = mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE, 747 MAP_ANON | MAP_PRIVATE, -1, 0); 748 ASSERT_NE(ptr, MAP_FAILED); 749 750 /* Populate. */ 751 for (i = 0; i < 10; i++) { 752 char *curr = &ptr[i * page_size]; 753 754 *curr = 'y'; 755 } 756 757 /* Lock. */ 758 ASSERT_EQ(mlock(ptr, 10 * page_size), 0); 759 760 /* Now try to guard, should fail with EINVAL. */ 761 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), -1); 762 ASSERT_EQ(errno, EINVAL); 763 764 /* OK unlock. */ 765 ASSERT_EQ(munlock(ptr, 10 * page_size), 0); 766 767 /* Guard first half of range, should now succeed. */ 768 ASSERT_EQ(madvise(ptr, 5 * page_size, MADV_GUARD_INSTALL), 0); 769 770 /* Make sure guard works. */ 771 for (i = 0; i < 10; i++) { 772 char *curr = &ptr[i * page_size]; 773 bool result = try_read_write_buf(curr); 774 775 if (i < 5) { 776 ASSERT_FALSE(result); 777 } else { 778 ASSERT_TRUE(result); 779 ASSERT_EQ(*curr, 'x'); 780 } 781 } 782 783 /* 784 * Now lock the latter part of the range. We can't lock the guard pages, 785 * as this would result in the pages being populated and the guarding 786 * would cause this to error out. 787 */ 788 ASSERT_EQ(mlock(&ptr[5 * page_size], 5 * page_size), 0); 789 790 /* 791 * Now remove guard pages, we permit mlock()'d ranges to have guard 792 * pages removed as it is a non-destructive operation. 793 */ 794 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0); 795 796 /* Now check that no guard pages remain. */ 797 for (i = 0; i < 10; i++) { 798 char *curr = &ptr[i * page_size]; 799 800 ASSERT_TRUE(try_read_write_buf(curr)); 801 } 802 803 /* Cleanup. */ 804 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 805} 806 807/* 808 * Assert that moving, extending and shrinking memory via mremap() retains 809 * guard markers where possible. 810 * 811 * - Moving a mapping alone should retain markers as they are. 812 */ 813TEST_F(guard_pages, mremap_move) 814{ 815 const unsigned long page_size = self->page_size; 816 char *ptr, *ptr_new; 817 818 /* Map 5 pages. */ 819 ptr = mmap(NULL, 5 * page_size, PROT_READ | PROT_WRITE, 820 MAP_ANON | MAP_PRIVATE, -1, 0); 821 ASSERT_NE(ptr, MAP_FAILED); 822 823 /* Place guard markers at both ends of the 5 page span. */ 824 ASSERT_EQ(madvise(ptr, page_size, MADV_GUARD_INSTALL), 0); 825 ASSERT_EQ(madvise(&ptr[4 * page_size], page_size, MADV_GUARD_INSTALL), 0); 826 827 /* Make sure the guard pages are in effect. */ 828 ASSERT_FALSE(try_read_write_buf(ptr)); 829 ASSERT_FALSE(try_read_write_buf(&ptr[4 * page_size])); 830 831 /* Map a new region we will move this range into. Doing this ensures 832 * that we have reserved a range to map into. 833 */ 834 ptr_new = mmap(NULL, 5 * page_size, PROT_NONE, MAP_ANON | MAP_PRIVATE, 835 -1, 0); 836 ASSERT_NE(ptr_new, MAP_FAILED); 837 838 ASSERT_EQ(mremap(ptr, 5 * page_size, 5 * page_size, 839 MREMAP_MAYMOVE | MREMAP_FIXED, ptr_new), ptr_new); 840 841 /* Make sure the guard markers are retained. */ 842 ASSERT_FALSE(try_read_write_buf(ptr_new)); 843 ASSERT_FALSE(try_read_write_buf(&ptr_new[4 * page_size])); 844 845 /* 846 * Clean up - we only need reference the new pointer as we overwrote the 847 * PROT_NONE range and moved the existing one. 848 */ 849 munmap(ptr_new, 5 * page_size); 850} 851 852/* 853 * Assert that moving, extending and shrinking memory via mremap() retains 854 * guard markers where possible. 855 * 856 * Expanding should retain guard pages, only now in different position. The user 857 * will have to remove guard pages manually to fix up (they'd have to do the 858 * same if it were a PROT_NONE mapping). 859 */ 860TEST_F(guard_pages, mremap_expand) 861{ 862 const unsigned long page_size = self->page_size; 863 char *ptr, *ptr_new; 864 865 /* Map 10 pages... */ 866 ptr = mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE, 867 MAP_ANON | MAP_PRIVATE, -1, 0); 868 ASSERT_NE(ptr, MAP_FAILED); 869 /* ...But unmap the last 5 so we can ensure we can expand into them. */ 870 ASSERT_EQ(munmap(&ptr[5 * page_size], 5 * page_size), 0); 871 872 /* Place guard markers at both ends of the 5 page span. */ 873 ASSERT_EQ(madvise(ptr, page_size, MADV_GUARD_INSTALL), 0); 874 ASSERT_EQ(madvise(&ptr[4 * page_size], page_size, MADV_GUARD_INSTALL), 0); 875 876 /* Make sure the guarding is in effect. */ 877 ASSERT_FALSE(try_read_write_buf(ptr)); 878 ASSERT_FALSE(try_read_write_buf(&ptr[4 * page_size])); 879 880 /* Now expand to 10 pages. */ 881 ptr = mremap(ptr, 5 * page_size, 10 * page_size, 0); 882 ASSERT_NE(ptr, MAP_FAILED); 883 884 /* 885 * Make sure the guard markers are retained in their original positions. 886 */ 887 ASSERT_FALSE(try_read_write_buf(ptr)); 888 ASSERT_FALSE(try_read_write_buf(&ptr[4 * page_size])); 889 890 /* Reserve a region which we can move to and expand into. */ 891 ptr_new = mmap(NULL, 20 * page_size, PROT_NONE, 892 MAP_ANON | MAP_PRIVATE, -1, 0); 893 ASSERT_NE(ptr_new, MAP_FAILED); 894 895 /* Now move and expand into it. */ 896 ptr = mremap(ptr, 10 * page_size, 20 * page_size, 897 MREMAP_MAYMOVE | MREMAP_FIXED, ptr_new); 898 ASSERT_EQ(ptr, ptr_new); 899 900 /* 901 * Again, make sure the guard markers are retained in their original positions. 902 */ 903 ASSERT_FALSE(try_read_write_buf(ptr)); 904 ASSERT_FALSE(try_read_write_buf(&ptr[4 * page_size])); 905 906 /* 907 * A real user would have to remove guard markers, but would reasonably 908 * expect all characteristics of the mapping to be retained, including 909 * guard markers. 910 */ 911 912 /* Cleanup. */ 913 munmap(ptr, 20 * page_size); 914} 915/* 916 * Assert that moving, extending and shrinking memory via mremap() retains 917 * guard markers where possible. 918 * 919 * Shrinking will result in markers that are shrunk over being removed. Again, 920 * if the user were using a PROT_NONE mapping they'd have to manually fix this 921 * up also so this is OK. 922 */ 923TEST_F(guard_pages, mremap_shrink) 924{ 925 const unsigned long page_size = self->page_size; 926 char *ptr; 927 int i; 928 929 /* Map 5 pages. */ 930 ptr = mmap(NULL, 5 * page_size, PROT_READ | PROT_WRITE, 931 MAP_ANON | MAP_PRIVATE, -1, 0); 932 ASSERT_NE(ptr, MAP_FAILED); 933 934 /* Place guard markers at both ends of the 5 page span. */ 935 ASSERT_EQ(madvise(ptr, page_size, MADV_GUARD_INSTALL), 0); 936 ASSERT_EQ(madvise(&ptr[4 * page_size], page_size, MADV_GUARD_INSTALL), 0); 937 938 /* Make sure the guarding is in effect. */ 939 ASSERT_FALSE(try_read_write_buf(ptr)); 940 ASSERT_FALSE(try_read_write_buf(&ptr[4 * page_size])); 941 942 /* Now shrink to 3 pages. */ 943 ptr = mremap(ptr, 5 * page_size, 3 * page_size, MREMAP_MAYMOVE); 944 ASSERT_NE(ptr, MAP_FAILED); 945 946 /* We expect the guard marker at the start to be retained... */ 947 ASSERT_FALSE(try_read_write_buf(ptr)); 948 949 /* ...But remaining pages will not have guard markers. */ 950 for (i = 1; i < 3; i++) { 951 char *curr = &ptr[i * page_size]; 952 953 ASSERT_TRUE(try_read_write_buf(curr)); 954 } 955 956 /* 957 * As with expansion, a real user would have to remove guard pages and 958 * fixup. But you'd have to do similar manual things with PROT_NONE 959 * mappings too. 960 */ 961 962 /* 963 * If we expand back to the original size, the end marker will, of 964 * course, no longer be present. 965 */ 966 ptr = mremap(ptr, 3 * page_size, 5 * page_size, 0); 967 ASSERT_NE(ptr, MAP_FAILED); 968 969 /* Again, we expect the guard marker at the start to be retained... */ 970 ASSERT_FALSE(try_read_write_buf(ptr)); 971 972 /* ...But remaining pages will not have guard markers. */ 973 for (i = 1; i < 5; i++) { 974 char *curr = &ptr[i * page_size]; 975 976 ASSERT_TRUE(try_read_write_buf(curr)); 977 } 978 979 /* Cleanup. */ 980 munmap(ptr, 5 * page_size); 981} 982 983/* 984 * Assert that forking a process with VMAs that do not have VM_WIPEONFORK set 985 * retain guard pages. 986 */ 987TEST_F(guard_pages, fork) 988{ 989 const unsigned long page_size = self->page_size; 990 char *ptr; 991 pid_t pid; 992 int i; 993 994 /* Map 10 pages. */ 995 ptr = mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE, 996 MAP_ANON | MAP_PRIVATE, -1, 0); 997 ASSERT_NE(ptr, MAP_FAILED); 998 999 /* Establish guard pages in the first 5 pages. */ 1000 ASSERT_EQ(madvise(ptr, 5 * page_size, MADV_GUARD_INSTALL), 0); 1001 1002 pid = fork(); 1003 ASSERT_NE(pid, -1); 1004 if (!pid) { 1005 /* This is the child process now. */ 1006 1007 /* Assert that the guarding is in effect. */ 1008 for (i = 0; i < 10; i++) { 1009 char *curr = &ptr[i * page_size]; 1010 bool result = try_read_write_buf(curr); 1011 1012 ASSERT_TRUE(i >= 5 ? result : !result); 1013 } 1014 1015 /* Now unguard the range.*/ 1016 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0); 1017 1018 exit(0); 1019 } 1020 1021 /* Parent process. */ 1022 1023 /* Parent simply waits on child. */ 1024 waitpid(pid, NULL, 0); 1025 1026 /* Child unguard does not impact parent page table state. */ 1027 for (i = 0; i < 10; i++) { 1028 char *curr = &ptr[i * page_size]; 1029 bool result = try_read_write_buf(curr); 1030 1031 ASSERT_TRUE(i >= 5 ? result : !result); 1032 } 1033 1034 /* Cleanup. */ 1035 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1036} 1037 1038/* 1039 * Assert expected behaviour after we fork populated ranges of anonymous memory 1040 * and then guard and unguard the range. 1041 */ 1042TEST_F(guard_pages, fork_cow) 1043{ 1044 const unsigned long page_size = self->page_size; 1045 char *ptr; 1046 pid_t pid; 1047 int i; 1048 1049 /* Map 10 pages. */ 1050 ptr = mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE, 1051 MAP_ANON | MAP_PRIVATE, -1, 0); 1052 ASSERT_NE(ptr, MAP_FAILED); 1053 1054 /* Populate range. */ 1055 for (i = 0; i < 10 * page_size; i++) { 1056 char chr = 'a' + (i % 26); 1057 1058 ptr[i] = chr; 1059 } 1060 1061 pid = fork(); 1062 ASSERT_NE(pid, -1); 1063 if (!pid) { 1064 /* This is the child process now. */ 1065 1066 /* Ensure the range is as expected. */ 1067 for (i = 0; i < 10 * page_size; i++) { 1068 char expected = 'a' + (i % 26); 1069 char actual = ptr[i]; 1070 1071 ASSERT_EQ(actual, expected); 1072 } 1073 1074 /* Establish guard pages across the whole range. */ 1075 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), 0); 1076 /* Remove it. */ 1077 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0); 1078 1079 /* 1080 * By removing the guard pages, the page tables will be 1081 * cleared. Assert that we are looking at the zero page now. 1082 */ 1083 for (i = 0; i < 10 * page_size; i++) { 1084 char actual = ptr[i]; 1085 1086 ASSERT_EQ(actual, '\0'); 1087 } 1088 1089 exit(0); 1090 } 1091 1092 /* Parent process. */ 1093 1094 /* Parent simply waits on child. */ 1095 waitpid(pid, NULL, 0); 1096 1097 /* Ensure the range is unchanged in parent anon range. */ 1098 for (i = 0; i < 10 * page_size; i++) { 1099 char expected = 'a' + (i % 26); 1100 char actual = ptr[i]; 1101 1102 ASSERT_EQ(actual, expected); 1103 } 1104 1105 /* Cleanup. */ 1106 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1107} 1108 1109/* 1110 * Assert that forking a process with VMAs that do have VM_WIPEONFORK set 1111 * behave as expected. 1112 */ 1113TEST_F(guard_pages, fork_wipeonfork) 1114{ 1115 const unsigned long page_size = self->page_size; 1116 char *ptr; 1117 pid_t pid; 1118 int i; 1119 1120 /* Map 10 pages. */ 1121 ptr = mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE, 1122 MAP_ANON | MAP_PRIVATE, -1, 0); 1123 ASSERT_NE(ptr, MAP_FAILED); 1124 1125 /* Mark wipe on fork. */ 1126 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_WIPEONFORK), 0); 1127 1128 /* Guard the first 5 pages. */ 1129 ASSERT_EQ(madvise(ptr, 5 * page_size, MADV_GUARD_INSTALL), 0); 1130 1131 pid = fork(); 1132 ASSERT_NE(pid, -1); 1133 if (!pid) { 1134 /* This is the child process now. */ 1135 1136 /* Guard will have been wiped. */ 1137 for (i = 0; i < 10; i++) { 1138 char *curr = &ptr[i * page_size]; 1139 1140 ASSERT_TRUE(try_read_write_buf(curr)); 1141 } 1142 1143 exit(0); 1144 } 1145 1146 /* Parent process. */ 1147 1148 waitpid(pid, NULL, 0); 1149 1150 /* Guard markers should be in effect.*/ 1151 for (i = 0; i < 10; i++) { 1152 char *curr = &ptr[i * page_size]; 1153 bool result = try_read_write_buf(curr); 1154 1155 ASSERT_TRUE(i >= 5 ? result : !result); 1156 } 1157 1158 /* Cleanup. */ 1159 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1160} 1161 1162/* Ensure that MADV_FREE retains guard entries as expected. */ 1163TEST_F(guard_pages, lazyfree) 1164{ 1165 const unsigned long page_size = self->page_size; 1166 char *ptr; 1167 int i; 1168 1169 /* Map 10 pages. */ 1170 ptr = mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE, 1171 MAP_ANON | MAP_PRIVATE, -1, 0); 1172 ASSERT_NE(ptr, MAP_FAILED); 1173 1174 /* Guard range. */ 1175 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), 0); 1176 1177 /* Ensure guarded. */ 1178 for (i = 0; i < 10; i++) { 1179 char *curr = &ptr[i * page_size]; 1180 1181 ASSERT_FALSE(try_read_write_buf(curr)); 1182 } 1183 1184 /* Lazyfree range. */ 1185 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_FREE), 0); 1186 1187 /* This should leave the guard markers in place. */ 1188 for (i = 0; i < 10; i++) { 1189 char *curr = &ptr[i * page_size]; 1190 1191 ASSERT_FALSE(try_read_write_buf(curr)); 1192 } 1193 1194 /* Cleanup. */ 1195 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1196} 1197 1198/* Ensure that MADV_POPULATE_READ, MADV_POPULATE_WRITE behave as expected. */ 1199TEST_F(guard_pages, populate) 1200{ 1201 const unsigned long page_size = self->page_size; 1202 char *ptr; 1203 1204 /* Map 10 pages. */ 1205 ptr = mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE, 1206 MAP_ANON | MAP_PRIVATE, -1, 0); 1207 ASSERT_NE(ptr, MAP_FAILED); 1208 1209 /* Guard range. */ 1210 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), 0); 1211 1212 /* Populate read should error out... */ 1213 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_POPULATE_READ), -1); 1214 ASSERT_EQ(errno, EFAULT); 1215 1216 /* ...as should populate write. */ 1217 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_POPULATE_WRITE), -1); 1218 ASSERT_EQ(errno, EFAULT); 1219 1220 /* Cleanup. */ 1221 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1222} 1223 1224/* Ensure that MADV_COLD, MADV_PAGEOUT do not remove guard markers. */ 1225TEST_F(guard_pages, cold_pageout) 1226{ 1227 const unsigned long page_size = self->page_size; 1228 char *ptr; 1229 int i; 1230 1231 /* Map 10 pages. */ 1232 ptr = mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE, 1233 MAP_ANON | MAP_PRIVATE, -1, 0); 1234 ASSERT_NE(ptr, MAP_FAILED); 1235 1236 /* Guard range. */ 1237 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), 0); 1238 1239 /* Ensured guarded. */ 1240 for (i = 0; i < 10; i++) { 1241 char *curr = &ptr[i * page_size]; 1242 1243 ASSERT_FALSE(try_read_write_buf(curr)); 1244 } 1245 1246 /* Now mark cold. This should have no impact on guard markers. */ 1247 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_COLD), 0); 1248 1249 /* Should remain guarded. */ 1250 for (i = 0; i < 10; i++) { 1251 char *curr = &ptr[i * page_size]; 1252 1253 ASSERT_FALSE(try_read_write_buf(curr)); 1254 } 1255 1256 /* OK, now page out. This should equally, have no effect on markers. */ 1257 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_PAGEOUT), 0); 1258 1259 /* Should remain guarded. */ 1260 for (i = 0; i < 10; i++) { 1261 char *curr = &ptr[i * page_size]; 1262 1263 ASSERT_FALSE(try_read_write_buf(curr)); 1264 } 1265 1266 /* Cleanup. */ 1267 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1268} 1269 1270/* Ensure that guard pages do not break userfaultd. */ 1271TEST_F(guard_pages, uffd) 1272{ 1273 const unsigned long page_size = self->page_size; 1274 int uffd; 1275 char *ptr; 1276 int i; 1277 struct uffdio_api api = { 1278 .api = UFFD_API, 1279 .features = 0, 1280 }; 1281 struct uffdio_register reg; 1282 struct uffdio_range range; 1283 1284 /* Set up uffd. */ 1285 uffd = userfaultfd(0); 1286 if (uffd == -1 && errno == EPERM) 1287 ksft_exit_skip("No userfaultfd permissions, try running as root.\n"); 1288 ASSERT_NE(uffd, -1); 1289 1290 ASSERT_EQ(ioctl(uffd, UFFDIO_API, &api), 0); 1291 1292 /* Map 10 pages. */ 1293 ptr = mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE, 1294 MAP_ANON | MAP_PRIVATE, -1, 0); 1295 ASSERT_NE(ptr, MAP_FAILED); 1296 1297 /* Register the range with uffd. */ 1298 range.start = (unsigned long)ptr; 1299 range.len = 10 * page_size; 1300 reg.range = range; 1301 reg.mode = UFFDIO_REGISTER_MODE_MISSING; 1302 ASSERT_EQ(ioctl(uffd, UFFDIO_REGISTER, &reg), 0); 1303 1304 /* Guard the range. This should not trigger the uffd. */ 1305 ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), 0); 1306 1307 /* The guarding should behave as usual with no uffd intervention. */ 1308 for (i = 0; i < 10; i++) { 1309 char *curr = &ptr[i * page_size]; 1310 1311 ASSERT_FALSE(try_read_write_buf(curr)); 1312 } 1313 1314 /* Cleanup. */ 1315 ASSERT_EQ(ioctl(uffd, UFFDIO_UNREGISTER, &range), 0); 1316 close(uffd); 1317 ASSERT_EQ(munmap(ptr, 10 * page_size), 0); 1318} 1319 1320TEST_HARNESS_MAIN