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_two_vma_with_gap(bool seal) 770 { 771 void *ptr; 772 unsigned long page_size = getpagesize(); 773 unsigned long size = 4 * page_size; 774 int ret; 775 776 setup_single_address(size, &ptr); 777 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 778 779 /* use mprotect to split. */ 780 ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); 781 FAIL_TEST_IF_FALSE(!ret); 782 783 /* use mprotect to split. */ 784 ret = sys_mprotect(ptr + 3 * page_size, page_size, 785 PROT_READ | PROT_WRITE); 786 FAIL_TEST_IF_FALSE(!ret); 787 788 /* use munmap to free two pages in the middle */ 789 ret = sys_munmap(ptr + page_size, 2 * page_size); 790 FAIL_TEST_IF_FALSE(!ret); 791 792 /* mprotect will fail, because there is a gap in the address. */ 793 /* notes, internally mprotect still updated the first page. */ 794 ret = sys_mprotect(ptr, 4 * page_size, PROT_READ); 795 FAIL_TEST_IF_FALSE(ret < 0); 796 797 /* mseal will fail as well. */ 798 ret = sys_mseal(ptr, 4 * page_size); 799 FAIL_TEST_IF_FALSE(ret < 0); 800 801 /* the first page is not sealed. */ 802 ret = sys_mprotect(ptr, page_size, PROT_READ); 803 FAIL_TEST_IF_FALSE(ret == 0); 804 805 /* the last page is not sealed. */ 806 ret = sys_mprotect(ptr + 3 * page_size, page_size, PROT_READ); 807 FAIL_TEST_IF_FALSE(ret == 0); 808 809 REPORT_TEST_PASS(); 810 } 811 812 static void test_seal_mprotect_split(bool seal) 813 { 814 void *ptr; 815 unsigned long page_size = getpagesize(); 816 unsigned long size = 4 * page_size; 817 int ret; 818 819 setup_single_address(size, &ptr); 820 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 821 822 /* use mprotect to split. */ 823 ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); 824 FAIL_TEST_IF_FALSE(!ret); 825 826 /* seal all 4 pages. */ 827 if (seal) { 828 ret = sys_mseal(ptr, 4 * page_size); 829 FAIL_TEST_IF_FALSE(!ret); 830 } 831 832 /* mprotect is sealed. */ 833 ret = sys_mprotect(ptr, 2 * page_size, PROT_READ); 834 if (seal) 835 FAIL_TEST_IF_FALSE(ret < 0); 836 else 837 FAIL_TEST_IF_FALSE(!ret); 838 839 840 ret = sys_mprotect(ptr + 2 * page_size, 2 * page_size, PROT_READ); 841 if (seal) 842 FAIL_TEST_IF_FALSE(ret < 0); 843 else 844 FAIL_TEST_IF_FALSE(!ret); 845 846 REPORT_TEST_PASS(); 847 } 848 849 static void test_seal_mprotect_merge(bool seal) 850 { 851 void *ptr; 852 unsigned long page_size = getpagesize(); 853 unsigned long size = 4 * page_size; 854 int ret; 855 856 setup_single_address(size, &ptr); 857 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 858 859 /* use mprotect to split one page. */ 860 ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); 861 FAIL_TEST_IF_FALSE(!ret); 862 863 /* seal first two pages. */ 864 if (seal) { 865 ret = sys_mseal(ptr, 2 * page_size); 866 FAIL_TEST_IF_FALSE(!ret); 867 } 868 869 /* 2 pages are sealed. */ 870 ret = sys_mprotect(ptr, 2 * page_size, PROT_READ); 871 if (seal) 872 FAIL_TEST_IF_FALSE(ret < 0); 873 else 874 FAIL_TEST_IF_FALSE(!ret); 875 876 /* last 2 pages are not sealed. */ 877 ret = sys_mprotect(ptr + 2 * page_size, 2 * page_size, PROT_READ); 878 FAIL_TEST_IF_FALSE(ret == 0); 879 880 REPORT_TEST_PASS(); 881 } 882 883 static void test_seal_munmap(bool seal) 884 { 885 void *ptr; 886 unsigned long page_size = getpagesize(); 887 unsigned long size = 4 * page_size; 888 int ret; 889 890 setup_single_address(size, &ptr); 891 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 892 893 if (seal) { 894 ret = sys_mseal(ptr, size); 895 FAIL_TEST_IF_FALSE(!ret); 896 } 897 898 /* 4 pages are sealed. */ 899 ret = sys_munmap(ptr, size); 900 if (seal) 901 FAIL_TEST_IF_FALSE(ret < 0); 902 else 903 FAIL_TEST_IF_FALSE(!ret); 904 905 REPORT_TEST_PASS(); 906 } 907 908 /* 909 * allocate 4 pages, 910 * use mprotect to split it as two VMAs 911 * seal the whole range 912 * munmap will fail on both 913 */ 914 static void test_seal_munmap_two_vma(bool seal) 915 { 916 void *ptr; 917 unsigned long page_size = getpagesize(); 918 unsigned long size = 4 * page_size; 919 int ret; 920 921 setup_single_address(size, &ptr); 922 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 923 924 /* use mprotect to split */ 925 ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE); 926 FAIL_TEST_IF_FALSE(!ret); 927 928 if (seal) { 929 ret = sys_mseal(ptr, size); 930 FAIL_TEST_IF_FALSE(!ret); 931 } 932 933 ret = sys_munmap(ptr, page_size * 2); 934 if (seal) 935 FAIL_TEST_IF_FALSE(ret < 0); 936 else 937 FAIL_TEST_IF_FALSE(!ret); 938 939 ret = sys_munmap(ptr + page_size, page_size * 2); 940 if (seal) 941 FAIL_TEST_IF_FALSE(ret < 0); 942 else 943 FAIL_TEST_IF_FALSE(!ret); 944 945 REPORT_TEST_PASS(); 946 } 947 948 /* 949 * allocate a VMA with 4 pages. 950 * munmap the middle 2 pages. 951 * seal the whole 4 pages, will fail. 952 * munmap the first page will be OK. 953 * munmap the last page will be OK. 954 */ 955 static void test_seal_munmap_vma_with_gap(bool seal) 956 { 957 void *ptr; 958 unsigned long page_size = getpagesize(); 959 unsigned long size = 4 * page_size; 960 int ret; 961 962 setup_single_address(size, &ptr); 963 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 964 965 ret = sys_munmap(ptr + page_size, page_size * 2); 966 FAIL_TEST_IF_FALSE(!ret); 967 968 if (seal) { 969 /* can't have gap in the middle. */ 970 ret = sys_mseal(ptr, size); 971 FAIL_TEST_IF_FALSE(ret < 0); 972 } 973 974 ret = sys_munmap(ptr, page_size); 975 FAIL_TEST_IF_FALSE(!ret); 976 977 ret = sys_munmap(ptr + page_size * 2, page_size); 978 FAIL_TEST_IF_FALSE(!ret); 979 980 ret = sys_munmap(ptr, size); 981 FAIL_TEST_IF_FALSE(!ret); 982 983 REPORT_TEST_PASS(); 984 } 985 986 static void test_munmap_start_freed(bool seal) 987 { 988 void *ptr; 989 unsigned long page_size = getpagesize(); 990 unsigned long size = 4 * page_size; 991 int ret; 992 int prot; 993 994 setup_single_address(size, &ptr); 995 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 996 997 /* unmap the first page. */ 998 ret = sys_munmap(ptr, page_size); 999 FAIL_TEST_IF_FALSE(!ret); 1000 1001 /* seal the last 3 pages. */ 1002 if (seal) { 1003 ret = sys_mseal(ptr + page_size, 3 * page_size); 1004 FAIL_TEST_IF_FALSE(!ret); 1005 } 1006 1007 /* unmap from the first page. */ 1008 ret = sys_munmap(ptr, size); 1009 if (seal) { 1010 FAIL_TEST_IF_FALSE(ret < 0); 1011 1012 size = get_vma_size(ptr + page_size, &prot); 1013 FAIL_TEST_IF_FALSE(size == page_size * 3); 1014 } else { 1015 /* note: this will be OK, even the first page is */ 1016 /* already unmapped. */ 1017 FAIL_TEST_IF_FALSE(!ret); 1018 1019 size = get_vma_size(ptr + page_size, &prot); 1020 FAIL_TEST_IF_FALSE(size == 0); 1021 } 1022 1023 REPORT_TEST_PASS(); 1024 } 1025 1026 static void test_munmap_end_freed(bool seal) 1027 { 1028 void *ptr; 1029 unsigned long page_size = getpagesize(); 1030 unsigned long size = 4 * page_size; 1031 int ret; 1032 1033 setup_single_address(size, &ptr); 1034 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1035 1036 /* unmap last page. */ 1037 ret = sys_munmap(ptr + page_size * 3, page_size); 1038 FAIL_TEST_IF_FALSE(!ret); 1039 1040 /* seal the first 3 pages. */ 1041 if (seal) { 1042 ret = sys_mseal(ptr, 3 * page_size); 1043 FAIL_TEST_IF_FALSE(!ret); 1044 } 1045 1046 /* unmap all pages. */ 1047 ret = sys_munmap(ptr, size); 1048 if (seal) 1049 FAIL_TEST_IF_FALSE(ret < 0); 1050 else 1051 FAIL_TEST_IF_FALSE(!ret); 1052 1053 REPORT_TEST_PASS(); 1054 } 1055 1056 static void test_munmap_middle_freed(bool seal) 1057 { 1058 void *ptr; 1059 unsigned long page_size = getpagesize(); 1060 unsigned long size = 4 * page_size; 1061 int ret; 1062 int prot; 1063 1064 setup_single_address(size, &ptr); 1065 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1066 1067 /* unmap 2 pages in the middle. */ 1068 ret = sys_munmap(ptr + page_size, page_size * 2); 1069 FAIL_TEST_IF_FALSE(!ret); 1070 1071 /* seal the first page. */ 1072 if (seal) { 1073 ret = sys_mseal(ptr, page_size); 1074 FAIL_TEST_IF_FALSE(!ret); 1075 } 1076 1077 /* munmap all 4 pages. */ 1078 ret = sys_munmap(ptr, size); 1079 if (seal) { 1080 FAIL_TEST_IF_FALSE(ret < 0); 1081 1082 size = get_vma_size(ptr, &prot); 1083 FAIL_TEST_IF_FALSE(size == page_size); 1084 1085 size = get_vma_size(ptr + page_size * 3, &prot); 1086 FAIL_TEST_IF_FALSE(size == page_size); 1087 } else { 1088 FAIL_TEST_IF_FALSE(!ret); 1089 1090 size = get_vma_size(ptr, &prot); 1091 FAIL_TEST_IF_FALSE(size == 0); 1092 1093 size = get_vma_size(ptr + page_size * 3, &prot); 1094 FAIL_TEST_IF_FALSE(size == 0); 1095 } 1096 1097 REPORT_TEST_PASS(); 1098 } 1099 1100 static void test_seal_mremap_shrink(bool seal) 1101 { 1102 void *ptr; 1103 unsigned long page_size = getpagesize(); 1104 unsigned long size = 4 * page_size; 1105 int ret; 1106 void *ret2; 1107 1108 setup_single_address(size, &ptr); 1109 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1110 1111 if (seal) { 1112 ret = sys_mseal(ptr, size); 1113 FAIL_TEST_IF_FALSE(!ret); 1114 } 1115 1116 /* shrink from 4 pages to 2 pages. */ 1117 ret2 = sys_mremap(ptr, size, 2 * page_size, 0, 0); 1118 if (seal) { 1119 FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED); 1120 FAIL_TEST_IF_FALSE(errno == EPERM); 1121 } else { 1122 FAIL_TEST_IF_FALSE(ret2 != (void *) MAP_FAILED); 1123 1124 } 1125 1126 REPORT_TEST_PASS(); 1127 } 1128 1129 static void test_seal_mremap_expand(bool seal) 1130 { 1131 void *ptr; 1132 unsigned long page_size = getpagesize(); 1133 unsigned long size = 4 * page_size; 1134 int ret; 1135 void *ret2; 1136 1137 setup_single_address(size, &ptr); 1138 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1139 /* ummap last 2 pages. */ 1140 ret = sys_munmap(ptr + 2 * page_size, 2 * page_size); 1141 FAIL_TEST_IF_FALSE(!ret); 1142 1143 if (seal) { 1144 ret = sys_mseal(ptr, 2 * page_size); 1145 FAIL_TEST_IF_FALSE(!ret); 1146 } 1147 1148 /* expand from 2 page to 4 pages. */ 1149 ret2 = sys_mremap(ptr, 2 * page_size, 4 * page_size, 0, 0); 1150 if (seal) { 1151 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1152 FAIL_TEST_IF_FALSE(errno == EPERM); 1153 } else { 1154 FAIL_TEST_IF_FALSE(ret2 == ptr); 1155 1156 } 1157 1158 REPORT_TEST_PASS(); 1159 } 1160 1161 static void test_seal_mremap_move(bool seal) 1162 { 1163 void *ptr, *newPtr; 1164 unsigned long page_size = getpagesize(); 1165 unsigned long size = page_size; 1166 int ret; 1167 void *ret2; 1168 1169 setup_single_address(size, &ptr); 1170 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1171 setup_single_address(size, &newPtr); 1172 FAIL_TEST_IF_FALSE(newPtr != (void *)-1); 1173 ret = clean_single_address(newPtr, size); 1174 FAIL_TEST_IF_FALSE(!ret); 1175 1176 if (seal) { 1177 ret = sys_mseal(ptr, size); 1178 FAIL_TEST_IF_FALSE(!ret); 1179 } 1180 1181 /* move from ptr to fixed address. */ 1182 ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, newPtr); 1183 if (seal) { 1184 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1185 FAIL_TEST_IF_FALSE(errno == EPERM); 1186 } else { 1187 FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED); 1188 1189 } 1190 1191 REPORT_TEST_PASS(); 1192 } 1193 1194 static void test_seal_mmap_overwrite_prot(bool seal) 1195 { 1196 void *ptr; 1197 unsigned long page_size = getpagesize(); 1198 unsigned long size = page_size; 1199 int ret; 1200 void *ret2; 1201 1202 setup_single_address(size, &ptr); 1203 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1204 1205 if (seal) { 1206 ret = sys_mseal(ptr, size); 1207 FAIL_TEST_IF_FALSE(!ret); 1208 } 1209 1210 /* use mmap to change protection. */ 1211 ret2 = mmap(ptr, size, PROT_NONE, 1212 MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); 1213 if (seal) { 1214 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1215 FAIL_TEST_IF_FALSE(errno == EPERM); 1216 } else 1217 FAIL_TEST_IF_FALSE(ret2 == ptr); 1218 1219 REPORT_TEST_PASS(); 1220 } 1221 1222 static void test_seal_mmap_expand(bool seal) 1223 { 1224 void *ptr; 1225 unsigned long page_size = getpagesize(); 1226 unsigned long size = 12 * page_size; 1227 int ret; 1228 void *ret2; 1229 1230 setup_single_address(size, &ptr); 1231 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1232 /* ummap last 4 pages. */ 1233 ret = sys_munmap(ptr + 8 * page_size, 4 * page_size); 1234 FAIL_TEST_IF_FALSE(!ret); 1235 1236 if (seal) { 1237 ret = sys_mseal(ptr, 8 * page_size); 1238 FAIL_TEST_IF_FALSE(!ret); 1239 } 1240 1241 /* use mmap to expand. */ 1242 ret2 = mmap(ptr, size, PROT_READ, 1243 MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); 1244 if (seal) { 1245 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1246 FAIL_TEST_IF_FALSE(errno == EPERM); 1247 } else 1248 FAIL_TEST_IF_FALSE(ret2 == ptr); 1249 1250 REPORT_TEST_PASS(); 1251 } 1252 1253 static void test_seal_mmap_shrink(bool seal) 1254 { 1255 void *ptr; 1256 unsigned long page_size = getpagesize(); 1257 unsigned long size = 12 * page_size; 1258 int ret; 1259 void *ret2; 1260 1261 setup_single_address(size, &ptr); 1262 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1263 1264 if (seal) { 1265 ret = sys_mseal(ptr, size); 1266 FAIL_TEST_IF_FALSE(!ret); 1267 } 1268 1269 /* use mmap to shrink. */ 1270 ret2 = mmap(ptr, 8 * page_size, PROT_READ, 1271 MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); 1272 if (seal) { 1273 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1274 FAIL_TEST_IF_FALSE(errno == EPERM); 1275 } else 1276 FAIL_TEST_IF_FALSE(ret2 == ptr); 1277 1278 REPORT_TEST_PASS(); 1279 } 1280 1281 static void test_seal_mremap_shrink_fixed(bool seal) 1282 { 1283 void *ptr; 1284 void *newAddr; 1285 unsigned long page_size = getpagesize(); 1286 unsigned long size = 4 * page_size; 1287 int ret; 1288 void *ret2; 1289 1290 setup_single_address(size, &ptr); 1291 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1292 setup_single_address(size, &newAddr); 1293 FAIL_TEST_IF_FALSE(newAddr != (void *)-1); 1294 1295 if (seal) { 1296 ret = sys_mseal(ptr, size); 1297 FAIL_TEST_IF_FALSE(!ret); 1298 } 1299 1300 /* mremap to move and shrink to fixed address */ 1301 ret2 = sys_mremap(ptr, size, 2 * page_size, MREMAP_MAYMOVE | MREMAP_FIXED, 1302 newAddr); 1303 if (seal) { 1304 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1305 FAIL_TEST_IF_FALSE(errno == EPERM); 1306 } else 1307 FAIL_TEST_IF_FALSE(ret2 == newAddr); 1308 1309 REPORT_TEST_PASS(); 1310 } 1311 1312 static void test_seal_mremap_expand_fixed(bool seal) 1313 { 1314 void *ptr; 1315 void *newAddr; 1316 unsigned long page_size = getpagesize(); 1317 unsigned long size = 4 * page_size; 1318 int ret; 1319 void *ret2; 1320 1321 setup_single_address(page_size, &ptr); 1322 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1323 setup_single_address(size, &newAddr); 1324 FAIL_TEST_IF_FALSE(newAddr != (void *)-1); 1325 1326 if (seal) { 1327 ret = sys_mseal(newAddr, size); 1328 FAIL_TEST_IF_FALSE(!ret); 1329 } 1330 1331 /* mremap to move and expand to fixed address */ 1332 ret2 = sys_mremap(ptr, page_size, size, MREMAP_MAYMOVE | MREMAP_FIXED, 1333 newAddr); 1334 if (seal) { 1335 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1336 FAIL_TEST_IF_FALSE(errno == EPERM); 1337 } else 1338 FAIL_TEST_IF_FALSE(ret2 == newAddr); 1339 1340 REPORT_TEST_PASS(); 1341 } 1342 1343 static void test_seal_mremap_move_fixed(bool seal) 1344 { 1345 void *ptr; 1346 void *newAddr; 1347 unsigned long page_size = getpagesize(); 1348 unsigned long size = 4 * page_size; 1349 int ret; 1350 void *ret2; 1351 1352 setup_single_address(size, &ptr); 1353 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1354 setup_single_address(size, &newAddr); 1355 FAIL_TEST_IF_FALSE(newAddr != (void *)-1); 1356 1357 if (seal) { 1358 ret = sys_mseal(newAddr, size); 1359 FAIL_TEST_IF_FALSE(!ret); 1360 } 1361 1362 /* mremap to move to fixed address */ 1363 ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, newAddr); 1364 if (seal) { 1365 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1366 FAIL_TEST_IF_FALSE(errno == EPERM); 1367 } else 1368 FAIL_TEST_IF_FALSE(ret2 == newAddr); 1369 1370 REPORT_TEST_PASS(); 1371 } 1372 1373 static void test_seal_mremap_move_fixed_zero(bool seal) 1374 { 1375 void *ptr; 1376 unsigned long page_size = getpagesize(); 1377 unsigned long size = 4 * page_size; 1378 int ret; 1379 void *ret2; 1380 1381 setup_single_address(size, &ptr); 1382 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1383 1384 if (seal) { 1385 ret = sys_mseal(ptr, size); 1386 FAIL_TEST_IF_FALSE(!ret); 1387 } 1388 1389 /* 1390 * MREMAP_FIXED can move the mapping to zero address 1391 */ 1392 ret2 = sys_mremap(ptr, size, 2 * page_size, MREMAP_MAYMOVE | MREMAP_FIXED, 1393 0); 1394 if (seal) { 1395 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1396 FAIL_TEST_IF_FALSE(errno == EPERM); 1397 } else { 1398 FAIL_TEST_IF_FALSE(ret2 == 0); 1399 } 1400 1401 REPORT_TEST_PASS(); 1402 } 1403 1404 static void test_seal_mremap_move_dontunmap(bool seal) 1405 { 1406 void *ptr; 1407 unsigned long page_size = getpagesize(); 1408 unsigned long size = 4 * page_size; 1409 int ret; 1410 void *ret2; 1411 1412 setup_single_address(size, &ptr); 1413 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1414 1415 if (seal) { 1416 ret = sys_mseal(ptr, size); 1417 FAIL_TEST_IF_FALSE(!ret); 1418 } 1419 1420 /* mremap to move, and don't unmap src addr. */ 1421 ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_DONTUNMAP, 0); 1422 if (seal) { 1423 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1424 FAIL_TEST_IF_FALSE(errno == EPERM); 1425 } else { 1426 /* kernel will allocate a new address */ 1427 FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED); 1428 } 1429 1430 REPORT_TEST_PASS(); 1431 } 1432 1433 static void test_seal_mremap_move_dontunmap_anyaddr(bool seal) 1434 { 1435 void *ptr, *ptr2; 1436 unsigned long page_size = getpagesize(); 1437 unsigned long size = 4 * page_size; 1438 int ret; 1439 void *ret2; 1440 1441 setup_single_address(size, &ptr); 1442 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1443 1444 if (seal) { 1445 ret = sys_mseal(ptr, size); 1446 FAIL_TEST_IF_FALSE(!ret); 1447 } 1448 1449 /* 1450 * The new address is any address that not allocated. 1451 * use allocate/free to similate that. 1452 */ 1453 setup_single_address(size, &ptr2); 1454 FAIL_TEST_IF_FALSE(ptr2 != (void *)-1); 1455 ret = sys_munmap(ptr2, size); 1456 FAIL_TEST_IF_FALSE(!ret); 1457 1458 /* 1459 * remap to any address. 1460 */ 1461 ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_DONTUNMAP, 1462 (void *) ptr2); 1463 if (seal) { 1464 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); 1465 FAIL_TEST_IF_FALSE(errno == EPERM); 1466 } else { 1467 /* remap success and return ptr2 */ 1468 FAIL_TEST_IF_FALSE(ret2 == ptr2); 1469 } 1470 1471 REPORT_TEST_PASS(); 1472 } 1473 1474 static void test_seal_merge_and_split(void) 1475 { 1476 void *ptr; 1477 unsigned long page_size = getpagesize(); 1478 unsigned long size; 1479 int ret; 1480 int prot; 1481 1482 /* (24 RO) */ 1483 setup_single_address(24 * page_size, &ptr); 1484 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1485 1486 /* use mprotect(NONE) to set out boundary */ 1487 /* (1 NONE) (22 RO) (1 NONE) */ 1488 ret = sys_mprotect(ptr, page_size, PROT_NONE); 1489 FAIL_TEST_IF_FALSE(!ret); 1490 ret = sys_mprotect(ptr + 23 * page_size, page_size, PROT_NONE); 1491 FAIL_TEST_IF_FALSE(!ret); 1492 size = get_vma_size(ptr + page_size, &prot); 1493 FAIL_TEST_IF_FALSE(size == 22 * page_size); 1494 FAIL_TEST_IF_FALSE(prot == 4); 1495 1496 /* use mseal to split from beginning */ 1497 /* (1 NONE) (1 RO_SEAL) (21 RO) (1 NONE) */ 1498 ret = sys_mseal(ptr + page_size, page_size); 1499 FAIL_TEST_IF_FALSE(!ret); 1500 size = get_vma_size(ptr + page_size, &prot); 1501 FAIL_TEST_IF_FALSE(size == page_size); 1502 FAIL_TEST_IF_FALSE(prot == 0x4); 1503 size = get_vma_size(ptr + 2 * page_size, &prot); 1504 FAIL_TEST_IF_FALSE(size == 21 * page_size); 1505 FAIL_TEST_IF_FALSE(prot == 0x4); 1506 1507 /* use mseal to split from the end. */ 1508 /* (1 NONE) (1 RO_SEAL) (20 RO) (1 RO_SEAL) (1 NONE) */ 1509 ret = sys_mseal(ptr + 22 * page_size, page_size); 1510 FAIL_TEST_IF_FALSE(!ret); 1511 size = get_vma_size(ptr + 22 * page_size, &prot); 1512 FAIL_TEST_IF_FALSE(size == page_size); 1513 FAIL_TEST_IF_FALSE(prot == 0x4); 1514 size = get_vma_size(ptr + 2 * page_size, &prot); 1515 FAIL_TEST_IF_FALSE(size == 20 * page_size); 1516 FAIL_TEST_IF_FALSE(prot == 0x4); 1517 1518 /* merge with prev. */ 1519 /* (1 NONE) (2 RO_SEAL) (19 RO) (1 RO_SEAL) (1 NONE) */ 1520 ret = sys_mseal(ptr + 2 * page_size, page_size); 1521 FAIL_TEST_IF_FALSE(!ret); 1522 size = get_vma_size(ptr + page_size, &prot); 1523 FAIL_TEST_IF_FALSE(size == 2 * page_size); 1524 FAIL_TEST_IF_FALSE(prot == 0x4); 1525 1526 /* merge with after. */ 1527 /* (1 NONE) (2 RO_SEAL) (18 RO) (2 RO_SEALS) (1 NONE) */ 1528 ret = sys_mseal(ptr + 21 * page_size, page_size); 1529 FAIL_TEST_IF_FALSE(!ret); 1530 size = get_vma_size(ptr + 21 * page_size, &prot); 1531 FAIL_TEST_IF_FALSE(size == 2 * page_size); 1532 FAIL_TEST_IF_FALSE(prot == 0x4); 1533 1534 /* split and merge from prev */ 1535 /* (1 NONE) (3 RO_SEAL) (17 RO) (2 RO_SEALS) (1 NONE) */ 1536 ret = sys_mseal(ptr + 2 * page_size, 2 * page_size); 1537 FAIL_TEST_IF_FALSE(!ret); 1538 size = get_vma_size(ptr + 1 * page_size, &prot); 1539 FAIL_TEST_IF_FALSE(size == 3 * page_size); 1540 FAIL_TEST_IF_FALSE(prot == 0x4); 1541 ret = sys_munmap(ptr + page_size, page_size); 1542 FAIL_TEST_IF_FALSE(ret < 0); 1543 ret = sys_mprotect(ptr + 2 * page_size, page_size, PROT_NONE); 1544 FAIL_TEST_IF_FALSE(ret < 0); 1545 1546 /* split and merge from next */ 1547 /* (1 NONE) (3 RO_SEAL) (16 RO) (3 RO_SEALS) (1 NONE) */ 1548 ret = sys_mseal(ptr + 20 * page_size, 2 * page_size); 1549 FAIL_TEST_IF_FALSE(!ret); 1550 FAIL_TEST_IF_FALSE(prot == 0x4); 1551 size = get_vma_size(ptr + 20 * page_size, &prot); 1552 FAIL_TEST_IF_FALSE(size == 3 * page_size); 1553 FAIL_TEST_IF_FALSE(prot == 0x4); 1554 1555 /* merge from middle of prev and middle of next. */ 1556 /* (1 NONE) (22 RO_SEAL) (1 NONE) */ 1557 ret = sys_mseal(ptr + 2 * page_size, 20 * page_size); 1558 FAIL_TEST_IF_FALSE(!ret); 1559 size = get_vma_size(ptr + page_size, &prot); 1560 FAIL_TEST_IF_FALSE(size == 22 * page_size); 1561 FAIL_TEST_IF_FALSE(prot == 0x4); 1562 1563 REPORT_TEST_PASS(); 1564 } 1565 1566 static void test_seal_discard_ro_anon_on_rw(bool seal) 1567 { 1568 void *ptr; 1569 unsigned long page_size = getpagesize(); 1570 unsigned long size = 4 * page_size; 1571 int ret; 1572 1573 setup_single_address_rw(size, &ptr); 1574 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1575 1576 if (seal) { 1577 ret = sys_mseal(ptr, size); 1578 FAIL_TEST_IF_FALSE(!ret); 1579 } 1580 1581 /* sealing doesn't take effect on RW memory. */ 1582 ret = sys_madvise(ptr, size, MADV_DONTNEED); 1583 FAIL_TEST_IF_FALSE(!ret); 1584 1585 /* base seal still apply. */ 1586 ret = sys_munmap(ptr, size); 1587 if (seal) 1588 FAIL_TEST_IF_FALSE(ret < 0); 1589 else 1590 FAIL_TEST_IF_FALSE(!ret); 1591 1592 REPORT_TEST_PASS(); 1593 } 1594 1595 static void test_seal_discard_ro_anon_on_pkey(bool seal) 1596 { 1597 void *ptr; 1598 unsigned long page_size = getpagesize(); 1599 unsigned long size = 4 * page_size; 1600 int ret; 1601 int pkey; 1602 1603 SKIP_TEST_IF_FALSE(pkey_supported()); 1604 1605 setup_single_address_rw(size, &ptr); 1606 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1607 1608 pkey = sys_pkey_alloc(0, 0); 1609 FAIL_TEST_IF_FALSE(pkey > 0); 1610 1611 ret = sys_mprotect_pkey((void *)ptr, size, PROT_READ | PROT_WRITE, pkey); 1612 FAIL_TEST_IF_FALSE(!ret); 1613 1614 if (seal) { 1615 ret = sys_mseal(ptr, size); 1616 FAIL_TEST_IF_FALSE(!ret); 1617 } 1618 1619 /* sealing doesn't take effect if PKRU allow write. */ 1620 set_pkey(pkey, 0); 1621 ret = sys_madvise(ptr, size, MADV_DONTNEED); 1622 FAIL_TEST_IF_FALSE(!ret); 1623 1624 /* sealing will take effect if PKRU deny write. */ 1625 set_pkey(pkey, PKEY_DISABLE_WRITE); 1626 ret = sys_madvise(ptr, size, MADV_DONTNEED); 1627 if (seal) 1628 FAIL_TEST_IF_FALSE(ret < 0); 1629 else 1630 FAIL_TEST_IF_FALSE(!ret); 1631 1632 /* base seal still apply. */ 1633 ret = sys_munmap(ptr, size); 1634 if (seal) 1635 FAIL_TEST_IF_FALSE(ret < 0); 1636 else 1637 FAIL_TEST_IF_FALSE(!ret); 1638 1639 REPORT_TEST_PASS(); 1640 } 1641 1642 static void test_seal_discard_ro_anon_on_filebacked(bool seal) 1643 { 1644 void *ptr; 1645 unsigned long page_size = getpagesize(); 1646 unsigned long size = 4 * page_size; 1647 int ret; 1648 int fd; 1649 unsigned long mapflags = MAP_PRIVATE; 1650 1651 fd = memfd_create("test", 0); 1652 FAIL_TEST_IF_FALSE(fd > 0); 1653 1654 ret = fallocate(fd, 0, 0, size); 1655 FAIL_TEST_IF_FALSE(!ret); 1656 1657 ptr = mmap(NULL, size, PROT_READ, mapflags, fd, 0); 1658 FAIL_TEST_IF_FALSE(ptr != MAP_FAILED); 1659 1660 if (seal) { 1661 ret = sys_mseal(ptr, size); 1662 FAIL_TEST_IF_FALSE(!ret); 1663 } 1664 1665 /* sealing doesn't apply for file backed mapping. */ 1666 ret = sys_madvise(ptr, size, MADV_DONTNEED); 1667 FAIL_TEST_IF_FALSE(!ret); 1668 1669 ret = sys_munmap(ptr, size); 1670 if (seal) 1671 FAIL_TEST_IF_FALSE(ret < 0); 1672 else 1673 FAIL_TEST_IF_FALSE(!ret); 1674 close(fd); 1675 1676 REPORT_TEST_PASS(); 1677 } 1678 1679 static void test_seal_discard_ro_anon_on_shared(bool seal) 1680 { 1681 void *ptr; 1682 unsigned long page_size = getpagesize(); 1683 unsigned long size = 4 * page_size; 1684 int ret; 1685 unsigned long mapflags = MAP_ANONYMOUS | MAP_SHARED; 1686 1687 ptr = mmap(NULL, size, PROT_READ, mapflags, -1, 0); 1688 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1689 1690 if (seal) { 1691 ret = sys_mseal(ptr, size); 1692 FAIL_TEST_IF_FALSE(!ret); 1693 } 1694 1695 /* sealing doesn't apply for shared mapping. */ 1696 ret = sys_madvise(ptr, size, MADV_DONTNEED); 1697 FAIL_TEST_IF_FALSE(!ret); 1698 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(bool seal) 1709 { 1710 void *ptr; 1711 unsigned long page_size = getpagesize(); 1712 unsigned long size = 4 * page_size; 1713 int ret; 1714 1715 setup_single_address(size, &ptr); 1716 FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1717 1718 if (seal) { 1719 ret = seal_single_address(ptr, size); 1720 FAIL_TEST_IF_FALSE(!ret); 1721 } 1722 1723 ret = sys_madvise(ptr, size, MADV_DONTNEED); 1724 if (seal) 1725 FAIL_TEST_IF_FALSE(ret < 0); 1726 else 1727 FAIL_TEST_IF_FALSE(!ret); 1728 1729 ret = sys_munmap(ptr, size); 1730 if (seal) 1731 FAIL_TEST_IF_FALSE(ret < 0); 1732 else 1733 FAIL_TEST_IF_FALSE(!ret); 1734 1735 REPORT_TEST_PASS(); 1736 } 1737 1738 int main(int argc, char **argv) 1739 { 1740 bool test_seal = seal_support(); 1741 1742 ksft_print_header(); 1743 1744 if (!test_seal) 1745 ksft_exit_skip("sealing not supported, check CONFIG_64BIT\n"); 1746 1747 if (!pkey_supported()) 1748 ksft_print_msg("PKEY not supported\n"); 1749 1750 ksft_set_plan(80); 1751 1752 test_seal_addseal(); 1753 test_seal_unmapped_start(); 1754 test_seal_unmapped_middle(); 1755 test_seal_unmapped_end(); 1756 test_seal_multiple_vmas(); 1757 test_seal_split_start(); 1758 test_seal_split_end(); 1759 test_seal_invalid_input(); 1760 test_seal_zero_length(); 1761 test_seal_twice(); 1762 1763 test_seal_mprotect(false); 1764 test_seal_mprotect(true); 1765 1766 test_seal_start_mprotect(false); 1767 test_seal_start_mprotect(true); 1768 1769 test_seal_end_mprotect(false); 1770 test_seal_end_mprotect(true); 1771 1772 test_seal_mprotect_unalign_len(false); 1773 test_seal_mprotect_unalign_len(true); 1774 1775 test_seal_mprotect_unalign_len_variant_2(false); 1776 test_seal_mprotect_unalign_len_variant_2(true); 1777 1778 test_seal_mprotect_two_vma(false); 1779 test_seal_mprotect_two_vma(true); 1780 1781 test_seal_mprotect_two_vma_with_split(false); 1782 test_seal_mprotect_two_vma_with_split(true); 1783 1784 test_seal_mprotect_partial_mprotect(false); 1785 test_seal_mprotect_partial_mprotect(true); 1786 1787 test_seal_mprotect_two_vma_with_gap(false); 1788 test_seal_mprotect_two_vma_with_gap(true); 1789 1790 test_seal_mprotect_merge(false); 1791 test_seal_mprotect_merge(true); 1792 1793 test_seal_mprotect_split(false); 1794 test_seal_mprotect_split(true); 1795 1796 test_seal_munmap(false); 1797 test_seal_munmap(true); 1798 test_seal_munmap_two_vma(false); 1799 test_seal_munmap_two_vma(true); 1800 test_seal_munmap_vma_with_gap(false); 1801 test_seal_munmap_vma_with_gap(true); 1802 1803 test_munmap_start_freed(false); 1804 test_munmap_start_freed(true); 1805 test_munmap_middle_freed(false); 1806 test_munmap_middle_freed(true); 1807 test_munmap_end_freed(false); 1808 test_munmap_end_freed(true); 1809 1810 test_seal_mremap_shrink(false); 1811 test_seal_mremap_shrink(true); 1812 test_seal_mremap_expand(false); 1813 test_seal_mremap_expand(true); 1814 test_seal_mremap_move(false); 1815 test_seal_mremap_move(true); 1816 1817 test_seal_mremap_shrink_fixed(false); 1818 test_seal_mremap_shrink_fixed(true); 1819 test_seal_mremap_expand_fixed(false); 1820 test_seal_mremap_expand_fixed(true); 1821 test_seal_mremap_move_fixed(false); 1822 test_seal_mremap_move_fixed(true); 1823 test_seal_mremap_move_dontunmap(false); 1824 test_seal_mremap_move_dontunmap(true); 1825 test_seal_mremap_move_fixed_zero(false); 1826 test_seal_mremap_move_fixed_zero(true); 1827 test_seal_mremap_move_dontunmap_anyaddr(false); 1828 test_seal_mremap_move_dontunmap_anyaddr(true); 1829 test_seal_discard_ro_anon(false); 1830 test_seal_discard_ro_anon(true); 1831 test_seal_discard_ro_anon_on_rw(false); 1832 test_seal_discard_ro_anon_on_rw(true); 1833 test_seal_discard_ro_anon_on_shared(false); 1834 test_seal_discard_ro_anon_on_shared(true); 1835 test_seal_discard_ro_anon_on_filebacked(false); 1836 test_seal_discard_ro_anon_on_filebacked(true); 1837 test_seal_mmap_overwrite_prot(false); 1838 test_seal_mmap_overwrite_prot(true); 1839 test_seal_mmap_expand(false); 1840 test_seal_mmap_expand(true); 1841 test_seal_mmap_shrink(false); 1842 test_seal_mmap_shrink(true); 1843 1844 test_seal_merge_and_split(); 1845 test_seal_zero_address(); 1846 1847 test_seal_discard_ro_anon_on_pkey(false); 1848 test_seal_discard_ro_anon_on_pkey(true); 1849 1850 ksft_finished(); 1851 } 1852
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.