1 // SPDX-License-Identifier: GPL-2.0 2 #define _GNU_SOURCE 3 #include <linux/mman.h> 4 #include <sys/mman.h> 5 #include <stdint.h> 6 #include <asm-generic/unistd.h> 7 #include <string.h> 8 #include <sys/time.h> 9 #include <sys/resource.h> 10 #include <stdbool.h> 11 #include "../kselftest.h" 12 #include <syscall.h> 13 #include <errno.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <fcntl.h> 17 #include <sys/ioctl.h> 18 #include <sys/vfs.h> 19 #include <sys/stat.h> 20 #include "mseal_helpers.h" 21 22 static unsigned long get_vma_size(void *addr, int *prot) 23 { 24 FILE *maps; 25 char line[256]; 26 int size = 0; 27 uintptr_t addr_start, addr_end; 28 char protstr[5]; 29 *prot = 0; 30 31 maps = fopen("/proc/self/maps", "r"); 32 if (!maps) 33 return 0; 34 35 while (fgets(line, sizeof(line), maps)) { 36 if (sscanf(line, "%lx-%lx %4s", &addr_start, &addr_end, protstr) == 3) { 37 if (addr_start == (uintptr_t) addr) { 38 size = addr_end - addr_start; 39 if (protstr[0] == 'r') 40 *prot |= 0x4; 41 if (protstr[1] == 'w') 42 *prot |= 0x2; 43 if (protstr[2] == 'x') 44 *prot |= 0x1; 45 break; 46 } 47 } 48 } 49 fclose(maps); 50 return size; 51 } 52 53 /* 54 * define sys_xyx to call syscall directly. 55 */ 56 static int sys_mseal(void *start, size_t len) 57 { 58 int sret; 59 60 errno = 0; 61 sret = syscall(__NR_mseal, start, len, 0); 62 return sret; 63 } 64 65 static int sys_mprotect(void *ptr, size_t size, unsigned long prot) 66 { 67 int sret; 68 69 errno = 0; 70 sret = syscall(__NR_mprotect, ptr, size, prot); 71 return sret; 72 } 73 74 static int sys_mprotect_pkey(void *ptr, size_t size, unsigned long orig_prot, 75 unsigned long pkey) 76 { 77 int sret; 78 79 errno = 0; 80 sret = syscall(__NR_pkey_mprotect, ptr, size, orig_prot, pkey); 81 return sret; 82 } 83 84 static int sys_munmap(void *ptr, size_t size) 85 { 86 int sret; 87 88 errno = 0; 89 sret = syscall(__NR_munmap, ptr, size); 90 return sret; 91 } 92 93 static int sys_madvise(void *start, size_t len, int types) 94 { 95 int sret; 96 97 errno = 0; 98 sret = syscall(__NR_madvise, start, len, types); 99 return sret; 100 } 101 102 static void *sys_mremap(void *addr, size_t old_len, size_t new_len, 103 unsigned long flags, void *new_addr) 104 { 105 void *sret; 106 107 errno = 0; 108 sret = (void *) syscall(__NR_mremap, addr, old_len, new_len, flags, new_addr); 109 return sret; 110 } 111 112 static int sys_pkey_alloc(unsigned long flags, unsigned long init_val) 113 { 114 int ret = syscall(__NR_pkey_alloc, flags, init_val); 115 116 return ret; 117 } 118 119 static unsigned int __read_pkey_reg(void) 120 { 121 unsigned int pkey_reg = 0; 122 #if defined(__i386__) || defined(__x86_64__) /* arch */ 123 unsigned int eax, edx; 124 unsigned int ecx = 0; 125 126 asm volatile(".byte 0x0f,0x01,0xee\n\t" 127 : "=a" (eax), "=d" (edx) 128 : "c" (ecx)); 129 pkey_reg = eax; 130 #endif 131 return pkey_reg; 132 } 133 134 static void __write_pkey_reg(u64 pkey_reg) 135 { 136 #if defined(__i386__) || defined(__x86_64__) /* arch */ 137 unsigned int eax = pkey_reg; 138 unsigned int ecx = 0; 139 unsigned int edx = 0; 140 141 asm volatile(".byte 0x0f,0x01,0xef\n\t" 142 : : "a" (eax), "c" (ecx), "d" (edx)); 143 #endif 144 } 145 146 static unsigned long pkey_bit_position(int pkey) 147 { 148 return pkey * PKEY_BITS_PER_PKEY; 149 } 150 151 static u64 set_pkey_bits(u64 reg, int pkey, u64 flags) 152 { 153 unsigned long shift = pkey_bit_position(pkey); 154 155 /* mask out bits from pkey in old value */ 156 reg &= ~((u64)PKEY_MASK << shift); 157 /* OR in new bits for pkey */ 158 reg |= (flags & PKEY_MASK) << shift; 159 return reg; 160 } 161 162 static void set_pkey(int pkey, unsigned long pkey_value) 163 { 164 u64 new_pkey_reg; 165 166 new_pkey_reg = set_pkey_bits(__read_pkey_reg(), pkey, pkey_value); 167 __write_pkey_reg(new_pkey_reg); 168 } 169 170 static void setup_single_address(int size, void **ptrOut) 171 { 172 void *ptr; 173 174 ptr = mmap(NULL, size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 175 *ptrOut = ptr; 176 } 177 178 static void setup_single_address_rw(int size, void **ptrOut) 179 { 180 void *ptr; 181 unsigned long mapflags = MAP_ANONYMOUS | MAP_PRIVATE; 182 183 ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, mapflags, -1, 0); 184 *ptrOut = ptr; 185 } 186 187 static int clean_single_address(void *ptr, int size) 188 { 189 int ret; 190 ret = munmap(ptr, size); 191 return ret; 192 } 193 194 static int seal_single_address(void *ptr, int size) 195 { 196 int ret; 197 ret = sys_mseal(ptr, size); 198 return ret; 199 } 200 201 bool seal_support(void) 202 { 203 int ret; 204 void *ptr; 205 unsigned long page_size = getpagesize(); 206 207 ptr = mmap(NULL, page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 208 if (ptr == (void *) -1) 209 return false; 210 211 ret = sys_mseal(ptr, page_size); 212 if (ret < 0) 213 return false; 214 215 return true; 216 } 217 218 bool pkey_supported(void) 219 { 220 #if defined(__i386__) || defined(__x86_64__) /* arch */ 221 int pkey = sys_pkey_alloc(0, 0); 222 223 if (pkey > 0) 224 return true; 225 #endif 226 return false; 227 } 228 229 static void test_seal_addseal(void) 230 { 231 int ret; 232 void *ptr; 233 unsigned long page_size = getpagesize(); 234 unsigned long size = 4 * page_size; 235 236 setup_single_address(size, &ptr); 237 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 238 239 ret = sys_mseal(ptr, size); 240 FAIL_TEST_IF_FALSE(!ret); 241 242 REPORT_TEST_PASS(); 243 } 244 245 static void test_seal_unmapped_start(void) 246 { 247 int ret; 248 void *ptr; 249 unsigned long page_size = getpagesize(); 250 unsigned long size = 4 * page_size; 251 252 setup_single_address(size, &ptr); 253 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 254 255 /* munmap 2 pages from ptr. */ 256 ret = sys_munmap(ptr, 2 * page_size); 257 FAIL_TEST_IF_FALSE(!ret); 258 259 /* mprotect will fail because 2 pages from ptr are unmapped. */ 260 ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE); 261 FAIL_TEST_IF_FALSE(ret < 0); 262 263 /* mseal will fail because 2 pages from ptr are unmapped. */ 264 ret = sys_mseal(ptr, size); 265 FAIL_TEST_IF_FALSE(ret < 0); 266 267 ret = sys_mseal(ptr + 2 * page_size, 2 * page_size); 268 FAIL_TEST_IF_FALSE(!ret); 269 270 REPORT_TEST_PASS(); 271 } 272 273 static void test_seal_unmapped_middle(void) 274 { 275 int ret; 276 void *ptr; 277 unsigned long page_size = getpagesize(); 278 unsigned long size = 4 * page_size; 279 280 setup_single_address(size, &ptr); 281 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 282 283 /* munmap 2 pages from ptr + page. */ 284 ret = sys_munmap(ptr + page_size, 2 * page_size); 285 FAIL_TEST_IF_FALSE(!ret); 286 287 /* mprotect will fail, since middle 2 pages are unmapped. */ 288 ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE); 289 FAIL_TEST_IF_FALSE(ret < 0); 290 291 /* mseal will fail as well. */ 292 ret = sys_mseal(ptr, size); 293 FAIL_TEST_IF_FALSE(ret < 0); 294 295 /* we still can add seal to the first page and last page*/ 296 ret = sys_mseal(ptr, page_size); 297 FAIL_TEST_IF_FALSE(!ret); 298 299 ret = sys_mseal(ptr + 3 * page_size, page_size); 300 FAIL_TEST_IF_FALSE(!ret); 301 302 REPORT_TEST_PASS(); 303 } 304 305 static void test_seal_unmapped_end(void) 306 { 307 int ret; 308 void *ptr; 309 unsigned long page_size = getpagesize(); 310 unsigned long size = 4 * page_size; 311 312 setup_single_address(size, &ptr); 313 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 314 315 /* unmap last 2 pages. */ 316 ret = sys_munmap(ptr + 2 * page_size, 2 * page_size); 317 FAIL_TEST_IF_FALSE(!ret); 318 319 /* mprotect will fail since last 2 pages are unmapped. */ 320 ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE); 321 FAIL_TEST_IF_FALSE(ret < 0); 322 323 /* mseal will fail as well. */ 324 ret = sys_mseal(ptr, size); 325 FAIL_TEST_IF_FALSE(ret < 0); 326 327 /* The first 2 pages is not sealed, and can add seals */ 328 ret = sys_mseal(ptr, 2 * page_size); 329 FAIL_TEST_IF_FALSE(!ret); 330 331 REPORT_TEST_PASS(); 332 } 333 334 static void test_seal_multiple_vmas(void) 335 { 336 int ret; 337 void *ptr; 338 unsigned long page_size = getpagesize(); 339 unsigned long size = 4 * page_size; 340 341 setup_single_address(size, &ptr); 342 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 343 344 /* use mprotect to split the vma into 3. */ 345 ret = sys_mprotect(ptr + page_size, 2 * page_size, 346 PROT_READ | PROT_WRITE); 347 FAIL_TEST_IF_FALSE(!ret); 348 349 /* mprotect will get applied to all 4 pages - 3 VMAs. */ 350 ret = sys_mprotect(ptr, size, PROT_READ); 351 FAIL_TEST_IF_FALSE(!ret); 352 353 /* use mprotect to split the vma into 3. */ 354 ret = sys_mprotect(ptr + page_size, 2 * page_size, 355 PROT_READ | PROT_WRITE); 356 FAIL_TEST_IF_FALSE(!ret); 357 358 /* mseal get applied to all 4 pages - 3 VMAs. */ 359 ret = sys_mseal(ptr, size); 360 FAIL_TEST_IF_FALSE(!ret); 361 362 REPORT_TEST_PASS(); 363 } 364 365 static void test_seal_split_start(void) 366 { 367 int ret; 368 void *ptr; 369 unsigned long page_size = getpagesize(); 370 unsigned long size = 4 * page_size; 371 372 setup_single_address(size, &ptr); 373 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 374 375 /* use mprotect to split at middle */ 376 ret = sys_mprotect(ptr, 2 * page_size, PROT_READ | PROT_WRITE); 377 FAIL_TEST_IF_FALSE(!ret); 378 379 /* seal the first page, this will split the VMA */ 380 ret = sys_mseal(ptr, page_size); 381 FAIL_TEST_IF_FALSE(!ret); 382 383 /* add seal to the remain 3 pages */ 384 ret = sys_mseal(ptr + page_size, 3 * page_size); 385 FAIL_TEST_IF_FALSE(!ret); 386 387 REPORT_TEST_PASS(); 388 } 389 390 static void test_seal_split_end(void) 391 { 392 int ret; 393 void *ptr; 394 unsigned long page_size = getpagesize(); 395 unsigned long size = 4 * page_size; 396 397 setup_single_address(size, &ptr); 398 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 399 400 /* use mprotect to split at middle */ 401 ret = sys_mprotect(ptr, 2 * page_size, PROT_READ | PROT_WRITE); 402 FAIL_TEST_IF_FALSE(!ret); 403 404 /* seal the last page */ 405 ret = sys_mseal(ptr + 3 * page_size, page_size); 406 FAIL_TEST_IF_FALSE(!ret); 407 408 /* Adding seals to the first 3 pages */ 409 ret = sys_mseal(ptr, 3 * page_size); 410 FAIL_TEST_IF_FALSE(!ret); 411 412 REPORT_TEST_PASS(); 413 } 414 415 static void test_seal_invalid_input(void) 416 { 417 void *ptr; 418 unsigned long page_size = getpagesize(); 419 unsigned long size = 4 * page_size; 420 int ret; 421 422 setup_single_address(8 * page_size, &ptr); 423 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 424 ret = clean_single_address(ptr + 4 * page_size, 4 * page_size); 425 FAIL_TEST_IF_FALSE(!ret); 426 427 /* invalid flag */ 428 ret = syscall(__NR_mseal, ptr, size, 0x20); 429 FAIL_TEST_IF_FALSE(ret < 0); 430 431 /* unaligned address */ 432 ret = sys_mseal(ptr + 1, 2 * page_size); 433 FAIL_TEST_IF_FALSE(ret < 0); 434 435 /* length too big */ 436 ret = sys_mseal(ptr, 5 * page_size); 437 FAIL_TEST_IF_FALSE(ret < 0); 438 439 /* length overflow */ 440 ret = sys_mseal(ptr, UINT64_MAX/page_size); 441 FAIL_TEST_IF_FALSE(ret < 0); 442 443 /* start is not in a valid VMA */ 444 ret = sys_mseal(ptr - page_size, 5 * page_size); 445 FAIL_TEST_IF_FALSE(ret < 0); 446 447 REPORT_TEST_PASS(); 448 } 449 450 static void test_seal_zero_length(void) 451 { 452 void *ptr; 453 unsigned long page_size = getpagesize(); 454 unsigned long size = 4 * page_size; 455 int ret; 456 457 setup_single_address(size, &ptr); 458 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 459 460 ret = sys_mprotect(ptr, 0, PROT_READ | PROT_WRITE); 461 FAIL_TEST_IF_FALSE(!ret); 462 463 /* seal 0 length will be OK, same as mprotect */ 464 ret = sys_mseal(ptr, 0); 465 FAIL_TEST_IF_FALSE(!ret); 466 467 /* verify the 4 pages are not sealed by previous call. */ 468 ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE); 469 FAIL_TEST_IF_FALSE(!ret); 470 471 REPORT_TEST_PASS(); 472 } 473 474 static void test_seal_zero_address(void) 475 { 476 void *ptr; 477 unsigned long page_size = getpagesize(); 478 unsigned long size = 4 * page_size; 479 int ret; 480 int prot; 481 482 /* use mmap to change protection. */ 483 ptr = mmap(0, size, PROT_NONE, 484 MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); 485 FAIL_TEST_IF_FALSE(ptr == 0); 486 487 size = get_vma_size(ptr, &prot); 488 FAIL_TEST_IF_FALSE(size == 4 * page_size); 489 490 ret = sys_mseal(ptr, size); 491 FAIL_TEST_IF_FALSE(!ret); 492 493 /* verify the 4 pages are sealed by previous call. */ 494 ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE); 495 FAIL_TEST_IF_FALSE(ret); 496 497 REPORT_TEST_PASS(); 498 } 499 500 static void test_seal_twice(void) 501 { 502 int ret; 503 void *ptr; 504 unsigned long page_size = getpagesize(); 505 unsigned long size = 4 * page_size; 506 507 setup_single_address(size, &ptr); 508 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 509 510 ret = sys_mseal(ptr, size); 511 FAIL_TEST_IF_FALSE(!ret); 512 513 /* apply the same seal will be OK. idempotent. */ 514 ret = sys_mseal(ptr, size); 515 FAIL_TEST_IF_FALSE(!ret); 516 517 REPORT_TEST_PASS(); 518 } 519 520 static void test_seal_mprotect(bool seal) 521 { 522 void *ptr; 523 unsigned long page_size = getpagesize(); 524 unsigned long size = 4 * page_size; 525 int ret; 526 527 setup_single_address(size, &ptr); 528 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 529 530 if (seal) { 531 ret = seal_single_address(ptr, size); 532 FAIL_TEST_IF_FALSE(!ret); 533 } 534 535 ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE); 536 if (seal) 537 FAIL_TEST_IF_FALSE(ret < 0); 538 else 539 FAIL_TEST_IF_FALSE(!ret); 540 541 REPORT_TEST_PASS(); 542 } 543 544 static void test_seal_start_mprotect(bool seal) 545 { 546 void *ptr; 547 unsigned long page_size = getpagesize(); 548 unsigned long size = 4 * page_size; 549 int ret; 550 551 setup_single_address(size, &ptr); 552 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 553 554 if (seal) { 555 ret = seal_single_address(ptr, page_size); 556 FAIL_TEST_IF_FALSE(!ret); 557 } 558 559 /* the first page is sealed. */ 560 ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); 561 if (seal) 562 FAIL_TEST_IF_FALSE(ret < 0); 563 else 564 FAIL_TEST_IF_FALSE(!ret); 565 566 /* pages after the first page is not sealed. */ 567 ret = sys_mprotect(ptr + page_size, page_size * 3, 568 PROT_READ | PROT_WRITE); 569 FAIL_TEST_IF_FALSE(!ret); 570 571 REPORT_TEST_PASS(); 572 } 573 574 static void test_seal_end_mprotect(bool seal) 575 { 576 void *ptr; 577 unsigned long page_size = getpagesize(); 578 unsigned long size = 4 * page_size; 579 int ret; 580 581 setup_single_address(size, &ptr); 582 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 583 584 if (seal) { 585 ret = seal_single_address(ptr + page_size, 3 * page_size); 586 FAIL_TEST_IF_FALSE(!ret); 587 } 588 589 /* first page is not sealed */ 590 ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); 591 FAIL_TEST_IF_FALSE(!ret); 592 593 /* last 3 page are sealed */ 594 ret = sys_mprotect(ptr + page_size, page_size * 3, 595 PROT_READ | PROT_WRITE); 596 if (seal) 597 FAIL_TEST_IF_FALSE(ret < 0); 598 else 599 FAIL_TEST_IF_FALSE(!ret); 600 601 REPORT_TEST_PASS(); 602 } 603 604 static void test_seal_mprotect_unalign_len(bool seal) 605 { 606 void *ptr; 607 unsigned long page_size = getpagesize(); 608 unsigned long size = 4 * page_size; 609 int ret; 610 611 setup_single_address(size, &ptr); 612 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 613 614 if (seal) { 615 ret = seal_single_address(ptr, page_size * 2 - 1); 616 FAIL_TEST_IF_FALSE(!ret); 617 } 618 619 /* 2 pages are sealed. */ 620 ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE); 621 if (seal) 622 FAIL_TEST_IF_FALSE(ret < 0); 623 else 624 FAIL_TEST_IF_FALSE(!ret); 625 626 ret = sys_mprotect(ptr + page_size * 2, page_size, 627 PROT_READ | PROT_WRITE); 628 FAIL_TEST_IF_FALSE(!ret); 629 630 REPORT_TEST_PASS(); 631 } 632 633 static void test_seal_mprotect_unalign_len_variant_2(bool seal) 634 { 635 void *ptr; 636 unsigned long page_size = getpagesize(); 637 unsigned long size = 4 * page_size; 638 int ret; 639 640 setup_single_address(size, &ptr); 641 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 642 if (seal) { 643 ret = seal_single_address(ptr, page_size * 2 + 1); 644 FAIL_TEST_IF_FALSE(!ret); 645 } 646 647 /* 3 pages are sealed. */ 648 ret = sys_mprotect(ptr, page_size * 3, PROT_READ | PROT_WRITE); 649 if (seal) 650 FAIL_TEST_IF_FALSE(ret < 0); 651 else 652 FAIL_TEST_IF_FALSE(!ret); 653 654 ret = sys_mprotect(ptr + page_size * 3, page_size, 655 PROT_READ | PROT_WRITE); 656 FAIL_TEST_IF_FALSE(!ret); 657 658 REPORT_TEST_PASS(); 659 } 660 661 static void test_seal_mprotect_two_vma(bool seal) 662 { 663 void *ptr; 664 unsigned long page_size = getpagesize(); 665 unsigned long size = 4 * page_size; 666 int ret; 667 668 setup_single_address(size, &ptr); 669 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 670 671 /* use mprotect to split */ 672 ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE); 673 FAIL_TEST_IF_FALSE(!ret); 674 675 if (seal) { 676 ret = seal_single_address(ptr, page_size * 4); 677 FAIL_TEST_IF_FALSE(!ret); 678 } 679 680 ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE); 681 if (seal) 682 FAIL_TEST_IF_FALSE(ret < 0); 683 else 684 FAIL_TEST_IF_FALSE(!ret); 685 686 ret = sys_mprotect(ptr + page_size * 2, page_size * 2, 687 PROT_READ | PROT_WRITE); 688 if (seal) 689 FAIL_TEST_IF_FALSE(ret < 0); 690 else 691 FAIL_TEST_IF_FALSE(!ret); 692 693 REPORT_TEST_PASS(); 694 } 695 696 static void test_seal_mprotect_two_vma_with_split(bool seal) 697 { 698 void *ptr; 699 unsigned long page_size = getpagesize(); 700 unsigned long size = 4 * page_size; 701 int ret; 702 703 setup_single_address(size, &ptr); 704 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 705 706 /* use mprotect to split as two vma. */ 707 ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE); 708 FAIL_TEST_IF_FALSE(!ret); 709 710 /* mseal can apply across 2 vma, also split them. */ 711 if (seal) { 712 ret = seal_single_address(ptr + page_size, page_size * 2); 713 FAIL_TEST_IF_FALSE(!ret); 714 } 715 716 /* the first page is not sealed. */ 717 ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); 718 FAIL_TEST_IF_FALSE(!ret); 719 720 /* the second page is sealed. */ 721 ret = sys_mprotect(ptr + page_size, page_size, PROT_READ | PROT_WRITE); 722 if (seal) 723 FAIL_TEST_IF_FALSE(ret < 0); 724 else 725 FAIL_TEST_IF_FALSE(!ret); 726 727 /* the third page is sealed. */ 728 ret = sys_mprotect(ptr + 2 * page_size, page_size, 729 PROT_READ | PROT_WRITE); 730 if (seal) 731 FAIL_TEST_IF_FALSE(ret < 0); 732 else 733 FAIL_TEST_IF_FALSE(!ret); 734 735 /* the fouth page is not sealed. */ 736 ret = sys_mprotect(ptr + 3 * page_size, page_size, 737 PROT_READ | PROT_WRITE); 738 FAIL_TEST_IF_FALSE(!ret); 739 740 REPORT_TEST_PASS(); 741 } 742 743 static void test_seal_mprotect_partial_mprotect(bool seal) 744 { 745 void *ptr; 746 unsigned long page_size = getpagesize(); 747 unsigned long size = 4 * page_size; 748 int ret; 749 750 setup_single_address(size, &ptr); 751 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 752 753 /* seal one page. */ 754 if (seal) { 755 ret = seal_single_address(ptr, page_size); 756 FAIL_TEST_IF_FALSE(!ret); 757 } 758 759 /* mprotect first 2 page will fail, since the first page are sealed. */ 760 ret = sys_mprotect(ptr, 2 * page_size, PROT_READ | PROT_WRITE); 761 if (seal) 762 FAIL_TEST_IF_FALSE(ret < 0); 763 else 764 FAIL_TEST_IF_FALSE(!ret); 765 766 REPORT_TEST_PASS(); 767 } 768 769 static void test_seal_mprotect_partial_mprotect_tail(bool seal) 770 { 771 void *ptr; 772 unsigned long page_size = getpagesize(); 773 unsigned long size = 2 * page_size; 774 int ret; 775 int prot; 776 777 /* 778 * Check if a partial mseal (that results in two vmas) works correctly. 779 * It might mprotect the first, but it'll never touch the second (msealed) vma. 780 */ 781 782 setup_single_address(size, &ptr); 783 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 784 785 if (seal) { 786 ret = sys_mseal(ptr + page_size, page_size); 787 FAIL_TEST_IF_FALSE(!ret); 788 } 789 790 ret = sys_mprotect(ptr, size, PROT_EXEC); 791 if (seal) 792 FAIL_TEST_IF_FALSE(ret < 0); 793 else 794 FAIL_TEST_IF_FALSE(!ret); 795 796 if (seal) { 797 FAIL_TEST_IF_FALSE(get_vma_size(ptr + page_size, &prot) > 0); 798 FAIL_TEST_IF_FALSE(prot == 0x4); 799 } 800 801 REPORT_TEST_PASS(); 802 } 803 804 805 static void test_seal_mprotect_two_vma_with_gap(bool seal) 806 { 807 void *ptr; 808 unsigned long page_size = getpagesize(); 809 unsigned long size = 4 * page_size; 810 int ret; 811 812 setup_single_address(size, &ptr); 813 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 814 815 /* use mprotect to split. */ 816 ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); 817 FAIL_TEST_IF_FALSE(!ret); 818 819 /* use mprotect to split. */ 820 ret = sys_mprotect(ptr + 3 * page_size, page_size, 821 PROT_READ | PROT_WRITE); 822 FAIL_TEST_IF_FALSE(!ret); 823 824 /* use munmap to free two pages in the middle */ 825 ret = sys_munmap(ptr + page_size, 2 * page_size); 826 FAIL_TEST_IF_FALSE(!ret); 827 828 /* mprotect will fail, because there is a gap in the address. */ 829 /* notes, internally mprotect still updated the first page. */ 830 ret = sys_mprotect(ptr, 4 * page_size, PROT_READ); 831 FAIL_TEST_IF_FALSE(ret < 0); 832 833 /* mseal will fail as well. */ 834 ret = sys_mseal(ptr, 4 * page_size); 835 FAIL_TEST_IF_FALSE(ret < 0); 836 837 /* the first page is not sealed. */ 838 ret = sys_mprotect(ptr, page_size, PROT_READ); 839 FAIL_TEST_IF_FALSE(ret == 0); 840 841 /* the last page is not sealed. */ 842 ret = sys_mprotect(ptr + 3 * page_size, page_size, PROT_READ); 843 FAIL_TEST_IF_FALSE(ret == 0); 844 845 REPORT_TEST_PASS(); 846 } 847 848 static void test_seal_mprotect_split(bool seal) 849 { 850 void *ptr; 851 unsigned long page_size = getpagesize(); 852 unsigned long size = 4 * page_size; 853 int ret; 854 855 setup_single_address(size, &ptr); 856 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 857 858 /* use mprotect to split. */ 859 ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); 860 FAIL_TEST_IF_FALSE(!ret); 861 862 /* seal all 4 pages. */ 863 if (seal) { 864 ret = sys_mseal(ptr, 4 * page_size); 865 FAIL_TEST_IF_FALSE(!ret); 866 } 867 868 /* mprotect is sealed. */ 869 ret = sys_mprotect(ptr, 2 * page_size, PROT_READ); 870 if (seal) 871 FAIL_TEST_IF_FALSE(ret < 0); 872 else 873 FAIL_TEST_IF_FALSE(!ret); 874 875 876 ret = sys_mprotect(ptr + 2 * page_size, 2 * page_size, PROT_READ); 877 if (seal) 878 FAIL_TEST_IF_FALSE(ret < 0); 879 else 880 FAIL_TEST_IF_FALSE(!ret); 881 882 REPORT_TEST_PASS(); 883 } 884 885 static void test_seal_mprotect_merge(bool seal) 886 { 887 void *ptr; 888 unsigned long page_size = getpagesize(); 889 unsigned long size = 4 * page_size; 890 int ret; 891 892 setup_single_address(size, &ptr); 893 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 894 895 /* use mprotect to split one page. */ 896 ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); 897 FAIL_TEST_IF_FALSE(!ret); 898 899 /* seal first two pages. */ 900 if (seal) { 901 ret = sys_mseal(ptr, 2 * page_size); 902 FAIL_TEST_IF_FALSE(!ret); 903 } 904 905 /* 2 pages are sealed. */ 906 ret = sys_mprotect(ptr, 2 * page_size, PROT_READ); 907 if (seal) 908 FAIL_TEST_IF_FALSE(ret < 0); 909 else 910 FAIL_TEST_IF_FALSE(!ret); 911 912 /* last 2 pages are not sealed. */ 913 ret = sys_mprotect(ptr + 2 * page_size, 2 * page_size, PROT_READ); 914 FAIL_TEST_IF_FALSE(ret == 0); 915 916 REPORT_TEST_PASS(); 917 } 918 919 static void test_seal_munmap(bool seal) 920 { 921 void *ptr; 922 unsigned long page_size = getpagesize(); 923 unsigned long size = 4 * page_size; 924 int ret; 925 926 setup_single_address(size, &ptr); 927 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 928 929 if (seal) { 930 ret = sys_mseal(ptr, size); 931 FAIL_TEST_IF_FALSE(!ret); 932 } 933 934 /* 4 pages are sealed. */ 935 ret = sys_munmap(ptr, size); 936 if (seal) 937 FAIL_TEST_IF_FALSE(ret < 0); 938 else 939 FAIL_TEST_IF_FALSE(!ret); 940 941 REPORT_TEST_PASS(); 942 } 943 944 /* 945 * allocate 4 pages, 946 * use mprotect to split it as two VMAs 947 * seal the whole range 948 * munmap will fail on both 949 */ 950 static void test_seal_munmap_two_vma(bool seal) 951 { 952 void *ptr; 953 unsigned long page_size = getpagesize(); 954 unsigned long size = 4 * page_size; 955 int ret; 956 957 setup_single_address(size, &ptr); 958 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 959 960 /* use mprotect to split */ 961 ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE); 962 FAIL_TEST_IF_FALSE(!ret); 963 964 if (seal) { 965 ret = sys_mseal(ptr, size); 966 FAIL_TEST_IF_FALSE(!ret); 967 } 968 969 ret = sys_munmap(ptr, page_size * 2); 970 if (seal) 971 FAIL_TEST_IF_FALSE(ret < 0); 972 else 973 FAIL_TEST_IF_FALSE(!ret); 974 975 ret = sys_munmap(ptr + page_size, page_size * 2); 976 if (seal) 977 FAIL_TEST_IF_FALSE(ret < 0); 978 else 979 FAIL_TEST_IF_FALSE(!ret); 980 981 REPORT_TEST_PASS(); 982 } 983 984 /* 985 * allocate a VMA with 4 pages. 986 * munmap the middle 2 pages. 987 * seal the whole 4 pages, will fail. 988 * munmap the first page will be OK. 989 * munmap the last page will be OK. 990 */ 991 static void test_seal_munmap_vma_with_gap(bool seal) 992 { 993 void *ptr; 994 unsigned long page_size = getpagesize(); 995 unsigned long size = 4 * page_size; 996 int ret; 997 998 setup_single_address(size, &ptr); 999 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1000 1001 ret = sys_munmap(ptr + page_size, page_size * 2); 1002 FAIL_TEST_IF_FALSE(!ret); 1003 1004 if (seal) { 1005 /* can't have gap in the middle. */ 1006 ret = sys_mseal(ptr, size); 1007 FAIL_TEST_IF_FALSE(ret < 0); 1008 } 1009 1010 ret = sys_munmap(ptr, page_size); 1011 FAIL_TEST_IF_FALSE(!ret); 1012 1013 ret = sys_munmap(ptr + page_size * 2, page_size); 1014 FAIL_TEST_IF_FALSE(!ret); 1015 1016 ret = sys_munmap(ptr, size); 1017 FAIL_TEST_IF_FALSE(!ret); 1018 1019 REPORT_TEST_PASS(); 1020 } 1021 1022 static void test_seal_munmap_partial_across_vmas(bool seal) 1023 { 1024 void *ptr; 1025 unsigned long page_size = getpagesize(); 1026 unsigned long size = 2 * page_size; 1027 int ret; 1028 int prot; 1029 1030 setup_single_address(size, &ptr); 1031 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1032 1033 if (seal) { 1034 ret = sys_mseal(ptr + page_size, page_size); 1035 FAIL_TEST_IF_FALSE(!ret); 1036 } 1037 1038 ret = sys_munmap(ptr, size); 1039 if (seal) 1040 FAIL_TEST_IF_FALSE(ret < 0); 1041 else 1042 FAIL_TEST_IF_FALSE(!ret); 1043 1044 if (seal) { 1045 FAIL_TEST_IF_FALSE(get_vma_size(ptr + page_size, &prot) > 0); 1046 FAIL_TEST_IF_FALSE(prot == 0x4); 1047 } 1048 1049 REPORT_TEST_PASS(); 1050 } 1051 1052 static void test_munmap_start_freed(bool seal) 1053 { 1054 void *ptr; 1055 unsigned long page_size = getpagesize(); 1056 unsigned long size = 4 * page_size; 1057 int ret; 1058 int prot; 1059 1060 setup_single_address(size, &ptr); 1061 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1062 1063 /* unmap the first page. */ 1064 ret = sys_munmap(ptr, page_size); 1065 FAIL_TEST_IF_FALSE(!ret); 1066 1067 /* seal the last 3 pages. */ 1068 if (seal) { 1069 ret = sys_mseal(ptr + page_size, 3 * page_size); 1070 FAIL_TEST_IF_FALSE(!ret); 1071 } 1072 1073 /* unmap from the first page. */ 1074 ret = sys_munmap(ptr, size); 1075 if (seal) { 1076 FAIL_TEST_IF_FALSE(ret < 0); 1077 1078 size = get_vma_size(ptr + page_size, &prot); 1079 FAIL_TEST_IF_FALSE(size == page_size * 3); 1080 } else { 1081 /* note: this will be OK, even the first page is */ 1082 /* already unmapped. */ 1083 FAIL_TEST_IF_FALSE(!ret); 1084 1085 size = get_vma_size(ptr + page_size, &prot); 1086 FAIL_TEST_IF_FALSE(size == 0); 1087 } 1088 1089 REPORT_TEST_PASS(); 1090 } 1091 1092 static void test_munmap_end_freed(bool seal) 1093 { 1094 void *ptr; 1095 unsigned long page_size = getpagesize(); 1096 unsigned long size = 4 * page_size; 1097 int ret; 1098 1099 setup_single_address(size, &ptr); 1100 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1101 1102 /* unmap last page. */ 1103 ret = sys_munmap(ptr + page_size * 3, page_size); 1104 FAIL_TEST_IF_FALSE(!ret); 1105 1106 /* seal the first 3 pages. */ 1107 if (seal) { 1108 ret = sys_mseal(ptr, 3 * page_size); 1109 FAIL_TEST_IF_FALSE(!ret); 1110 } 1111 1112 /* unmap all pages. */ 1113 ret = sys_munmap(ptr, size); 1114 if (seal) 1115 FAIL_TEST_IF_FALSE(ret < 0); 1116 else 1117 FAIL_TEST_IF_FALSE(!ret); 1118 1119 REPORT_TEST_PASS(); 1120 } 1121 1122 static void test_munmap_middle_freed(bool seal) 1123 { 1124 void *ptr; 1125 unsigned long page_size = getpagesize(); 1126 unsigned long size = 4 * page_size; 1127 int ret; 1128 int prot; 1129 1130 setup_single_address(size, &ptr); 1131 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1132 1133 /* unmap 2 pages in the middle. */ 1134 ret = sys_munmap(ptr + page_size, page_size * 2); 1135 FAIL_TEST_IF_FALSE(!ret); 1136 1137 /* seal the first page. */ 1138 if (seal) { 1139 ret = sys_mseal(ptr, page_size); 1140 FAIL_TEST_IF_FALSE(!ret); 1141 } 1142 1143 /* munmap all 4 pages. */ 1144 ret = sys_munmap(ptr, size); 1145 if (seal) { 1146 FAIL_TEST_IF_FALSE(ret < 0); 1147 1148 size = get_vma_size(ptr, &prot); 1149 FAIL_TEST_IF_FALSE(size == page_size); 1150 1151 size = get_vma_size(ptr + page_size * 3, &prot); 1152 FAIL_TEST_IF_FALSE(size == page_size); 1153 } else { 1154 FAIL_TEST_IF_FALSE(!ret); 1155 1156 size = get_vma_size(ptr, &prot); 1157 FAIL_TEST_IF_FALSE(size == 0); 1158 1159 size = get_vma_size(ptr + page_size * 3, &prot); 1160 FAIL_TEST_IF_FALSE(size == 0); 1161 } 1162 1163 REPORT_TEST_PASS(); 1164 } 1165 1166 static void test_seal_mremap_shrink(bool seal) 1167 { 1168 void *ptr; 1169 unsigned long page_size = getpagesize(); 1170 unsigned long size = 4 * page_size; 1171 int ret; 1172 void *ret2; 1173 1174 setup_single_address(size, &ptr); 1175 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1176 1177 if (seal) { 1178 ret = sys_mseal(ptr, size); 1179 FAIL_TEST_IF_FALSE(!ret); 1180 } 1181 1182 /* shrink from 4 pages to 2 pages. */ 1183 ret2 = sys_mremap(ptr, size, 2 * page_size, 0, 0); 1184 if (seal) { 1185 FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED); 1186 FAIL_TEST_IF_FALSE(errno == EPERM); 1187 } else { 1188 FAIL_TEST_IF_FALSE(ret2 != (void *) MAP_FAILED); 1189 1190 } 1191 1192 REPORT_TEST_PASS(); 1193 } 1194 1195 static void test_seal_mremap_expand(bool seal) 1196 { 1197 void *ptr; 1198 unsigned long page_size = getpagesize(); 1199 unsigned long size = 4 * page_size; 1200 int ret; 1201 void *ret2; 1202 1203 setup_single_address(size, &ptr); 1204 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1205 /* ummap last 2 pages. */ 1206 ret = sys_munmap(ptr + 2 * page_size, 2 * page_size); 1207 FAIL_TEST_IF_FALSE(!ret); 1208 1209 if (seal) { 1210 ret = sys_mseal(ptr, 2 * page_size); 1211 FAIL_TEST_IF_FALSE(!ret); 1212 } 1213 1214 /* expand from 2 page to 4 pages. */ 1215 ret2 = sys_mremap(ptr, 2 * page_size, 4 * page_size, 0, 0); 1216 if (seal) { 1217 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1218 FAIL_TEST_IF_FALSE(errno == EPERM); 1219 } else { 1220 FAIL_TEST_IF_FALSE(ret2 == ptr); 1221 1222 } 1223 1224 REPORT_TEST_PASS(); 1225 } 1226 1227 static void test_seal_mremap_move(bool seal) 1228 { 1229 void *ptr, *newPtr; 1230 unsigned long page_size = getpagesize(); 1231 unsigned long size = page_size; 1232 int ret; 1233 void *ret2; 1234 1235 setup_single_address(size, &ptr); 1236 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1237 setup_single_address(size, &newPtr); 1238 FAIL_TEST_IF_FALSE(newPtr != (void *)-1); 1239 ret = clean_single_address(newPtr, size); 1240 FAIL_TEST_IF_FALSE(!ret); 1241 1242 if (seal) { 1243 ret = sys_mseal(ptr, size); 1244 FAIL_TEST_IF_FALSE(!ret); 1245 } 1246 1247 /* move from ptr to fixed address. */ 1248 ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, newPtr); 1249 if (seal) { 1250 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1251 FAIL_TEST_IF_FALSE(errno == EPERM); 1252 } else { 1253 FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED); 1254 1255 } 1256 1257 REPORT_TEST_PASS(); 1258 } 1259 1260 static void test_seal_mmap_overwrite_prot(bool seal) 1261 { 1262 void *ptr; 1263 unsigned long page_size = getpagesize(); 1264 unsigned long size = page_size; 1265 int ret; 1266 void *ret2; 1267 1268 setup_single_address(size, &ptr); 1269 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1270 1271 if (seal) { 1272 ret = sys_mseal(ptr, size); 1273 FAIL_TEST_IF_FALSE(!ret); 1274 } 1275 1276 /* use mmap to change protection. */ 1277 ret2 = mmap(ptr, size, PROT_NONE, 1278 MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); 1279 if (seal) { 1280 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1281 FAIL_TEST_IF_FALSE(errno == EPERM); 1282 } else 1283 FAIL_TEST_IF_FALSE(ret2 == ptr); 1284 1285 REPORT_TEST_PASS(); 1286 } 1287 1288 static void test_seal_mmap_expand(bool seal) 1289 { 1290 void *ptr; 1291 unsigned long page_size = getpagesize(); 1292 unsigned long size = 12 * page_size; 1293 int ret; 1294 void *ret2; 1295 1296 setup_single_address(size, &ptr); 1297 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1298 /* ummap last 4 pages. */ 1299 ret = sys_munmap(ptr + 8 * page_size, 4 * page_size); 1300 FAIL_TEST_IF_FALSE(!ret); 1301 1302 if (seal) { 1303 ret = sys_mseal(ptr, 8 * page_size); 1304 FAIL_TEST_IF_FALSE(!ret); 1305 } 1306 1307 /* use mmap to expand. */ 1308 ret2 = mmap(ptr, size, PROT_READ, 1309 MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); 1310 if (seal) { 1311 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1312 FAIL_TEST_IF_FALSE(errno == EPERM); 1313 } else 1314 FAIL_TEST_IF_FALSE(ret2 == ptr); 1315 1316 REPORT_TEST_PASS(); 1317 } 1318 1319 static void test_seal_mmap_shrink(bool seal) 1320 { 1321 void *ptr; 1322 unsigned long page_size = getpagesize(); 1323 unsigned long size = 12 * page_size; 1324 int ret; 1325 void *ret2; 1326 1327 setup_single_address(size, &ptr); 1328 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1329 1330 if (seal) { 1331 ret = sys_mseal(ptr, size); 1332 FAIL_TEST_IF_FALSE(!ret); 1333 } 1334 1335 /* use mmap to shrink. */ 1336 ret2 = mmap(ptr, 8 * page_size, PROT_READ, 1337 MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); 1338 if (seal) { 1339 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1340 FAIL_TEST_IF_FALSE(errno == EPERM); 1341 } else 1342 FAIL_TEST_IF_FALSE(ret2 == ptr); 1343 1344 REPORT_TEST_PASS(); 1345 } 1346 1347 static void test_seal_mremap_shrink_fixed(bool seal) 1348 { 1349 void *ptr; 1350 void *newAddr; 1351 unsigned long page_size = getpagesize(); 1352 unsigned long size = 4 * page_size; 1353 int ret; 1354 void *ret2; 1355 1356 setup_single_address(size, &ptr); 1357 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1358 setup_single_address(size, &newAddr); 1359 FAIL_TEST_IF_FALSE(newAddr != (void *)-1); 1360 1361 if (seal) { 1362 ret = sys_mseal(ptr, size); 1363 FAIL_TEST_IF_FALSE(!ret); 1364 } 1365 1366 /* mremap to move and shrink to fixed address */ 1367 ret2 = sys_mremap(ptr, size, 2 * page_size, MREMAP_MAYMOVE | MREMAP_FIXED, 1368 newAddr); 1369 if (seal) { 1370 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1371 FAIL_TEST_IF_FALSE(errno == EPERM); 1372 } else 1373 FAIL_TEST_IF_FALSE(ret2 == newAddr); 1374 1375 REPORT_TEST_PASS(); 1376 } 1377 1378 static void test_seal_mremap_expand_fixed(bool seal) 1379 { 1380 void *ptr; 1381 void *newAddr; 1382 unsigned long page_size = getpagesize(); 1383 unsigned long size = 4 * page_size; 1384 int ret; 1385 void *ret2; 1386 1387 setup_single_address(page_size, &ptr); 1388 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1389 setup_single_address(size, &newAddr); 1390 FAIL_TEST_IF_FALSE(newAddr != (void *)-1); 1391 1392 if (seal) { 1393 ret = sys_mseal(newAddr, size); 1394 FAIL_TEST_IF_FALSE(!ret); 1395 } 1396 1397 /* mremap to move and expand to fixed address */ 1398 ret2 = sys_mremap(ptr, page_size, size, MREMAP_MAYMOVE | MREMAP_FIXED, 1399 newAddr); 1400 if (seal) { 1401 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1402 FAIL_TEST_IF_FALSE(errno == EPERM); 1403 } else 1404 FAIL_TEST_IF_FALSE(ret2 == newAddr); 1405 1406 REPORT_TEST_PASS(); 1407 } 1408 1409 static void test_seal_mremap_move_fixed(bool seal) 1410 { 1411 void *ptr; 1412 void *newAddr; 1413 unsigned long page_size = getpagesize(); 1414 unsigned long size = 4 * page_size; 1415 int ret; 1416 void *ret2; 1417 1418 setup_single_address(size, &ptr); 1419 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1420 setup_single_address(size, &newAddr); 1421 FAIL_TEST_IF_FALSE(newAddr != (void *)-1); 1422 1423 if (seal) { 1424 ret = sys_mseal(newAddr, size); 1425 FAIL_TEST_IF_FALSE(!ret); 1426 } 1427 1428 /* mremap to move to fixed address */ 1429 ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, newAddr); 1430 if (seal) { 1431 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1432 FAIL_TEST_IF_FALSE(errno == EPERM); 1433 } else 1434 FAIL_TEST_IF_FALSE(ret2 == newAddr); 1435 1436 REPORT_TEST_PASS(); 1437 } 1438 1439 static void test_seal_mremap_move_fixed_zero(bool seal) 1440 { 1441 void *ptr; 1442 unsigned long page_size = getpagesize(); 1443 unsigned long size = 4 * page_size; 1444 int ret; 1445 void *ret2; 1446 1447 setup_single_address(size, &ptr); 1448 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1449 1450 if (seal) { 1451 ret = sys_mseal(ptr, size); 1452 FAIL_TEST_IF_FALSE(!ret); 1453 } 1454 1455 /* 1456 * MREMAP_FIXED can move the mapping to zero address 1457 */ 1458 ret2 = sys_mremap(ptr, size, 2 * page_size, MREMAP_MAYMOVE | MREMAP_FIXED, 1459 0); 1460 if (seal) { 1461 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1462 FAIL_TEST_IF_FALSE(errno == EPERM); 1463 } else { 1464 FAIL_TEST_IF_FALSE(ret2 == 0); 1465 } 1466 1467 REPORT_TEST_PASS(); 1468 } 1469 1470 static void test_seal_mremap_move_dontunmap(bool seal) 1471 { 1472 void *ptr; 1473 unsigned long page_size = getpagesize(); 1474 unsigned long size = 4 * page_size; 1475 int ret; 1476 void *ret2; 1477 1478 setup_single_address(size, &ptr); 1479 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1480 1481 if (seal) { 1482 ret = sys_mseal(ptr, size); 1483 FAIL_TEST_IF_FALSE(!ret); 1484 } 1485 1486 /* mremap to move, and don't unmap src addr. */ 1487 ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_DONTUNMAP, 0); 1488 if (seal) { 1489 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1490 FAIL_TEST_IF_FALSE(errno == EPERM); 1491 } else { 1492 /* kernel will allocate a new address */ 1493 FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED); 1494 } 1495 1496 REPORT_TEST_PASS(); 1497 } 1498 1499 static void test_seal_mremap_move_dontunmap_anyaddr(bool seal) 1500 { 1501 void *ptr, *ptr2; 1502 unsigned long page_size = getpagesize(); 1503 unsigned long size = 4 * page_size; 1504 int ret; 1505 void *ret2; 1506 1507 setup_single_address(size, &ptr); 1508 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1509 1510 if (seal) { 1511 ret = sys_mseal(ptr, size); 1512 FAIL_TEST_IF_FALSE(!ret); 1513 } 1514 1515 /* 1516 * The new address is any address that not allocated. 1517 * use allocate/free to similate that. 1518 */ 1519 setup_single_address(size, &ptr2); 1520 FAIL_TEST_IF_FALSE(ptr2 != (void *)-1); 1521 ret = sys_munmap(ptr2, size); 1522 FAIL_TEST_IF_FALSE(!ret); 1523 1524 /* 1525 * remap to any address. 1526 */ 1527 ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_DONTUNMAP, 1528 (void *) ptr2); 1529 if (seal) { 1530 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1531 FAIL_TEST_IF_FALSE(errno == EPERM); 1532 } else { 1533 /* remap success and return ptr2 */ 1534 FAIL_TEST_IF_FALSE(ret2 == ptr2); 1535 } 1536 1537 REPORT_TEST_PASS(); 1538 } 1539 1540 static void test_seal_merge_and_split(void) 1541 { 1542 void *ptr; 1543 unsigned long page_size = getpagesize(); 1544 unsigned long size; 1545 int ret; 1546 int prot; 1547 1548 /* (24 RO) */ 1549 setup_single_address(24 * page_size, &ptr); 1550 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1551 1552 /* use mprotect(NONE) to set out boundary */ 1553 /* (1 NONE) (22 RO) (1 NONE) */ 1554 ret = sys_mprotect(ptr, page_size, PROT_NONE); 1555 FAIL_TEST_IF_FALSE(!ret); 1556 ret = sys_mprotect(ptr + 23 * page_size, page_size, PROT_NONE); 1557 FAIL_TEST_IF_FALSE(!ret); 1558 size = get_vma_size(ptr + page_size, &prot); 1559 FAIL_TEST_IF_FALSE(size == 22 * page_size); 1560 FAIL_TEST_IF_FALSE(prot == 4); 1561 1562 /* use mseal to split from beginning */ 1563 /* (1 NONE) (1 RO_SEAL) (21 RO) (1 NONE) */ 1564 ret = sys_mseal(ptr + page_size, page_size); 1565 FAIL_TEST_IF_FALSE(!ret); 1566 size = get_vma_size(ptr + page_size, &prot); 1567 FAIL_TEST_IF_FALSE(size == page_size); 1568 FAIL_TEST_IF_FALSE(prot == 0x4); 1569 size = get_vma_size(ptr + 2 * page_size, &prot); 1570 FAIL_TEST_IF_FALSE(size == 21 * page_size); 1571 FAIL_TEST_IF_FALSE(prot == 0x4); 1572 1573 /* use mseal to split from the end. */ 1574 /* (1 NONE) (1 RO_SEAL) (20 RO) (1 RO_SEAL) (1 NONE) */ 1575 ret = sys_mseal(ptr + 22 * page_size, page_size); 1576 FAIL_TEST_IF_FALSE(!ret); 1577 size = get_vma_size(ptr + 22 * page_size, &prot); 1578 FAIL_TEST_IF_FALSE(size == page_size); 1579 FAIL_TEST_IF_FALSE(prot == 0x4); 1580 size = get_vma_size(ptr + 2 * page_size, &prot); 1581 FAIL_TEST_IF_FALSE(size == 20 * page_size); 1582 FAIL_TEST_IF_FALSE(prot == 0x4); 1583 1584 /* merge with prev. */ 1585 /* (1 NONE) (2 RO_SEAL) (19 RO) (1 RO_SEAL) (1 NONE) */ 1586 ret = sys_mseal(ptr + 2 * page_size, page_size); 1587 FAIL_TEST_IF_FALSE(!ret); 1588 size = get_vma_size(ptr + page_size, &prot); 1589 FAIL_TEST_IF_FALSE(size == 2 * page_size); 1590 FAIL_TEST_IF_FALSE(prot == 0x4); 1591 1592 /* merge with after. */ 1593 /* (1 NONE) (2 RO_SEAL) (18 RO) (2 RO_SEALS) (1 NONE) */ 1594 ret = sys_mseal(ptr + 21 * page_size, page_size); 1595 FAIL_TEST_IF_FALSE(!ret); 1596 size = get_vma_size(ptr + 21 * page_size, &prot); 1597 FAIL_TEST_IF_FALSE(size == 2 * page_size); 1598 FAIL_TEST_IF_FALSE(prot == 0x4); 1599 1600 /* split and merge from prev */ 1601 /* (1 NONE) (3 RO_SEAL) (17 RO) (2 RO_SEALS) (1 NONE) */ 1602 ret = sys_mseal(ptr + 2 * page_size, 2 * page_size); 1603 FAIL_TEST_IF_FALSE(!ret); 1604 size = get_vma_size(ptr + 1 * page_size, &prot); 1605 FAIL_TEST_IF_FALSE(size == 3 * page_size); 1606 FAIL_TEST_IF_FALSE(prot == 0x4); 1607 ret = sys_munmap(ptr + page_size, page_size); 1608 FAIL_TEST_IF_FALSE(ret < 0); 1609 ret = sys_mprotect(ptr + 2 * page_size, page_size, PROT_NONE); 1610 FAIL_TEST_IF_FALSE(ret < 0); 1611 1612 /* split and merge from next */ 1613 /* (1 NONE) (3 RO_SEAL) (16 RO) (3 RO_SEALS) (1 NONE) */ 1614 ret = sys_mseal(ptr + 20 * page_size, 2 * page_size); 1615 FAIL_TEST_IF_FALSE(!ret); 1616 FAIL_TEST_IF_FALSE(prot == 0x4); 1617 size = get_vma_size(ptr + 20 * page_size, &prot); 1618 FAIL_TEST_IF_FALSE(size == 3 * page_size); 1619 FAIL_TEST_IF_FALSE(prot == 0x4); 1620 1621 /* merge from middle of prev and middle of next. */ 1622 /* (1 NONE) (22 RO_SEAL) (1 NONE) */ 1623 ret = sys_mseal(ptr + 2 * page_size, 20 * page_size); 1624 FAIL_TEST_IF_FALSE(!ret); 1625 size = get_vma_size(ptr + page_size, &prot); 1626 FAIL_TEST_IF_FALSE(size == 22 * page_size); 1627 FAIL_TEST_IF_FALSE(prot == 0x4); 1628 1629 REPORT_TEST_PASS(); 1630 } 1631 1632 static void test_seal_discard_ro_anon_on_rw(bool seal) 1633 { 1634 void *ptr; 1635 unsigned long page_size = getpagesize(); 1636 unsigned long size = 4 * page_size; 1637 int ret; 1638 1639 setup_single_address_rw(size, &ptr); 1640 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1641 1642 if (seal) { 1643 ret = sys_mseal(ptr, size); 1644 FAIL_TEST_IF_FALSE(!ret); 1645 } 1646 1647 /* sealing doesn't take effect on RW memory. */ 1648 ret = sys_madvise(ptr, size, MADV_DONTNEED); 1649 FAIL_TEST_IF_FALSE(!ret); 1650 1651 /* base seal still apply. */ 1652 ret = sys_munmap(ptr, size); 1653 if (seal) 1654 FAIL_TEST_IF_FALSE(ret < 0); 1655 else 1656 FAIL_TEST_IF_FALSE(!ret); 1657 1658 REPORT_TEST_PASS(); 1659 } 1660 1661 static void test_seal_discard_ro_anon_on_pkey(bool seal) 1662 { 1663 void *ptr; 1664 unsigned long page_size = getpagesize(); 1665 unsigned long size = 4 * page_size; 1666 int ret; 1667 int pkey; 1668 1669 SKIP_TEST_IF_FALSE(pkey_supported()); 1670 1671 setup_single_address_rw(size, &ptr); 1672 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1673 1674 pkey = sys_pkey_alloc(0, 0); 1675 FAIL_TEST_IF_FALSE(pkey > 0); 1676 1677 ret = sys_mprotect_pkey((void *)ptr, size, PROT_READ | PROT_WRITE, pkey); 1678 FAIL_TEST_IF_FALSE(!ret); 1679 1680 if (seal) { 1681 ret = sys_mseal(ptr, size); 1682 FAIL_TEST_IF_FALSE(!ret); 1683 } 1684 1685 /* sealing doesn't take effect if PKRU allow write. */ 1686 set_pkey(pkey, 0); 1687 ret = sys_madvise(ptr, size, MADV_DONTNEED); 1688 FAIL_TEST_IF_FALSE(!ret); 1689 1690 /* sealing will take effect if PKRU deny write. */ 1691 set_pkey(pkey, PKEY_DISABLE_WRITE); 1692 ret = sys_madvise(ptr, size, MADV_DONTNEED); 1693 if (seal) 1694 FAIL_TEST_IF_FALSE(ret < 0); 1695 else 1696 FAIL_TEST_IF_FALSE(!ret); 1697 1698 /* base seal still apply. */ 1699 ret = sys_munmap(ptr, size); 1700 if (seal) 1701 FAIL_TEST_IF_FALSE(ret < 0); 1702 else 1703 FAIL_TEST_IF_FALSE(!ret); 1704 1705 REPORT_TEST_PASS(); 1706 } 1707 1708 static void test_seal_discard_ro_anon_on_filebacked(bool seal) 1709 { 1710 void *ptr; 1711 unsigned long page_size = getpagesize(); 1712 unsigned long size = 4 * page_size; 1713 int ret; 1714 int fd; 1715 unsigned long mapflags = MAP_PRIVATE; 1716 1717 fd = memfd_create("test", 0); 1718 FAIL_TEST_IF_FALSE(fd > 0); 1719 1720 ret = fallocate(fd, 0, 0, size); 1721 FAIL_TEST_IF_FALSE(!ret); 1722 1723 ptr = mmap(NULL, size, PROT_READ, mapflags, fd, 0); 1724 FAIL_TEST_IF_FALSE(ptr != MAP_FAILED); 1725 1726 if (seal) { 1727 ret = sys_mseal(ptr, size); 1728 FAIL_TEST_IF_FALSE(!ret); 1729 } 1730 1731 /* sealing doesn't apply for file backed mapping. */ 1732 ret = sys_madvise(ptr, size, MADV_DONTNEED); 1733 FAIL_TEST_IF_FALSE(!ret); 1734 1735 ret = sys_munmap(ptr, size); 1736 if (seal) 1737 FAIL_TEST_IF_FALSE(ret < 0); 1738 else 1739 FAIL_TEST_IF_FALSE(!ret); 1740 close(fd); 1741 1742 REPORT_TEST_PASS(); 1743 } 1744 1745 static void test_seal_discard_ro_anon_on_shared(bool seal) 1746 { 1747 void *ptr; 1748 unsigned long page_size = getpagesize(); 1749 unsigned long size = 4 * page_size; 1750 int ret; 1751 unsigned long mapflags = MAP_ANONYMOUS | MAP_SHARED; 1752 1753 ptr = mmap(NULL, size, PROT_READ, mapflags, -1, 0); 1754 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1755 1756 if (seal) { 1757 ret = sys_mseal(ptr, size); 1758 FAIL_TEST_IF_FALSE(!ret); 1759 } 1760 1761 /* sealing doesn't apply for shared mapping. */ 1762 ret = sys_madvise(ptr, size, MADV_DONTNEED); 1763 FAIL_TEST_IF_FALSE(!ret); 1764 1765 ret = sys_munmap(ptr, size); 1766 if (seal) 1767 FAIL_TEST_IF_FALSE(ret < 0); 1768 else 1769 FAIL_TEST_IF_FALSE(!ret); 1770 1771 REPORT_TEST_PASS(); 1772 } 1773 1774 static void test_seal_discard_ro_anon(bool seal) 1775 { 1776 void *ptr; 1777 unsigned long page_size = getpagesize(); 1778 unsigned long size = 4 * page_size; 1779 int ret; 1780 1781 setup_single_address(size, &ptr); 1782 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1783 1784 if (seal) { 1785 ret = seal_single_address(ptr, size); 1786 FAIL_TEST_IF_FALSE(!ret); 1787 } 1788 1789 ret = sys_madvise(ptr, size, MADV_DONTNEED); 1790 if (seal) 1791 FAIL_TEST_IF_FALSE(ret < 0); 1792 else 1793 FAIL_TEST_IF_FALSE(!ret); 1794 1795 ret = sys_munmap(ptr, size); 1796 if (seal) 1797 FAIL_TEST_IF_FALSE(ret < 0); 1798 else 1799 FAIL_TEST_IF_FALSE(!ret); 1800 1801 REPORT_TEST_PASS(); 1802 } 1803 1804 static void test_seal_discard_across_vmas(bool seal) 1805 { 1806 void *ptr; 1807 unsigned long page_size = getpagesize(); 1808 unsigned long size = 2 * page_size; 1809 int ret; 1810 1811 setup_single_address(size, &ptr); 1812 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1813 1814 if (seal) { 1815 ret = seal_single_address(ptr + page_size, page_size); 1816 FAIL_TEST_IF_FALSE(!ret); 1817 } 1818 1819 ret = sys_madvise(ptr, size, MADV_DONTNEED); 1820 if (seal) 1821 FAIL_TEST_IF_FALSE(ret < 0); 1822 else 1823 FAIL_TEST_IF_FALSE(!ret); 1824 1825 ret = sys_munmap(ptr, size); 1826 if (seal) 1827 FAIL_TEST_IF_FALSE(ret < 0); 1828 else 1829 FAIL_TEST_IF_FALSE(!ret); 1830 1831 REPORT_TEST_PASS(); 1832 } 1833 1834 1835 static void test_seal_madvise_nodiscard(bool seal) 1836 { 1837 void *ptr; 1838 unsigned long page_size = getpagesize(); 1839 unsigned long size = 4 * page_size; 1840 int ret; 1841 1842 setup_single_address(size, &ptr); 1843 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1844 1845 if (seal) { 1846 ret = seal_single_address(ptr, size); 1847 FAIL_TEST_IF_FALSE(!ret); 1848 } 1849 1850 /* 1851 * Test a random madvise flag like MADV_RANDOM that does not touch page 1852 * contents (and thus should work for msealed VMAs). RANDOM also happens to 1853 * share bits with other discard-ish flags like REMOVE. 1854 */ 1855 ret = sys_madvise(ptr, size, MADV_RANDOM); 1856 FAIL_TEST_IF_FALSE(!ret); 1857 1858 ret = sys_munmap(ptr, size); 1859 if (seal) 1860 FAIL_TEST_IF_FALSE(ret < 0); 1861 else 1862 FAIL_TEST_IF_FALSE(!ret); 1863 1864 REPORT_TEST_PASS(); 1865 } 1866 1867 int main(int argc, char **argv) 1868 { 1869 bool test_seal = seal_support(); 1870 1871 ksft_print_header(); 1872 1873 if (!test_seal) 1874 ksft_exit_skip("sealing not supported, check CONFIG_64BIT\n"); 1875 1876 if (!pkey_supported()) 1877 ksft_print_msg("PKEY not supported\n"); 1878 1879 ksft_set_plan(88); 1880 1881 test_seal_addseal(); 1882 test_seal_unmapped_start(); 1883 test_seal_unmapped_middle(); 1884 test_seal_unmapped_end(); 1885 test_seal_multiple_vmas(); 1886 test_seal_split_start(); 1887 test_seal_split_end(); 1888 test_seal_invalid_input(); 1889 test_seal_zero_length(); 1890 test_seal_twice(); 1891 1892 test_seal_mprotect(false); 1893 test_seal_mprotect(true); 1894 1895 test_seal_start_mprotect(false); 1896 test_seal_start_mprotect(true); 1897 1898 test_seal_end_mprotect(false); 1899 test_seal_end_mprotect(true); 1900 1901 test_seal_mprotect_unalign_len(false); 1902 test_seal_mprotect_unalign_len(true); 1903 1904 test_seal_mprotect_unalign_len_variant_2(false); 1905 test_seal_mprotect_unalign_len_variant_2(true); 1906 1907 test_seal_mprotect_two_vma(false); 1908 test_seal_mprotect_two_vma(true); 1909 1910 test_seal_mprotect_two_vma_with_split(false); 1911 test_seal_mprotect_two_vma_with_split(true); 1912 1913 test_seal_mprotect_partial_mprotect(false); 1914 test_seal_mprotect_partial_mprotect(true); 1915 1916 test_seal_mprotect_two_vma_with_gap(false); 1917 test_seal_mprotect_two_vma_with_gap(true); 1918 1919 test_seal_mprotect_merge(false); 1920 test_seal_mprotect_merge(true); 1921 1922 test_seal_mprotect_split(false); 1923 test_seal_mprotect_split(true); 1924 1925 test_seal_mprotect_partial_mprotect_tail(false); 1926 test_seal_mprotect_partial_mprotect_tail(true); 1927 1928 test_seal_munmap(false); 1929 test_seal_munmap(true); 1930 test_seal_munmap_two_vma(false); 1931 test_seal_munmap_two_vma(true); 1932 test_seal_munmap_vma_with_gap(false); 1933 test_seal_munmap_vma_with_gap(true); 1934 test_seal_munmap_partial_across_vmas(false); 1935 test_seal_munmap_partial_across_vmas(true); 1936 1937 test_munmap_start_freed(false); 1938 test_munmap_start_freed(true); 1939 test_munmap_middle_freed(false); 1940 test_munmap_middle_freed(true); 1941 test_munmap_end_freed(false); 1942 test_munmap_end_freed(true); 1943 1944 test_seal_mremap_shrink(false); 1945 test_seal_mremap_shrink(true); 1946 test_seal_mremap_expand(false); 1947 test_seal_mremap_expand(true); 1948 test_seal_mremap_move(false); 1949 test_seal_mremap_move(true); 1950 1951 test_seal_mremap_shrink_fixed(false); 1952 test_seal_mremap_shrink_fixed(true); 1953 test_seal_mremap_expand_fixed(false); 1954 test_seal_mremap_expand_fixed(true); 1955 test_seal_mremap_move_fixed(false); 1956 test_seal_mremap_move_fixed(true); 1957 test_seal_mremap_move_dontunmap(false); 1958 test_seal_mremap_move_dontunmap(true); 1959 test_seal_mremap_move_fixed_zero(false); 1960 test_seal_mremap_move_fixed_zero(true); 1961 test_seal_mremap_move_dontunmap_anyaddr(false); 1962 test_seal_mremap_move_dontunmap_anyaddr(true); 1963 test_seal_madvise_nodiscard(false); 1964 test_seal_madvise_nodiscard(true); 1965 test_seal_discard_ro_anon(false); 1966 test_seal_discard_ro_anon(true); 1967 test_seal_discard_across_vmas(false); 1968 test_seal_discard_across_vmas(true); 1969 test_seal_discard_ro_anon_on_rw(false); 1970 test_seal_discard_ro_anon_on_rw(true); 1971 test_seal_discard_ro_anon_on_shared(false); 1972 test_seal_discard_ro_anon_on_shared(true); 1973 test_seal_discard_ro_anon_on_filebacked(false); 1974 test_seal_discard_ro_anon_on_filebacked(true); 1975 test_seal_mmap_overwrite_prot(false); 1976 test_seal_mmap_overwrite_prot(true); 1977 test_seal_mmap_expand(false); 1978 test_seal_mmap_expand(true); 1979 test_seal_mmap_shrink(false); 1980 test_seal_mmap_shrink(true); 1981 1982 test_seal_merge_and_split(); 1983 test_seal_zero_address(); 1984 1985 test_seal_discard_ro_anon_on_pkey(false); 1986 test_seal_discard_ro_anon_on_pkey(true); 1987 1988 ksft_finished(); 1989 } 1990