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