1 // SPDX-License-Identifier: GPL-2.0 2 #define _GNU_SOURCE 3 #define __EXPORTED_HEADERS__ 4 5 #include <errno.h> 6 #include <inttypes.h> 7 #include <limits.h> 8 #include <linux/falloc.h> 9 #include <fcntl.h> 10 #include <linux/memfd.h> 11 #include <sched.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <signal.h> 15 #include <string.h> 16 #include <sys/mman.h> 17 #include <sys/stat.h> 18 #include <sys/syscall.h> 19 #include <sys/wait.h> 20 #include <unistd.h> 21 #include <ctype.h> 22 23 #include "common.h" 24 25 #define MEMFD_STR "memfd:" 26 #define MEMFD_HUGE_STR "memfd-hugetlb:" 27 #define SHARED_FT_STR "(shared file-table)" 28 29 #define MFD_DEF_SIZE 8192 30 #define STACK_SIZE 65536 31 32 #define F_SEAL_EXEC 0x0020 33 34 #define F_WX_SEALS (F_SEAL_SHRINK | \ 35 F_SEAL_GROW | \ 36 F_SEAL_WRITE | \ 37 F_SEAL_FUTURE_WRITE | \ 38 F_SEAL_EXEC) 39 40 #define MFD_NOEXEC_SEAL 0x0008U 41 42 /* 43 * Default is not to test hugetlbfs 44 */ 45 static size_t mfd_def_size = MFD_DEF_SIZE; 46 static const char *memfd_str = MEMFD_STR; 47 static int newpid_thread_fn2(void *arg); 48 static void join_newpid_thread(pid_t pid); 49 50 static ssize_t fd2name(int fd, char *buf, size_t bufsize) 51 { 52 char buf1[PATH_MAX]; 53 int size; 54 ssize_t nbytes; 55 56 size = snprintf(buf1, PATH_MAX, "/proc/self/fd/%d", fd); 57 if (size < 0) { 58 printf("snprintf(%d) failed on %m\n", fd); 59 abort(); 60 } 61 62 /* 63 * reserver one byte for string termination. 64 */ 65 nbytes = readlink(buf1, buf, bufsize-1); 66 if (nbytes == -1) { 67 printf("readlink(%s) failed %m\n", buf1); 68 abort(); 69 } 70 buf[nbytes] = '\0'; 71 return nbytes; 72 } 73 74 static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags) 75 { 76 int r, fd; 77 78 fd = sys_memfd_create(name, flags); 79 if (fd < 0) { 80 printf("memfd_create(\"%s\", %u) failed: %m\n", 81 name, flags); 82 abort(); 83 } 84 85 r = ftruncate(fd, sz); 86 if (r < 0) { 87 printf("ftruncate(%llu) failed: %m\n", (unsigned long long)sz); 88 abort(); 89 } 90 91 return fd; 92 } 93 94 static void sysctl_assert_write(const char *val) 95 { 96 int fd = open("/proc/sys/vm/memfd_noexec", O_WRONLY | O_CLOEXEC); 97 98 if (fd < 0) { 99 printf("open sysctl failed: %m\n"); 100 abort(); 101 } 102 103 if (write(fd, val, strlen(val)) < 0) { 104 printf("write sysctl %s failed: %m\n", val); 105 abort(); 106 } 107 } 108 109 static void sysctl_fail_write(const char *val) 110 { 111 int fd = open("/proc/sys/vm/memfd_noexec", O_WRONLY | O_CLOEXEC); 112 113 if (fd < 0) { 114 printf("open sysctl failed: %m\n"); 115 abort(); 116 } 117 118 if (write(fd, val, strlen(val)) >= 0) { 119 printf("write sysctl %s succeeded, but failure expected\n", 120 val); 121 abort(); 122 } 123 } 124 125 static void sysctl_assert_equal(const char *val) 126 { 127 char *p, buf[128] = {}; 128 int fd = open("/proc/sys/vm/memfd_noexec", O_RDONLY | O_CLOEXEC); 129 130 if (fd < 0) { 131 printf("open sysctl failed: %m\n"); 132 abort(); 133 } 134 135 if (read(fd, buf, sizeof(buf)) < 0) { 136 printf("read sysctl failed: %m\n"); 137 abort(); 138 } 139 140 /* Strip trailing whitespace. */ 141 p = buf; 142 while (!isspace(*p)) 143 p++; 144 *p = '\0'; 145 146 if (strcmp(buf, val) != 0) { 147 printf("unexpected sysctl value: expected %s, got %s\n", val, buf); 148 abort(); 149 } 150 } 151 152 static int mfd_assert_reopen_fd(int fd_in) 153 { 154 int fd; 155 char path[100]; 156 157 sprintf(path, "/proc/self/fd/%d", fd_in); 158 159 fd = open(path, O_RDWR); 160 if (fd < 0) { 161 printf("re-open of existing fd %d failed\n", fd_in); 162 abort(); 163 } 164 165 return fd; 166 } 167 168 static void mfd_fail_new(const char *name, unsigned int flags) 169 { 170 int r; 171 172 r = sys_memfd_create(name, flags); 173 if (r >= 0) { 174 printf("memfd_create(\"%s\", %u) succeeded, but failure expected\n", 175 name, flags); 176 close(r); 177 abort(); 178 } 179 } 180 181 static unsigned int mfd_assert_get_seals(int fd) 182 { 183 int r; 184 185 r = fcntl(fd, F_GET_SEALS); 186 if (r < 0) { 187 printf("GET_SEALS(%d) failed: %m\n", fd); 188 abort(); 189 } 190 191 return (unsigned int)r; 192 } 193 194 static void mfd_assert_has_seals(int fd, unsigned int seals) 195 { 196 char buf[PATH_MAX]; 197 int nbytes; 198 unsigned int s; 199 fd2name(fd, buf, PATH_MAX); 200 201 s = mfd_assert_get_seals(fd); 202 if (s != seals) { 203 printf("%u != %u = GET_SEALS(%s)\n", seals, s, buf); 204 abort(); 205 } 206 } 207 208 static void mfd_assert_add_seals(int fd, unsigned int seals) 209 { 210 int r; 211 unsigned int s; 212 213 s = mfd_assert_get_seals(fd); 214 r = fcntl(fd, F_ADD_SEALS, seals); 215 if (r < 0) { 216 printf("ADD_SEALS(%d, %u -> %u) failed: %m\n", fd, s, seals); 217 abort(); 218 } 219 } 220 221 static void mfd_fail_add_seals(int fd, unsigned int seals) 222 { 223 int r; 224 unsigned int s; 225 226 r = fcntl(fd, F_GET_SEALS); 227 if (r < 0) 228 s = 0; 229 else 230 s = (unsigned int)r; 231 232 r = fcntl(fd, F_ADD_SEALS, seals); 233 if (r >= 0) { 234 printf("ADD_SEALS(%d, %u -> %u) didn't fail as expected\n", 235 fd, s, seals); 236 abort(); 237 } 238 } 239 240 static void mfd_assert_size(int fd, size_t size) 241 { 242 struct stat st; 243 int r; 244 245 r = fstat(fd, &st); 246 if (r < 0) { 247 printf("fstat(%d) failed: %m\n", fd); 248 abort(); 249 } else if (st.st_size != size) { 250 printf("wrong file size %lld, but expected %lld\n", 251 (long long)st.st_size, (long long)size); 252 abort(); 253 } 254 } 255 256 static int mfd_assert_dup(int fd) 257 { 258 int r; 259 260 r = dup(fd); 261 if (r < 0) { 262 printf("dup(%d) failed: %m\n", fd); 263 abort(); 264 } 265 266 return r; 267 } 268 269 static void *mfd_assert_mmap_shared(int fd) 270 { 271 void *p; 272 273 p = mmap(NULL, 274 mfd_def_size, 275 PROT_READ | PROT_WRITE, 276 MAP_SHARED, 277 fd, 278 0); 279 if (p == MAP_FAILED) { 280 printf("mmap() failed: %m\n"); 281 abort(); 282 } 283 284 return p; 285 } 286 287 static void *mfd_assert_mmap_private(int fd) 288 { 289 void *p; 290 291 p = mmap(NULL, 292 mfd_def_size, 293 PROT_READ, 294 MAP_PRIVATE, 295 fd, 296 0); 297 if (p == MAP_FAILED) { 298 printf("mmap() failed: %m\n"); 299 abort(); 300 } 301 302 return p; 303 } 304 305 static int mfd_assert_open(int fd, int flags, mode_t mode) 306 { 307 char buf[512]; 308 int r; 309 310 sprintf(buf, "/proc/self/fd/%d", fd); 311 r = open(buf, flags, mode); 312 if (r < 0) { 313 printf("open(%s) failed: %m\n", buf); 314 abort(); 315 } 316 317 return r; 318 } 319 320 static void mfd_fail_open(int fd, int flags, mode_t mode) 321 { 322 char buf[512]; 323 int r; 324 325 sprintf(buf, "/proc/self/fd/%d", fd); 326 r = open(buf, flags, mode); 327 if (r >= 0) { 328 printf("open(%s) didn't fail as expected\n", buf); 329 abort(); 330 } 331 } 332 333 static void mfd_assert_read(int fd) 334 { 335 char buf[16]; 336 void *p; 337 ssize_t l; 338 339 l = read(fd, buf, sizeof(buf)); 340 if (l != sizeof(buf)) { 341 printf("read() failed: %m\n"); 342 abort(); 343 } 344 345 /* verify PROT_READ *is* allowed */ 346 p = mmap(NULL, 347 mfd_def_size, 348 PROT_READ, 349 MAP_PRIVATE, 350 fd, 351 0); 352 if (p == MAP_FAILED) { 353 printf("mmap() failed: %m\n"); 354 abort(); 355 } 356 munmap(p, mfd_def_size); 357 358 /* verify MAP_PRIVATE is *always* allowed (even writable) */ 359 p = mmap(NULL, 360 mfd_def_size, 361 PROT_READ | PROT_WRITE, 362 MAP_PRIVATE, 363 fd, 364 0); 365 if (p == MAP_FAILED) { 366 printf("mmap() failed: %m\n"); 367 abort(); 368 } 369 munmap(p, mfd_def_size); 370 } 371 372 /* Test that PROT_READ + MAP_SHARED mappings work. */ 373 static void mfd_assert_read_shared(int fd) 374 { 375 void *p; 376 377 /* verify PROT_READ and MAP_SHARED *is* allowed */ 378 p = mmap(NULL, 379 mfd_def_size, 380 PROT_READ, 381 MAP_SHARED, 382 fd, 383 0); 384 if (p == MAP_FAILED) { 385 printf("mmap() failed: %m\n"); 386 abort(); 387 } 388 munmap(p, mfd_def_size); 389 } 390 391 static void mfd_assert_fork_private_write(int fd) 392 { 393 int *p; 394 pid_t pid; 395 396 p = mmap(NULL, 397 mfd_def_size, 398 PROT_READ | PROT_WRITE, 399 MAP_PRIVATE, 400 fd, 401 0); 402 if (p == MAP_FAILED) { 403 printf("mmap() failed: %m\n"); 404 abort(); 405 } 406 407 p[0] = 22; 408 409 pid = fork(); 410 if (pid == 0) { 411 p[0] = 33; 412 exit(0); 413 } else { 414 waitpid(pid, NULL, 0); 415 416 if (p[0] != 22) { 417 printf("MAP_PRIVATE copy-on-write failed: %m\n"); 418 abort(); 419 } 420 } 421 422 munmap(p, mfd_def_size); 423 } 424 425 static void mfd_assert_write(int fd) 426 { 427 ssize_t l; 428 void *p; 429 int r; 430 431 /* 432 * huegtlbfs does not support write, but we want to 433 * verify everything else here. 434 */ 435 if (!hugetlbfs_test) { 436 /* verify write() succeeds */ 437 l = write(fd, "\0\0\0\0", 4); 438 if (l != 4) { 439 printf("write() failed: %m\n"); 440 abort(); 441 } 442 } 443 444 /* verify PROT_READ | PROT_WRITE is allowed */ 445 p = mmap(NULL, 446 mfd_def_size, 447 PROT_READ | PROT_WRITE, 448 MAP_SHARED, 449 fd, 450 0); 451 if (p == MAP_FAILED) { 452 printf("mmap() failed: %m\n"); 453 abort(); 454 } 455 *(char *)p = 0; 456 munmap(p, mfd_def_size); 457 458 /* verify PROT_WRITE is allowed */ 459 p = mmap(NULL, 460 mfd_def_size, 461 PROT_WRITE, 462 MAP_SHARED, 463 fd, 464 0); 465 if (p == MAP_FAILED) { 466 printf("mmap() failed: %m\n"); 467 abort(); 468 } 469 *(char *)p = 0; 470 munmap(p, mfd_def_size); 471 472 /* verify PROT_READ with MAP_SHARED is allowed and a following 473 * mprotect(PROT_WRITE) allows writing */ 474 p = mmap(NULL, 475 mfd_def_size, 476 PROT_READ, 477 MAP_SHARED, 478 fd, 479 0); 480 if (p == MAP_FAILED) { 481 printf("mmap() failed: %m\n"); 482 abort(); 483 } 484 485 r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE); 486 if (r < 0) { 487 printf("mprotect() failed: %m\n"); 488 abort(); 489 } 490 491 *(char *)p = 0; 492 munmap(p, mfd_def_size); 493 494 /* verify PUNCH_HOLE works */ 495 r = fallocate(fd, 496 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 497 0, 498 mfd_def_size); 499 if (r < 0) { 500 printf("fallocate(PUNCH_HOLE) failed: %m\n"); 501 abort(); 502 } 503 } 504 505 static void mfd_fail_write(int fd) 506 { 507 ssize_t l; 508 void *p; 509 int r; 510 511 /* verify write() fails */ 512 l = write(fd, "data", 4); 513 if (l != -EPERM) { 514 printf("expected EPERM on write(), but got %d: %m\n", (int)l); 515 abort(); 516 } 517 518 /* verify PROT_READ | PROT_WRITE is not allowed */ 519 p = mmap(NULL, 520 mfd_def_size, 521 PROT_READ | PROT_WRITE, 522 MAP_SHARED, 523 fd, 524 0); 525 if (p != MAP_FAILED) { 526 printf("mmap() didn't fail as expected\n"); 527 abort(); 528 } 529 530 /* verify PROT_WRITE is not allowed */ 531 p = mmap(NULL, 532 mfd_def_size, 533 PROT_WRITE, 534 MAP_SHARED, 535 fd, 536 0); 537 if (p != MAP_FAILED) { 538 printf("mmap() didn't fail as expected\n"); 539 abort(); 540 } 541 542 /* Verify PROT_READ with MAP_SHARED with a following mprotect is not 543 * allowed. Note that for r/w the kernel already prevents the mmap. */ 544 p = mmap(NULL, 545 mfd_def_size, 546 PROT_READ, 547 MAP_SHARED, 548 fd, 549 0); 550 if (p != MAP_FAILED) { 551 r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE); 552 if (r >= 0) { 553 printf("mmap()+mprotect() didn't fail as expected\n"); 554 abort(); 555 } 556 munmap(p, mfd_def_size); 557 } 558 559 /* verify PUNCH_HOLE fails */ 560 r = fallocate(fd, 561 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 562 0, 563 mfd_def_size); 564 if (r >= 0) { 565 printf("fallocate(PUNCH_HOLE) didn't fail as expected\n"); 566 abort(); 567 } 568 } 569 570 static void mfd_assert_shrink(int fd) 571 { 572 int r, fd2; 573 574 r = ftruncate(fd, mfd_def_size / 2); 575 if (r < 0) { 576 printf("ftruncate(SHRINK) failed: %m\n"); 577 abort(); 578 } 579 580 mfd_assert_size(fd, mfd_def_size / 2); 581 582 fd2 = mfd_assert_open(fd, 583 O_RDWR | O_CREAT | O_TRUNC, 584 S_IRUSR | S_IWUSR); 585 close(fd2); 586 587 mfd_assert_size(fd, 0); 588 } 589 590 static void mfd_fail_shrink(int fd) 591 { 592 int r; 593 594 r = ftruncate(fd, mfd_def_size / 2); 595 if (r >= 0) { 596 printf("ftruncate(SHRINK) didn't fail as expected\n"); 597 abort(); 598 } 599 600 mfd_fail_open(fd, 601 O_RDWR | O_CREAT | O_TRUNC, 602 S_IRUSR | S_IWUSR); 603 } 604 605 static void mfd_assert_grow(int fd) 606 { 607 int r; 608 609 r = ftruncate(fd, mfd_def_size * 2); 610 if (r < 0) { 611 printf("ftruncate(GROW) failed: %m\n"); 612 abort(); 613 } 614 615 mfd_assert_size(fd, mfd_def_size * 2); 616 617 r = fallocate(fd, 618 0, 619 0, 620 mfd_def_size * 4); 621 if (r < 0) { 622 printf("fallocate(ALLOC) failed: %m\n"); 623 abort(); 624 } 625 626 mfd_assert_size(fd, mfd_def_size * 4); 627 } 628 629 static void mfd_fail_grow(int fd) 630 { 631 int r; 632 633 r = ftruncate(fd, mfd_def_size * 2); 634 if (r >= 0) { 635 printf("ftruncate(GROW) didn't fail as expected\n"); 636 abort(); 637 } 638 639 r = fallocate(fd, 640 0, 641 0, 642 mfd_def_size * 4); 643 if (r >= 0) { 644 printf("fallocate(ALLOC) didn't fail as expected\n"); 645 abort(); 646 } 647 } 648 649 static void mfd_assert_grow_write(int fd) 650 { 651 static char *buf; 652 ssize_t l; 653 654 /* hugetlbfs does not support write */ 655 if (hugetlbfs_test) 656 return; 657 658 buf = malloc(mfd_def_size * 8); 659 if (!buf) { 660 printf("malloc(%zu) failed: %m\n", mfd_def_size * 8); 661 abort(); 662 } 663 664 l = pwrite(fd, buf, mfd_def_size * 8, 0); 665 if (l != (mfd_def_size * 8)) { 666 printf("pwrite() failed: %m\n"); 667 abort(); 668 } 669 670 mfd_assert_size(fd, mfd_def_size * 8); 671 } 672 673 static void mfd_fail_grow_write(int fd) 674 { 675 static char *buf; 676 ssize_t l; 677 678 /* hugetlbfs does not support write */ 679 if (hugetlbfs_test) 680 return; 681 682 buf = malloc(mfd_def_size * 8); 683 if (!buf) { 684 printf("malloc(%zu) failed: %m\n", mfd_def_size * 8); 685 abort(); 686 } 687 688 l = pwrite(fd, buf, mfd_def_size * 8, 0); 689 if (l == (mfd_def_size * 8)) { 690 printf("pwrite() didn't fail as expected\n"); 691 abort(); 692 } 693 } 694 695 static void mfd_assert_mode(int fd, int mode) 696 { 697 struct stat st; 698 char buf[PATH_MAX]; 699 int nbytes; 700 701 fd2name(fd, buf, PATH_MAX); 702 703 if (fstat(fd, &st) < 0) { 704 printf("fstat(%s) failed: %m\n", buf); 705 abort(); 706 } 707 708 if ((st.st_mode & 07777) != mode) { 709 printf("fstat(%s) wrong file mode 0%04o, but expected 0%04o\n", 710 buf, (int)st.st_mode & 07777, mode); 711 abort(); 712 } 713 } 714 715 static void mfd_assert_chmod(int fd, int mode) 716 { 717 char buf[PATH_MAX]; 718 int nbytes; 719 720 fd2name(fd, buf, PATH_MAX); 721 722 if (fchmod(fd, mode) < 0) { 723 printf("fchmod(%s, 0%04o) failed: %m\n", buf, mode); 724 abort(); 725 } 726 727 mfd_assert_mode(fd, mode); 728 } 729 730 static void mfd_fail_chmod(int fd, int mode) 731 { 732 struct stat st; 733 char buf[PATH_MAX]; 734 int nbytes; 735 736 fd2name(fd, buf, PATH_MAX); 737 738 if (fstat(fd, &st) < 0) { 739 printf("fstat(%s) failed: %m\n", buf); 740 abort(); 741 } 742 743 if (fchmod(fd, mode) == 0) { 744 printf("fchmod(%s, 0%04o) didn't fail as expected\n", 745 buf, mode); 746 abort(); 747 } 748 749 /* verify that file mode bits did not change */ 750 mfd_assert_mode(fd, st.st_mode & 07777); 751 } 752 753 static int idle_thread_fn(void *arg) 754 { 755 sigset_t set; 756 int sig; 757 758 /* dummy waiter; SIGTERM terminates us anyway */ 759 sigemptyset(&set); 760 sigaddset(&set, SIGTERM); 761 sigwait(&set, &sig); 762 763 return 0; 764 } 765 766 static pid_t spawn_thread(unsigned int flags, int (*fn)(void *), void *arg) 767 { 768 uint8_t *stack; 769 pid_t pid; 770 771 stack = malloc(STACK_SIZE); 772 if (!stack) { 773 printf("malloc(STACK_SIZE) failed: %m\n"); 774 abort(); 775 } 776 777 pid = clone(fn, stack + STACK_SIZE, SIGCHLD | flags, arg); 778 if (pid < 0) { 779 printf("clone() failed: %m\n"); 780 abort(); 781 } 782 783 return pid; 784 } 785 786 static void join_thread(pid_t pid) 787 { 788 int wstatus; 789 790 if (waitpid(pid, &wstatus, 0) < 0) { 791 printf("newpid thread: waitpid() failed: %m\n"); 792 abort(); 793 } 794 795 if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0) { 796 printf("newpid thread: exited with non-zero error code %d\n", 797 WEXITSTATUS(wstatus)); 798 abort(); 799 } 800 801 if (WIFSIGNALED(wstatus)) { 802 printf("newpid thread: killed by signal %d\n", 803 WTERMSIG(wstatus)); 804 abort(); 805 } 806 } 807 808 static pid_t spawn_idle_thread(unsigned int flags) 809 { 810 return spawn_thread(flags, idle_thread_fn, NULL); 811 } 812 813 static void join_idle_thread(pid_t pid) 814 { 815 kill(pid, SIGTERM); 816 waitpid(pid, NULL, 0); 817 } 818 819 /* 820 * Test memfd_create() syscall 821 * Verify syscall-argument validation, including name checks, flag validation 822 * and more. 823 */ 824 static void test_create(void) 825 { 826 char buf[2048]; 827 int fd; 828 829 printf("%s CREATE\n", memfd_str); 830 831 /* test NULL name */ 832 mfd_fail_new(NULL, 0); 833 834 /* test over-long name (not zero-terminated) */ 835 memset(buf, 0xff, sizeof(buf)); 836 mfd_fail_new(buf, 0); 837 838 /* test over-long zero-terminated name */ 839 memset(buf, 0xff, sizeof(buf)); 840 buf[sizeof(buf) - 1] = 0; 841 mfd_fail_new(buf, 0); 842 843 /* verify "" is a valid name */ 844 fd = mfd_assert_new("", 0, 0); 845 close(fd); 846 847 /* verify invalid O_* open flags */ 848 mfd_fail_new("", 0x0100); 849 mfd_fail_new("", ~MFD_CLOEXEC); 850 mfd_fail_new("", ~MFD_ALLOW_SEALING); 851 mfd_fail_new("", ~0); 852 mfd_fail_new("", 0x80000000U); 853 854 /* verify EXEC and NOEXEC_SEAL can't both be set */ 855 mfd_fail_new("", MFD_EXEC | MFD_NOEXEC_SEAL); 856 857 /* verify MFD_CLOEXEC is allowed */ 858 fd = mfd_assert_new("", 0, MFD_CLOEXEC); 859 close(fd); 860 861 /* verify MFD_ALLOW_SEALING is allowed */ 862 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING); 863 close(fd); 864 865 /* verify MFD_ALLOW_SEALING | MFD_CLOEXEC is allowed */ 866 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC); 867 close(fd); 868 } 869 870 /* 871 * Test basic sealing 872 * A very basic sealing test to see whether setting/retrieving seals works. 873 */ 874 static void test_basic(void) 875 { 876 int fd; 877 878 printf("%s BASIC\n", memfd_str); 879 880 fd = mfd_assert_new("kern_memfd_basic", 881 mfd_def_size, 882 MFD_CLOEXEC | MFD_ALLOW_SEALING); 883 884 /* add basic seals */ 885 mfd_assert_has_seals(fd, 0); 886 mfd_assert_add_seals(fd, F_SEAL_SHRINK | 887 F_SEAL_WRITE); 888 mfd_assert_has_seals(fd, F_SEAL_SHRINK | 889 F_SEAL_WRITE); 890 891 /* add them again */ 892 mfd_assert_add_seals(fd, F_SEAL_SHRINK | 893 F_SEAL_WRITE); 894 mfd_assert_has_seals(fd, F_SEAL_SHRINK | 895 F_SEAL_WRITE); 896 897 /* add more seals and seal against sealing */ 898 mfd_assert_add_seals(fd, F_SEAL_GROW | F_SEAL_SEAL); 899 mfd_assert_has_seals(fd, F_SEAL_SHRINK | 900 F_SEAL_GROW | 901 F_SEAL_WRITE | 902 F_SEAL_SEAL); 903 904 /* verify that sealing no longer works */ 905 mfd_fail_add_seals(fd, F_SEAL_GROW); 906 mfd_fail_add_seals(fd, 0); 907 908 close(fd); 909 910 /* verify sealing does not work without MFD_ALLOW_SEALING */ 911 fd = mfd_assert_new("kern_memfd_basic", 912 mfd_def_size, 913 MFD_CLOEXEC); 914 mfd_assert_has_seals(fd, F_SEAL_SEAL); 915 mfd_fail_add_seals(fd, F_SEAL_SHRINK | 916 F_SEAL_GROW | 917 F_SEAL_WRITE); 918 mfd_assert_has_seals(fd, F_SEAL_SEAL); 919 close(fd); 920 } 921 922 /* 923 * Test SEAL_WRITE 924 * Test whether SEAL_WRITE actually prevents modifications. 925 */ 926 static void test_seal_write(void) 927 { 928 int fd; 929 930 printf("%s SEAL-WRITE\n", memfd_str); 931 932 fd = mfd_assert_new("kern_memfd_seal_write", 933 mfd_def_size, 934 MFD_CLOEXEC | MFD_ALLOW_SEALING); 935 mfd_assert_has_seals(fd, 0); 936 mfd_assert_add_seals(fd, F_SEAL_WRITE); 937 mfd_assert_has_seals(fd, F_SEAL_WRITE); 938 939 mfd_assert_read(fd); 940 mfd_fail_write(fd); 941 mfd_assert_shrink(fd); 942 mfd_assert_grow(fd); 943 mfd_fail_grow_write(fd); 944 945 close(fd); 946 } 947 948 /* 949 * Test SEAL_FUTURE_WRITE 950 * Test whether SEAL_FUTURE_WRITE actually prevents modifications. 951 */ 952 static void test_seal_future_write(void) 953 { 954 int fd, fd2; 955 void *p; 956 957 printf("%s SEAL-FUTURE-WRITE\n", memfd_str); 958 959 fd = mfd_assert_new("kern_memfd_seal_future_write", 960 mfd_def_size, 961 MFD_CLOEXEC | MFD_ALLOW_SEALING); 962 963 p = mfd_assert_mmap_shared(fd); 964 965 mfd_assert_has_seals(fd, 0); 966 967 mfd_assert_add_seals(fd, F_SEAL_FUTURE_WRITE); 968 mfd_assert_has_seals(fd, F_SEAL_FUTURE_WRITE); 969 970 /* read should pass, writes should fail */ 971 mfd_assert_read(fd); 972 mfd_assert_read_shared(fd); 973 mfd_fail_write(fd); 974 975 fd2 = mfd_assert_reopen_fd(fd); 976 /* read should pass, writes should still fail */ 977 mfd_assert_read(fd2); 978 mfd_assert_read_shared(fd2); 979 mfd_fail_write(fd2); 980 981 mfd_assert_fork_private_write(fd); 982 983 munmap(p, mfd_def_size); 984 close(fd2); 985 close(fd); 986 } 987 988 /* 989 * Test SEAL_SHRINK 990 * Test whether SEAL_SHRINK actually prevents shrinking 991 */ 992 static void test_seal_shrink(void) 993 { 994 int fd; 995 996 printf("%s SEAL-SHRINK\n", memfd_str); 997 998 fd = mfd_assert_new("kern_memfd_seal_shrink", 999 mfd_def_size, 1000 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1001 mfd_assert_has_seals(fd, 0); 1002 mfd_assert_add_seals(fd, F_SEAL_SHRINK); 1003 mfd_assert_has_seals(fd, F_SEAL_SHRINK); 1004 1005 mfd_assert_read(fd); 1006 mfd_assert_write(fd); 1007 mfd_fail_shrink(fd); 1008 mfd_assert_grow(fd); 1009 mfd_assert_grow_write(fd); 1010 1011 close(fd); 1012 } 1013 1014 /* 1015 * Test SEAL_GROW 1016 * Test whether SEAL_GROW actually prevents growing 1017 */ 1018 static void test_seal_grow(void) 1019 { 1020 int fd; 1021 1022 printf("%s SEAL-GROW\n", memfd_str); 1023 1024 fd = mfd_assert_new("kern_memfd_seal_grow", 1025 mfd_def_size, 1026 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1027 mfd_assert_has_seals(fd, 0); 1028 mfd_assert_add_seals(fd, F_SEAL_GROW); 1029 mfd_assert_has_seals(fd, F_SEAL_GROW); 1030 1031 mfd_assert_read(fd); 1032 mfd_assert_write(fd); 1033 mfd_assert_shrink(fd); 1034 mfd_fail_grow(fd); 1035 mfd_fail_grow_write(fd); 1036 1037 close(fd); 1038 } 1039 1040 /* 1041 * Test SEAL_SHRINK | SEAL_GROW 1042 * Test whether SEAL_SHRINK | SEAL_GROW actually prevents resizing 1043 */ 1044 static void test_seal_resize(void) 1045 { 1046 int fd; 1047 1048 printf("%s SEAL-RESIZE\n", memfd_str); 1049 1050 fd = mfd_assert_new("kern_memfd_seal_resize", 1051 mfd_def_size, 1052 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1053 mfd_assert_has_seals(fd, 0); 1054 mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW); 1055 mfd_assert_has_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW); 1056 1057 mfd_assert_read(fd); 1058 mfd_assert_write(fd); 1059 mfd_fail_shrink(fd); 1060 mfd_fail_grow(fd); 1061 mfd_fail_grow_write(fd); 1062 1063 close(fd); 1064 } 1065 1066 /* 1067 * Test SEAL_EXEC 1068 * Test fd is created with exec and allow sealing. 1069 * chmod() cannot change x bits after sealing. 1070 */ 1071 static void test_exec_seal(void) 1072 { 1073 int fd; 1074 1075 printf("%s SEAL-EXEC\n", memfd_str); 1076 1077 printf("%s Apply SEAL_EXEC\n", memfd_str); 1078 fd = mfd_assert_new("kern_memfd_seal_exec", 1079 mfd_def_size, 1080 MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_EXEC); 1081 1082 mfd_assert_mode(fd, 0777); 1083 mfd_assert_chmod(fd, 0644); 1084 1085 mfd_assert_has_seals(fd, 0); 1086 mfd_assert_add_seals(fd, F_SEAL_EXEC); 1087 mfd_assert_has_seals(fd, F_SEAL_EXEC); 1088 1089 mfd_assert_chmod(fd, 0600); 1090 mfd_fail_chmod(fd, 0777); 1091 mfd_fail_chmod(fd, 0670); 1092 mfd_fail_chmod(fd, 0605); 1093 mfd_fail_chmod(fd, 0700); 1094 mfd_fail_chmod(fd, 0100); 1095 mfd_assert_chmod(fd, 0666); 1096 mfd_assert_write(fd); 1097 close(fd); 1098 1099 printf("%s Apply ALL_SEALS\n", memfd_str); 1100 fd = mfd_assert_new("kern_memfd_seal_exec", 1101 mfd_def_size, 1102 MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_EXEC); 1103 1104 mfd_assert_mode(fd, 0777); 1105 mfd_assert_chmod(fd, 0700); 1106 1107 mfd_assert_has_seals(fd, 0); 1108 mfd_assert_add_seals(fd, F_SEAL_EXEC); 1109 mfd_assert_has_seals(fd, F_WX_SEALS); 1110 1111 mfd_fail_chmod(fd, 0711); 1112 mfd_fail_chmod(fd, 0600); 1113 mfd_fail_write(fd); 1114 close(fd); 1115 } 1116 1117 /* 1118 * Test EXEC_NO_SEAL 1119 * Test fd is created with exec and not allow sealing. 1120 */ 1121 static void test_exec_no_seal(void) 1122 { 1123 int fd; 1124 1125 printf("%s EXEC_NO_SEAL\n", memfd_str); 1126 1127 /* Create with EXEC but without ALLOW_SEALING */ 1128 fd = mfd_assert_new("kern_memfd_exec_no_sealing", 1129 mfd_def_size, 1130 MFD_CLOEXEC | MFD_EXEC); 1131 mfd_assert_mode(fd, 0777); 1132 mfd_assert_has_seals(fd, F_SEAL_SEAL); 1133 mfd_assert_chmod(fd, 0666); 1134 close(fd); 1135 } 1136 1137 /* 1138 * Test memfd_create with MFD_NOEXEC flag 1139 */ 1140 static void test_noexec_seal(void) 1141 { 1142 int fd; 1143 1144 printf("%s NOEXEC_SEAL\n", memfd_str); 1145 1146 /* Create with NOEXEC and ALLOW_SEALING */ 1147 fd = mfd_assert_new("kern_memfd_noexec", 1148 mfd_def_size, 1149 MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_NOEXEC_SEAL); 1150 mfd_assert_mode(fd, 0666); 1151 mfd_assert_has_seals(fd, F_SEAL_EXEC); 1152 mfd_fail_chmod(fd, 0777); 1153 close(fd); 1154 1155 /* Create with NOEXEC but without ALLOW_SEALING */ 1156 fd = mfd_assert_new("kern_memfd_noexec", 1157 mfd_def_size, 1158 MFD_CLOEXEC | MFD_NOEXEC_SEAL); 1159 mfd_assert_mode(fd, 0666); 1160 mfd_assert_has_seals(fd, F_SEAL_EXEC); 1161 mfd_fail_chmod(fd, 0777); 1162 close(fd); 1163 } 1164 1165 static void test_sysctl_sysctl0(void) 1166 { 1167 int fd; 1168 1169 sysctl_assert_equal("0"); 1170 1171 fd = mfd_assert_new("kern_memfd_sysctl_0_dfl", 1172 mfd_def_size, 1173 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1174 mfd_assert_mode(fd, 0777); 1175 mfd_assert_has_seals(fd, 0); 1176 mfd_assert_chmod(fd, 0644); 1177 close(fd); 1178 } 1179 1180 static void test_sysctl_set_sysctl0(void) 1181 { 1182 sysctl_assert_write("0"); 1183 test_sysctl_sysctl0(); 1184 } 1185 1186 static void test_sysctl_sysctl1(void) 1187 { 1188 int fd; 1189 1190 sysctl_assert_equal("1"); 1191 1192 fd = mfd_assert_new("kern_memfd_sysctl_1_dfl", 1193 mfd_def_size, 1194 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1195 mfd_assert_mode(fd, 0666); 1196 mfd_assert_has_seals(fd, F_SEAL_EXEC); 1197 mfd_fail_chmod(fd, 0777); 1198 close(fd); 1199 1200 fd = mfd_assert_new("kern_memfd_sysctl_1_exec", 1201 mfd_def_size, 1202 MFD_CLOEXEC | MFD_EXEC | MFD_ALLOW_SEALING); 1203 mfd_assert_mode(fd, 0777); 1204 mfd_assert_has_seals(fd, 0); 1205 mfd_assert_chmod(fd, 0644); 1206 close(fd); 1207 1208 fd = mfd_assert_new("kern_memfd_sysctl_1_noexec", 1209 mfd_def_size, 1210 MFD_CLOEXEC | MFD_NOEXEC_SEAL | MFD_ALLOW_SEALING); 1211 mfd_assert_mode(fd, 0666); 1212 mfd_assert_has_seals(fd, F_SEAL_EXEC); 1213 mfd_fail_chmod(fd, 0777); 1214 close(fd); 1215 } 1216 1217 static void test_sysctl_set_sysctl1(void) 1218 { 1219 sysctl_assert_write("1"); 1220 test_sysctl_sysctl1(); 1221 } 1222 1223 static void test_sysctl_sysctl2(void) 1224 { 1225 int fd; 1226 1227 sysctl_assert_equal("2"); 1228 1229 fd = mfd_assert_new("kern_memfd_sysctl_2_dfl", 1230 mfd_def_size, 1231 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1232 mfd_assert_mode(fd, 0666); 1233 mfd_assert_has_seals(fd, F_SEAL_EXEC); 1234 mfd_fail_chmod(fd, 0777); 1235 close(fd); 1236 1237 mfd_fail_new("kern_memfd_sysctl_2_exec", 1238 MFD_CLOEXEC | MFD_EXEC | MFD_ALLOW_SEALING); 1239 1240 fd = mfd_assert_new("kern_memfd_sysctl_2_noexec", 1241 mfd_def_size, 1242 MFD_CLOEXEC | MFD_NOEXEC_SEAL | MFD_ALLOW_SEALING); 1243 mfd_assert_mode(fd, 0666); 1244 mfd_assert_has_seals(fd, F_SEAL_EXEC); 1245 mfd_fail_chmod(fd, 0777); 1246 close(fd); 1247 } 1248 1249 static void test_sysctl_set_sysctl2(void) 1250 { 1251 sysctl_assert_write("2"); 1252 test_sysctl_sysctl2(); 1253 } 1254 1255 static int sysctl_simple_child(void *arg) 1256 { 1257 int fd; 1258 int pid; 1259 1260 printf("%s sysctl 0\n", memfd_str); 1261 test_sysctl_set_sysctl0(); 1262 1263 printf("%s sysctl 1\n", memfd_str); 1264 test_sysctl_set_sysctl1(); 1265 1266 printf("%s sysctl 0\n", memfd_str); 1267 test_sysctl_set_sysctl0(); 1268 1269 printf("%s sysctl 2\n", memfd_str); 1270 test_sysctl_set_sysctl2(); 1271 1272 printf("%s sysctl 1\n", memfd_str); 1273 test_sysctl_set_sysctl1(); 1274 1275 printf("%s sysctl 0\n", memfd_str); 1276 test_sysctl_set_sysctl0(); 1277 1278 return 0; 1279 } 1280 1281 /* 1282 * Test sysctl 1283 * A very basic test to make sure the core sysctl semantics work. 1284 */ 1285 static void test_sysctl_simple(void) 1286 { 1287 int pid = spawn_thread(CLONE_NEWPID, sysctl_simple_child, NULL); 1288 1289 join_thread(pid); 1290 } 1291 1292 static int sysctl_nested(void *arg) 1293 { 1294 void (*fn)(void) = arg; 1295 1296 fn(); 1297 return 0; 1298 } 1299 1300 static int sysctl_nested_wait(void *arg) 1301 { 1302 /* Wait for a SIGCONT. */ 1303 kill(getpid(), SIGSTOP); 1304 return sysctl_nested(arg); 1305 } 1306 1307 static void test_sysctl_sysctl1_failset(void) 1308 { 1309 sysctl_fail_write("0"); 1310 test_sysctl_sysctl1(); 1311 } 1312 1313 static void test_sysctl_sysctl2_failset(void) 1314 { 1315 sysctl_fail_write("1"); 1316 test_sysctl_sysctl2(); 1317 1318 sysctl_fail_write("0"); 1319 test_sysctl_sysctl2(); 1320 } 1321 1322 static int sysctl_nested_child(void *arg) 1323 { 1324 int fd; 1325 int pid; 1326 1327 printf("%s nested sysctl 0\n", memfd_str); 1328 sysctl_assert_write("0"); 1329 /* A further nested pidns works the same. */ 1330 pid = spawn_thread(CLONE_NEWPID, sysctl_simple_child, NULL); 1331 join_thread(pid); 1332 1333 printf("%s nested sysctl 1\n", memfd_str); 1334 sysctl_assert_write("1"); 1335 /* Child inherits our setting. */ 1336 pid = spawn_thread(CLONE_NEWPID, sysctl_nested, test_sysctl_sysctl1); 1337 join_thread(pid); 1338 /* Child cannot raise the setting. */ 1339 pid = spawn_thread(CLONE_NEWPID, sysctl_nested, 1340 test_sysctl_sysctl1_failset); 1341 join_thread(pid); 1342 /* Child can lower the setting. */ 1343 pid = spawn_thread(CLONE_NEWPID, sysctl_nested, 1344 test_sysctl_set_sysctl2); 1345 join_thread(pid); 1346 /* Child lowering the setting has no effect on our setting. */ 1347 test_sysctl_sysctl1(); 1348 1349 printf("%s nested sysctl 2\n", memfd_str); 1350 sysctl_assert_write("2"); 1351 /* Child inherits our setting. */ 1352 pid = spawn_thread(CLONE_NEWPID, sysctl_nested, test_sysctl_sysctl2); 1353 join_thread(pid); 1354 /* Child cannot raise the setting. */ 1355 pid = spawn_thread(CLONE_NEWPID, sysctl_nested, 1356 test_sysctl_sysctl2_failset); 1357 join_thread(pid); 1358 1359 /* Verify that the rules are actually inherited after fork. */ 1360 printf("%s nested sysctl 0 -> 1 after fork\n", memfd_str); 1361 sysctl_assert_write("0"); 1362 1363 pid = spawn_thread(CLONE_NEWPID, sysctl_nested_wait, 1364 test_sysctl_sysctl1_failset); 1365 sysctl_assert_write("1"); 1366 kill(pid, SIGCONT); 1367 join_thread(pid); 1368 1369 printf("%s nested sysctl 0 -> 2 after fork\n", memfd_str); 1370 sysctl_assert_write("0"); 1371 1372 pid = spawn_thread(CLONE_NEWPID, sysctl_nested_wait, 1373 test_sysctl_sysctl2_failset); 1374 sysctl_assert_write("2"); 1375 kill(pid, SIGCONT); 1376 join_thread(pid); 1377 1378 /* 1379 * Verify that the current effective setting is saved on fork, meaning 1380 * that the parent lowering the sysctl doesn't affect already-forked 1381 * children. 1382 */ 1383 printf("%s nested sysctl 2 -> 1 after fork\n", memfd_str); 1384 sysctl_assert_write("2"); 1385 pid = spawn_thread(CLONE_NEWPID, sysctl_nested_wait, 1386 test_sysctl_sysctl2); 1387 sysctl_assert_write("1"); 1388 kill(pid, SIGCONT); 1389 join_thread(pid); 1390 1391 printf("%s nested sysctl 2 -> 0 after fork\n", memfd_str); 1392 sysctl_assert_write("2"); 1393 pid = spawn_thread(CLONE_NEWPID, sysctl_nested_wait, 1394 test_sysctl_sysctl2); 1395 sysctl_assert_write("0"); 1396 kill(pid, SIGCONT); 1397 join_thread(pid); 1398 1399 printf("%s nested sysctl 1 -> 0 after fork\n", memfd_str); 1400 sysctl_assert_write("1"); 1401 pid = spawn_thread(CLONE_NEWPID, sysctl_nested_wait, 1402 test_sysctl_sysctl1); 1403 sysctl_assert_write("0"); 1404 kill(pid, SIGCONT); 1405 join_thread(pid); 1406 1407 return 0; 1408 } 1409 1410 /* 1411 * Test sysctl with nested pid namespaces 1412 * Make sure that the sysctl nesting semantics work correctly. 1413 */ 1414 static void test_sysctl_nested(void) 1415 { 1416 int pid = spawn_thread(CLONE_NEWPID, sysctl_nested_child, NULL); 1417 1418 join_thread(pid); 1419 } 1420 1421 /* 1422 * Test sharing via dup() 1423 * Test that seals are shared between dupped FDs and they're all equal. 1424 */ 1425 static void test_share_dup(char *banner, char *b_suffix) 1426 { 1427 int fd, fd2; 1428 1429 printf("%s %s %s\n", memfd_str, banner, b_suffix); 1430 1431 fd = mfd_assert_new("kern_memfd_share_dup", 1432 mfd_def_size, 1433 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1434 mfd_assert_has_seals(fd, 0); 1435 1436 fd2 = mfd_assert_dup(fd); 1437 mfd_assert_has_seals(fd2, 0); 1438 1439 mfd_assert_add_seals(fd, F_SEAL_WRITE); 1440 mfd_assert_has_seals(fd, F_SEAL_WRITE); 1441 mfd_assert_has_seals(fd2, F_SEAL_WRITE); 1442 1443 mfd_assert_add_seals(fd2, F_SEAL_SHRINK); 1444 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK); 1445 mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK); 1446 1447 mfd_assert_add_seals(fd, F_SEAL_SEAL); 1448 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL); 1449 mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL); 1450 1451 mfd_fail_add_seals(fd, F_SEAL_GROW); 1452 mfd_fail_add_seals(fd2, F_SEAL_GROW); 1453 mfd_fail_add_seals(fd, F_SEAL_SEAL); 1454 mfd_fail_add_seals(fd2, F_SEAL_SEAL); 1455 1456 close(fd2); 1457 1458 mfd_fail_add_seals(fd, F_SEAL_GROW); 1459 close(fd); 1460 } 1461 1462 /* 1463 * Test sealing with active mmap()s 1464 * Modifying seals is only allowed if no other mmap() refs exist. 1465 */ 1466 static void test_share_mmap(char *banner, char *b_suffix) 1467 { 1468 int fd; 1469 void *p; 1470 1471 printf("%s %s %s\n", memfd_str, banner, b_suffix); 1472 1473 fd = mfd_assert_new("kern_memfd_share_mmap", 1474 mfd_def_size, 1475 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1476 mfd_assert_has_seals(fd, 0); 1477 1478 /* shared/writable ref prevents sealing WRITE, but allows others */ 1479 p = mfd_assert_mmap_shared(fd); 1480 mfd_fail_add_seals(fd, F_SEAL_WRITE); 1481 mfd_assert_has_seals(fd, 0); 1482 mfd_assert_add_seals(fd, F_SEAL_SHRINK); 1483 mfd_assert_has_seals(fd, F_SEAL_SHRINK); 1484 munmap(p, mfd_def_size); 1485 1486 /* readable ref allows sealing */ 1487 p = mfd_assert_mmap_private(fd); 1488 mfd_assert_add_seals(fd, F_SEAL_WRITE); 1489 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK); 1490 munmap(p, mfd_def_size); 1491 1492 close(fd); 1493 } 1494 1495 /* 1496 * Test sealing with open(/proc/self/fd/%d) 1497 * Via /proc we can get access to a separate file-context for the same memfd. 1498 * This is *not* like dup(), but like a real separate open(). Make sure the 1499 * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR. 1500 */ 1501 static void test_share_open(char *banner, char *b_suffix) 1502 { 1503 int fd, fd2; 1504 1505 printf("%s %s %s\n", memfd_str, banner, b_suffix); 1506 1507 fd = mfd_assert_new("kern_memfd_share_open", 1508 mfd_def_size, 1509 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1510 mfd_assert_has_seals(fd, 0); 1511 1512 fd2 = mfd_assert_open(fd, O_RDWR, 0); 1513 mfd_assert_add_seals(fd, F_SEAL_WRITE); 1514 mfd_assert_has_seals(fd, F_SEAL_WRITE); 1515 mfd_assert_has_seals(fd2, F_SEAL_WRITE); 1516 1517 mfd_assert_add_seals(fd2, F_SEAL_SHRINK); 1518 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK); 1519 mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK); 1520 1521 close(fd); 1522 fd = mfd_assert_open(fd2, O_RDONLY, 0); 1523 1524 mfd_fail_add_seals(fd, F_SEAL_SEAL); 1525 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK); 1526 mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK); 1527 1528 close(fd2); 1529 fd2 = mfd_assert_open(fd, O_RDWR, 0); 1530 1531 mfd_assert_add_seals(fd2, F_SEAL_SEAL); 1532 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL); 1533 mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL); 1534 1535 close(fd2); 1536 close(fd); 1537 } 1538 1539 /* 1540 * Test sharing via fork() 1541 * Test whether seal-modifications work as expected with forked childs. 1542 */ 1543 static void test_share_fork(char *banner, char *b_suffix) 1544 { 1545 int fd; 1546 pid_t pid; 1547 1548 printf("%s %s %s\n", memfd_str, banner, b_suffix); 1549 1550 fd = mfd_assert_new("kern_memfd_share_fork", 1551 mfd_def_size, 1552 MFD_CLOEXEC | MFD_ALLOW_SEALING); 1553 mfd_assert_has_seals(fd, 0); 1554 1555 pid = spawn_idle_thread(0); 1556 mfd_assert_add_seals(fd, F_SEAL_SEAL); 1557 mfd_assert_has_seals(fd, F_SEAL_SEAL); 1558 1559 mfd_fail_add_seals(fd, F_SEAL_WRITE); 1560 mfd_assert_has_seals(fd, F_SEAL_SEAL); 1561 1562 join_idle_thread(pid); 1563 1564 mfd_fail_add_seals(fd, F_SEAL_WRITE); 1565 mfd_assert_has_seals(fd, F_SEAL_SEAL); 1566 1567 close(fd); 1568 } 1569 1570 int main(int argc, char **argv) 1571 { 1572 pid_t pid; 1573 1574 if (argc == 2) { 1575 if (!strcmp(argv[1], "hugetlbfs")) { 1576 unsigned long hpage_size = default_huge_page_size(); 1577 1578 if (!hpage_size) { 1579 printf("Unable to determine huge page size\n"); 1580 abort(); 1581 } 1582 1583 hugetlbfs_test = 1; 1584 memfd_str = MEMFD_HUGE_STR; 1585 mfd_def_size = hpage_size * 2; 1586 } else { 1587 printf("Unknown option: %s\n", argv[1]); 1588 abort(); 1589 } 1590 } 1591 1592 test_create(); 1593 test_basic(); 1594 test_exec_seal(); 1595 test_exec_no_seal(); 1596 test_noexec_seal(); 1597 1598 test_seal_write(); 1599 test_seal_future_write(); 1600 test_seal_shrink(); 1601 test_seal_grow(); 1602 test_seal_resize(); 1603 1604 test_sysctl_simple(); 1605 test_sysctl_nested(); 1606 1607 test_share_dup("SHARE-DUP", ""); 1608 test_share_mmap("SHARE-MMAP", ""); 1609 test_share_open("SHARE-OPEN", ""); 1610 test_share_fork("SHARE-FORK", ""); 1611 1612 /* Run test-suite in a multi-threaded environment with a shared 1613 * file-table. */ 1614 pid = spawn_idle_thread(CLONE_FILES | CLONE_FS | CLONE_VM); 1615 test_share_dup("SHARE-DUP", SHARED_FT_STR); 1616 test_share_mmap("SHARE-MMAP", SHARED_FT_STR); 1617 test_share_open("SHARE-OPEN", SHARED_FT_STR); 1618 test_share_fork("SHARE-FORK", SHARED_FT_STR); 1619 join_idle_thread(pid); 1620 1621 printf("memfd: DONE\n"); 1622 1623 return 0; 1624 } 1625