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