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