0001
0002 #define _GNU_SOURCE
0003 #define __EXPORTED_HEADERS__
0004
0005 #include <errno.h>
0006 #include <inttypes.h>
0007 #include <limits.h>
0008 #include <linux/falloc.h>
0009 #include <fcntl.h>
0010 #include <linux/memfd.h>
0011 #include <sched.h>
0012 #include <stdio.h>
0013 #include <stdlib.h>
0014 #include <signal.h>
0015 #include <string.h>
0016 #include <sys/mman.h>
0017 #include <sys/stat.h>
0018 #include <sys/syscall.h>
0019 #include <sys/wait.h>
0020 #include <unistd.h>
0021
0022 #include "common.h"
0023
0024 #define MEMFD_STR "memfd:"
0025 #define MEMFD_HUGE_STR "memfd-hugetlb:"
0026 #define SHARED_FT_STR "(shared file-table)"
0027
0028 #define MFD_DEF_SIZE 8192
0029 #define STACK_SIZE 65536
0030
0031
0032
0033
0034 static size_t mfd_def_size = MFD_DEF_SIZE;
0035 static const char *memfd_str = MEMFD_STR;
0036
0037 static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags)
0038 {
0039 int r, fd;
0040
0041 fd = sys_memfd_create(name, flags);
0042 if (fd < 0) {
0043 printf("memfd_create(\"%s\", %u) failed: %m\n",
0044 name, flags);
0045 abort();
0046 }
0047
0048 r = ftruncate(fd, sz);
0049 if (r < 0) {
0050 printf("ftruncate(%llu) failed: %m\n", (unsigned long long)sz);
0051 abort();
0052 }
0053
0054 return fd;
0055 }
0056
0057 static int mfd_assert_reopen_fd(int fd_in)
0058 {
0059 int fd;
0060 char path[100];
0061
0062 sprintf(path, "/proc/self/fd/%d", fd_in);
0063
0064 fd = open(path, O_RDWR);
0065 if (fd < 0) {
0066 printf("re-open of existing fd %d failed\n", fd_in);
0067 abort();
0068 }
0069
0070 return fd;
0071 }
0072
0073 static void mfd_fail_new(const char *name, unsigned int flags)
0074 {
0075 int r;
0076
0077 r = sys_memfd_create(name, flags);
0078 if (r >= 0) {
0079 printf("memfd_create(\"%s\", %u) succeeded, but failure expected\n",
0080 name, flags);
0081 close(r);
0082 abort();
0083 }
0084 }
0085
0086 static unsigned int mfd_assert_get_seals(int fd)
0087 {
0088 int r;
0089
0090 r = fcntl(fd, F_GET_SEALS);
0091 if (r < 0) {
0092 printf("GET_SEALS(%d) failed: %m\n", fd);
0093 abort();
0094 }
0095
0096 return (unsigned int)r;
0097 }
0098
0099 static void mfd_assert_has_seals(int fd, unsigned int seals)
0100 {
0101 unsigned int s;
0102
0103 s = mfd_assert_get_seals(fd);
0104 if (s != seals) {
0105 printf("%u != %u = GET_SEALS(%d)\n", seals, s, fd);
0106 abort();
0107 }
0108 }
0109
0110 static void mfd_assert_add_seals(int fd, unsigned int seals)
0111 {
0112 int r;
0113 unsigned int s;
0114
0115 s = mfd_assert_get_seals(fd);
0116 r = fcntl(fd, F_ADD_SEALS, seals);
0117 if (r < 0) {
0118 printf("ADD_SEALS(%d, %u -> %u) failed: %m\n", fd, s, seals);
0119 abort();
0120 }
0121 }
0122
0123 static void mfd_fail_add_seals(int fd, unsigned int seals)
0124 {
0125 int r;
0126 unsigned int s;
0127
0128 r = fcntl(fd, F_GET_SEALS);
0129 if (r < 0)
0130 s = 0;
0131 else
0132 s = (unsigned int)r;
0133
0134 r = fcntl(fd, F_ADD_SEALS, seals);
0135 if (r >= 0) {
0136 printf("ADD_SEALS(%d, %u -> %u) didn't fail as expected\n",
0137 fd, s, seals);
0138 abort();
0139 }
0140 }
0141
0142 static void mfd_assert_size(int fd, size_t size)
0143 {
0144 struct stat st;
0145 int r;
0146
0147 r = fstat(fd, &st);
0148 if (r < 0) {
0149 printf("fstat(%d) failed: %m\n", fd);
0150 abort();
0151 } else if (st.st_size != size) {
0152 printf("wrong file size %lld, but expected %lld\n",
0153 (long long)st.st_size, (long long)size);
0154 abort();
0155 }
0156 }
0157
0158 static int mfd_assert_dup(int fd)
0159 {
0160 int r;
0161
0162 r = dup(fd);
0163 if (r < 0) {
0164 printf("dup(%d) failed: %m\n", fd);
0165 abort();
0166 }
0167
0168 return r;
0169 }
0170
0171 static void *mfd_assert_mmap_shared(int fd)
0172 {
0173 void *p;
0174
0175 p = mmap(NULL,
0176 mfd_def_size,
0177 PROT_READ | PROT_WRITE,
0178 MAP_SHARED,
0179 fd,
0180 0);
0181 if (p == MAP_FAILED) {
0182 printf("mmap() failed: %m\n");
0183 abort();
0184 }
0185
0186 return p;
0187 }
0188
0189 static void *mfd_assert_mmap_private(int fd)
0190 {
0191 void *p;
0192
0193 p = mmap(NULL,
0194 mfd_def_size,
0195 PROT_READ,
0196 MAP_PRIVATE,
0197 fd,
0198 0);
0199 if (p == MAP_FAILED) {
0200 printf("mmap() failed: %m\n");
0201 abort();
0202 }
0203
0204 return p;
0205 }
0206
0207 static int mfd_assert_open(int fd, int flags, mode_t mode)
0208 {
0209 char buf[512];
0210 int r;
0211
0212 sprintf(buf, "/proc/self/fd/%d", fd);
0213 r = open(buf, flags, mode);
0214 if (r < 0) {
0215 printf("open(%s) failed: %m\n", buf);
0216 abort();
0217 }
0218
0219 return r;
0220 }
0221
0222 static void mfd_fail_open(int fd, int flags, mode_t mode)
0223 {
0224 char buf[512];
0225 int r;
0226
0227 sprintf(buf, "/proc/self/fd/%d", fd);
0228 r = open(buf, flags, mode);
0229 if (r >= 0) {
0230 printf("open(%s) didn't fail as expected\n", buf);
0231 abort();
0232 }
0233 }
0234
0235 static void mfd_assert_read(int fd)
0236 {
0237 char buf[16];
0238 void *p;
0239 ssize_t l;
0240
0241 l = read(fd, buf, sizeof(buf));
0242 if (l != sizeof(buf)) {
0243 printf("read() failed: %m\n");
0244 abort();
0245 }
0246
0247
0248 p = mmap(NULL,
0249 mfd_def_size,
0250 PROT_READ,
0251 MAP_PRIVATE,
0252 fd,
0253 0);
0254 if (p == MAP_FAILED) {
0255 printf("mmap() failed: %m\n");
0256 abort();
0257 }
0258 munmap(p, mfd_def_size);
0259
0260
0261 p = mmap(NULL,
0262 mfd_def_size,
0263 PROT_READ | PROT_WRITE,
0264 MAP_PRIVATE,
0265 fd,
0266 0);
0267 if (p == MAP_FAILED) {
0268 printf("mmap() failed: %m\n");
0269 abort();
0270 }
0271 munmap(p, mfd_def_size);
0272 }
0273
0274
0275 static void mfd_assert_read_shared(int fd)
0276 {
0277 void *p;
0278
0279
0280 p = mmap(NULL,
0281 mfd_def_size,
0282 PROT_READ,
0283 MAP_SHARED,
0284 fd,
0285 0);
0286 if (p == MAP_FAILED) {
0287 printf("mmap() failed: %m\n");
0288 abort();
0289 }
0290 munmap(p, mfd_def_size);
0291 }
0292
0293 static void mfd_assert_fork_private_write(int fd)
0294 {
0295 int *p;
0296 pid_t pid;
0297
0298 p = mmap(NULL,
0299 mfd_def_size,
0300 PROT_READ | PROT_WRITE,
0301 MAP_PRIVATE,
0302 fd,
0303 0);
0304 if (p == MAP_FAILED) {
0305 printf("mmap() failed: %m\n");
0306 abort();
0307 }
0308
0309 p[0] = 22;
0310
0311 pid = fork();
0312 if (pid == 0) {
0313 p[0] = 33;
0314 exit(0);
0315 } else {
0316 waitpid(pid, NULL, 0);
0317
0318 if (p[0] != 22) {
0319 printf("MAP_PRIVATE copy-on-write failed: %m\n");
0320 abort();
0321 }
0322 }
0323
0324 munmap(p, mfd_def_size);
0325 }
0326
0327 static void mfd_assert_write(int fd)
0328 {
0329 ssize_t l;
0330 void *p;
0331 int r;
0332
0333
0334
0335
0336
0337 if (!hugetlbfs_test) {
0338
0339 l = write(fd, "\0\0\0\0", 4);
0340 if (l != 4) {
0341 printf("write() failed: %m\n");
0342 abort();
0343 }
0344 }
0345
0346
0347 p = mmap(NULL,
0348 mfd_def_size,
0349 PROT_READ | PROT_WRITE,
0350 MAP_SHARED,
0351 fd,
0352 0);
0353 if (p == MAP_FAILED) {
0354 printf("mmap() failed: %m\n");
0355 abort();
0356 }
0357 *(char *)p = 0;
0358 munmap(p, mfd_def_size);
0359
0360
0361 p = mmap(NULL,
0362 mfd_def_size,
0363 PROT_WRITE,
0364 MAP_SHARED,
0365 fd,
0366 0);
0367 if (p == MAP_FAILED) {
0368 printf("mmap() failed: %m\n");
0369 abort();
0370 }
0371 *(char *)p = 0;
0372 munmap(p, mfd_def_size);
0373
0374
0375
0376 p = mmap(NULL,
0377 mfd_def_size,
0378 PROT_READ,
0379 MAP_SHARED,
0380 fd,
0381 0);
0382 if (p == MAP_FAILED) {
0383 printf("mmap() failed: %m\n");
0384 abort();
0385 }
0386
0387 r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE);
0388 if (r < 0) {
0389 printf("mprotect() failed: %m\n");
0390 abort();
0391 }
0392
0393 *(char *)p = 0;
0394 munmap(p, mfd_def_size);
0395
0396
0397 r = fallocate(fd,
0398 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
0399 0,
0400 mfd_def_size);
0401 if (r < 0) {
0402 printf("fallocate(PUNCH_HOLE) failed: %m\n");
0403 abort();
0404 }
0405 }
0406
0407 static void mfd_fail_write(int fd)
0408 {
0409 ssize_t l;
0410 void *p;
0411 int r;
0412
0413
0414 l = write(fd, "data", 4);
0415 if (l != -EPERM) {
0416 printf("expected EPERM on write(), but got %d: %m\n", (int)l);
0417 abort();
0418 }
0419
0420
0421 p = mmap(NULL,
0422 mfd_def_size,
0423 PROT_READ | PROT_WRITE,
0424 MAP_SHARED,
0425 fd,
0426 0);
0427 if (p != MAP_FAILED) {
0428 printf("mmap() didn't fail as expected\n");
0429 abort();
0430 }
0431
0432
0433 p = mmap(NULL,
0434 mfd_def_size,
0435 PROT_WRITE,
0436 MAP_SHARED,
0437 fd,
0438 0);
0439 if (p != MAP_FAILED) {
0440 printf("mmap() didn't fail as expected\n");
0441 abort();
0442 }
0443
0444
0445
0446 p = mmap(NULL,
0447 mfd_def_size,
0448 PROT_READ,
0449 MAP_SHARED,
0450 fd,
0451 0);
0452 if (p != MAP_FAILED) {
0453 r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE);
0454 if (r >= 0) {
0455 printf("mmap()+mprotect() didn't fail as expected\n");
0456 abort();
0457 }
0458 munmap(p, mfd_def_size);
0459 }
0460
0461
0462 r = fallocate(fd,
0463 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
0464 0,
0465 mfd_def_size);
0466 if (r >= 0) {
0467 printf("fallocate(PUNCH_HOLE) didn't fail as expected\n");
0468 abort();
0469 }
0470 }
0471
0472 static void mfd_assert_shrink(int fd)
0473 {
0474 int r, fd2;
0475
0476 r = ftruncate(fd, mfd_def_size / 2);
0477 if (r < 0) {
0478 printf("ftruncate(SHRINK) failed: %m\n");
0479 abort();
0480 }
0481
0482 mfd_assert_size(fd, mfd_def_size / 2);
0483
0484 fd2 = mfd_assert_open(fd,
0485 O_RDWR | O_CREAT | O_TRUNC,
0486 S_IRUSR | S_IWUSR);
0487 close(fd2);
0488
0489 mfd_assert_size(fd, 0);
0490 }
0491
0492 static void mfd_fail_shrink(int fd)
0493 {
0494 int r;
0495
0496 r = ftruncate(fd, mfd_def_size / 2);
0497 if (r >= 0) {
0498 printf("ftruncate(SHRINK) didn't fail as expected\n");
0499 abort();
0500 }
0501
0502 mfd_fail_open(fd,
0503 O_RDWR | O_CREAT | O_TRUNC,
0504 S_IRUSR | S_IWUSR);
0505 }
0506
0507 static void mfd_assert_grow(int fd)
0508 {
0509 int r;
0510
0511 r = ftruncate(fd, mfd_def_size * 2);
0512 if (r < 0) {
0513 printf("ftruncate(GROW) failed: %m\n");
0514 abort();
0515 }
0516
0517 mfd_assert_size(fd, mfd_def_size * 2);
0518
0519 r = fallocate(fd,
0520 0,
0521 0,
0522 mfd_def_size * 4);
0523 if (r < 0) {
0524 printf("fallocate(ALLOC) failed: %m\n");
0525 abort();
0526 }
0527
0528 mfd_assert_size(fd, mfd_def_size * 4);
0529 }
0530
0531 static void mfd_fail_grow(int fd)
0532 {
0533 int r;
0534
0535 r = ftruncate(fd, mfd_def_size * 2);
0536 if (r >= 0) {
0537 printf("ftruncate(GROW) didn't fail as expected\n");
0538 abort();
0539 }
0540
0541 r = fallocate(fd,
0542 0,
0543 0,
0544 mfd_def_size * 4);
0545 if (r >= 0) {
0546 printf("fallocate(ALLOC) didn't fail as expected\n");
0547 abort();
0548 }
0549 }
0550
0551 static void mfd_assert_grow_write(int fd)
0552 {
0553 static char *buf;
0554 ssize_t l;
0555
0556
0557 if (hugetlbfs_test)
0558 return;
0559
0560 buf = malloc(mfd_def_size * 8);
0561 if (!buf) {
0562 printf("malloc(%zu) failed: %m\n", mfd_def_size * 8);
0563 abort();
0564 }
0565
0566 l = pwrite(fd, buf, mfd_def_size * 8, 0);
0567 if (l != (mfd_def_size * 8)) {
0568 printf("pwrite() failed: %m\n");
0569 abort();
0570 }
0571
0572 mfd_assert_size(fd, mfd_def_size * 8);
0573 }
0574
0575 static void mfd_fail_grow_write(int fd)
0576 {
0577 static char *buf;
0578 ssize_t l;
0579
0580
0581 if (hugetlbfs_test)
0582 return;
0583
0584 buf = malloc(mfd_def_size * 8);
0585 if (!buf) {
0586 printf("malloc(%zu) failed: %m\n", mfd_def_size * 8);
0587 abort();
0588 }
0589
0590 l = pwrite(fd, buf, mfd_def_size * 8, 0);
0591 if (l == (mfd_def_size * 8)) {
0592 printf("pwrite() didn't fail as expected\n");
0593 abort();
0594 }
0595 }
0596
0597 static int idle_thread_fn(void *arg)
0598 {
0599 sigset_t set;
0600 int sig;
0601
0602
0603 sigemptyset(&set);
0604 sigaddset(&set, SIGTERM);
0605 sigwait(&set, &sig);
0606
0607 return 0;
0608 }
0609
0610 static pid_t spawn_idle_thread(unsigned int flags)
0611 {
0612 uint8_t *stack;
0613 pid_t pid;
0614
0615 stack = malloc(STACK_SIZE);
0616 if (!stack) {
0617 printf("malloc(STACK_SIZE) failed: %m\n");
0618 abort();
0619 }
0620
0621 pid = clone(idle_thread_fn,
0622 stack + STACK_SIZE,
0623 SIGCHLD | flags,
0624 NULL);
0625 if (pid < 0) {
0626 printf("clone() failed: %m\n");
0627 abort();
0628 }
0629
0630 return pid;
0631 }
0632
0633 static void join_idle_thread(pid_t pid)
0634 {
0635 kill(pid, SIGTERM);
0636 waitpid(pid, NULL, 0);
0637 }
0638
0639
0640
0641
0642
0643
0644 static void test_create(void)
0645 {
0646 char buf[2048];
0647 int fd;
0648
0649 printf("%s CREATE\n", memfd_str);
0650
0651
0652 mfd_fail_new(NULL, 0);
0653
0654
0655 memset(buf, 0xff, sizeof(buf));
0656 mfd_fail_new(buf, 0);
0657
0658
0659 memset(buf, 0xff, sizeof(buf));
0660 buf[sizeof(buf) - 1] = 0;
0661 mfd_fail_new(buf, 0);
0662
0663
0664 fd = mfd_assert_new("", 0, 0);
0665 close(fd);
0666
0667
0668 mfd_fail_new("", 0x0100);
0669 mfd_fail_new("", ~MFD_CLOEXEC);
0670 mfd_fail_new("", ~MFD_ALLOW_SEALING);
0671 mfd_fail_new("", ~0);
0672 mfd_fail_new("", 0x80000000U);
0673
0674
0675 fd = mfd_assert_new("", 0, MFD_CLOEXEC);
0676 close(fd);
0677
0678
0679 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING);
0680 close(fd);
0681
0682
0683 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC);
0684 close(fd);
0685 }
0686
0687
0688
0689
0690
0691 static void test_basic(void)
0692 {
0693 int fd;
0694
0695 printf("%s BASIC\n", memfd_str);
0696
0697 fd = mfd_assert_new("kern_memfd_basic",
0698 mfd_def_size,
0699 MFD_CLOEXEC | MFD_ALLOW_SEALING);
0700
0701
0702 mfd_assert_has_seals(fd, 0);
0703 mfd_assert_add_seals(fd, F_SEAL_SHRINK |
0704 F_SEAL_WRITE);
0705 mfd_assert_has_seals(fd, F_SEAL_SHRINK |
0706 F_SEAL_WRITE);
0707
0708
0709 mfd_assert_add_seals(fd, F_SEAL_SHRINK |
0710 F_SEAL_WRITE);
0711 mfd_assert_has_seals(fd, F_SEAL_SHRINK |
0712 F_SEAL_WRITE);
0713
0714
0715 mfd_assert_add_seals(fd, F_SEAL_GROW | F_SEAL_SEAL);
0716 mfd_assert_has_seals(fd, F_SEAL_SHRINK |
0717 F_SEAL_GROW |
0718 F_SEAL_WRITE |
0719 F_SEAL_SEAL);
0720
0721
0722 mfd_fail_add_seals(fd, F_SEAL_GROW);
0723 mfd_fail_add_seals(fd, 0);
0724
0725 close(fd);
0726
0727
0728 fd = mfd_assert_new("kern_memfd_basic",
0729 mfd_def_size,
0730 MFD_CLOEXEC);
0731 mfd_assert_has_seals(fd, F_SEAL_SEAL);
0732 mfd_fail_add_seals(fd, F_SEAL_SHRINK |
0733 F_SEAL_GROW |
0734 F_SEAL_WRITE);
0735 mfd_assert_has_seals(fd, F_SEAL_SEAL);
0736 close(fd);
0737 }
0738
0739
0740
0741
0742
0743 static void test_seal_write(void)
0744 {
0745 int fd;
0746
0747 printf("%s SEAL-WRITE\n", memfd_str);
0748
0749 fd = mfd_assert_new("kern_memfd_seal_write",
0750 mfd_def_size,
0751 MFD_CLOEXEC | MFD_ALLOW_SEALING);
0752 mfd_assert_has_seals(fd, 0);
0753 mfd_assert_add_seals(fd, F_SEAL_WRITE);
0754 mfd_assert_has_seals(fd, F_SEAL_WRITE);
0755
0756 mfd_assert_read(fd);
0757 mfd_fail_write(fd);
0758 mfd_assert_shrink(fd);
0759 mfd_assert_grow(fd);
0760 mfd_fail_grow_write(fd);
0761
0762 close(fd);
0763 }
0764
0765
0766
0767
0768
0769 static void test_seal_future_write(void)
0770 {
0771 int fd, fd2;
0772 void *p;
0773
0774 printf("%s SEAL-FUTURE-WRITE\n", memfd_str);
0775
0776 fd = mfd_assert_new("kern_memfd_seal_future_write",
0777 mfd_def_size,
0778 MFD_CLOEXEC | MFD_ALLOW_SEALING);
0779
0780 p = mfd_assert_mmap_shared(fd);
0781
0782 mfd_assert_has_seals(fd, 0);
0783
0784 mfd_assert_add_seals(fd, F_SEAL_FUTURE_WRITE);
0785 mfd_assert_has_seals(fd, F_SEAL_FUTURE_WRITE);
0786
0787
0788 mfd_assert_read(fd);
0789 mfd_assert_read_shared(fd);
0790 mfd_fail_write(fd);
0791
0792 fd2 = mfd_assert_reopen_fd(fd);
0793
0794 mfd_assert_read(fd2);
0795 mfd_assert_read_shared(fd2);
0796 mfd_fail_write(fd2);
0797
0798 mfd_assert_fork_private_write(fd);
0799
0800 munmap(p, mfd_def_size);
0801 close(fd2);
0802 close(fd);
0803 }
0804
0805
0806
0807
0808
0809 static void test_seal_shrink(void)
0810 {
0811 int fd;
0812
0813 printf("%s SEAL-SHRINK\n", memfd_str);
0814
0815 fd = mfd_assert_new("kern_memfd_seal_shrink",
0816 mfd_def_size,
0817 MFD_CLOEXEC | MFD_ALLOW_SEALING);
0818 mfd_assert_has_seals(fd, 0);
0819 mfd_assert_add_seals(fd, F_SEAL_SHRINK);
0820 mfd_assert_has_seals(fd, F_SEAL_SHRINK);
0821
0822 mfd_assert_read(fd);
0823 mfd_assert_write(fd);
0824 mfd_fail_shrink(fd);
0825 mfd_assert_grow(fd);
0826 mfd_assert_grow_write(fd);
0827
0828 close(fd);
0829 }
0830
0831
0832
0833
0834
0835 static void test_seal_grow(void)
0836 {
0837 int fd;
0838
0839 printf("%s SEAL-GROW\n", memfd_str);
0840
0841 fd = mfd_assert_new("kern_memfd_seal_grow",
0842 mfd_def_size,
0843 MFD_CLOEXEC | MFD_ALLOW_SEALING);
0844 mfd_assert_has_seals(fd, 0);
0845 mfd_assert_add_seals(fd, F_SEAL_GROW);
0846 mfd_assert_has_seals(fd, F_SEAL_GROW);
0847
0848 mfd_assert_read(fd);
0849 mfd_assert_write(fd);
0850 mfd_assert_shrink(fd);
0851 mfd_fail_grow(fd);
0852 mfd_fail_grow_write(fd);
0853
0854 close(fd);
0855 }
0856
0857
0858
0859
0860
0861 static void test_seal_resize(void)
0862 {
0863 int fd;
0864
0865 printf("%s SEAL-RESIZE\n", memfd_str);
0866
0867 fd = mfd_assert_new("kern_memfd_seal_resize",
0868 mfd_def_size,
0869 MFD_CLOEXEC | MFD_ALLOW_SEALING);
0870 mfd_assert_has_seals(fd, 0);
0871 mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
0872 mfd_assert_has_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
0873
0874 mfd_assert_read(fd);
0875 mfd_assert_write(fd);
0876 mfd_fail_shrink(fd);
0877 mfd_fail_grow(fd);
0878 mfd_fail_grow_write(fd);
0879
0880 close(fd);
0881 }
0882
0883
0884
0885
0886
0887 static void test_share_dup(char *banner, char *b_suffix)
0888 {
0889 int fd, fd2;
0890
0891 printf("%s %s %s\n", memfd_str, banner, b_suffix);
0892
0893 fd = mfd_assert_new("kern_memfd_share_dup",
0894 mfd_def_size,
0895 MFD_CLOEXEC | MFD_ALLOW_SEALING);
0896 mfd_assert_has_seals(fd, 0);
0897
0898 fd2 = mfd_assert_dup(fd);
0899 mfd_assert_has_seals(fd2, 0);
0900
0901 mfd_assert_add_seals(fd, F_SEAL_WRITE);
0902 mfd_assert_has_seals(fd, F_SEAL_WRITE);
0903 mfd_assert_has_seals(fd2, F_SEAL_WRITE);
0904
0905 mfd_assert_add_seals(fd2, F_SEAL_SHRINK);
0906 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
0907 mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
0908
0909 mfd_assert_add_seals(fd, F_SEAL_SEAL);
0910 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
0911 mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
0912
0913 mfd_fail_add_seals(fd, F_SEAL_GROW);
0914 mfd_fail_add_seals(fd2, F_SEAL_GROW);
0915 mfd_fail_add_seals(fd, F_SEAL_SEAL);
0916 mfd_fail_add_seals(fd2, F_SEAL_SEAL);
0917
0918 close(fd2);
0919
0920 mfd_fail_add_seals(fd, F_SEAL_GROW);
0921 close(fd);
0922 }
0923
0924
0925
0926
0927
0928 static void test_share_mmap(char *banner, char *b_suffix)
0929 {
0930 int fd;
0931 void *p;
0932
0933 printf("%s %s %s\n", memfd_str, banner, b_suffix);
0934
0935 fd = mfd_assert_new("kern_memfd_share_mmap",
0936 mfd_def_size,
0937 MFD_CLOEXEC | MFD_ALLOW_SEALING);
0938 mfd_assert_has_seals(fd, 0);
0939
0940
0941 p = mfd_assert_mmap_shared(fd);
0942 mfd_fail_add_seals(fd, F_SEAL_WRITE);
0943 mfd_assert_has_seals(fd, 0);
0944 mfd_assert_add_seals(fd, F_SEAL_SHRINK);
0945 mfd_assert_has_seals(fd, F_SEAL_SHRINK);
0946 munmap(p, mfd_def_size);
0947
0948
0949 p = mfd_assert_mmap_private(fd);
0950 mfd_assert_add_seals(fd, F_SEAL_WRITE);
0951 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
0952 munmap(p, mfd_def_size);
0953
0954 close(fd);
0955 }
0956
0957
0958
0959
0960
0961
0962
0963 static void test_share_open(char *banner, char *b_suffix)
0964 {
0965 int fd, fd2;
0966
0967 printf("%s %s %s\n", memfd_str, banner, b_suffix);
0968
0969 fd = mfd_assert_new("kern_memfd_share_open",
0970 mfd_def_size,
0971 MFD_CLOEXEC | MFD_ALLOW_SEALING);
0972 mfd_assert_has_seals(fd, 0);
0973
0974 fd2 = mfd_assert_open(fd, O_RDWR, 0);
0975 mfd_assert_add_seals(fd, F_SEAL_WRITE);
0976 mfd_assert_has_seals(fd, F_SEAL_WRITE);
0977 mfd_assert_has_seals(fd2, F_SEAL_WRITE);
0978
0979 mfd_assert_add_seals(fd2, F_SEAL_SHRINK);
0980 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
0981 mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
0982
0983 close(fd);
0984 fd = mfd_assert_open(fd2, O_RDONLY, 0);
0985
0986 mfd_fail_add_seals(fd, F_SEAL_SEAL);
0987 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
0988 mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
0989
0990 close(fd2);
0991 fd2 = mfd_assert_open(fd, O_RDWR, 0);
0992
0993 mfd_assert_add_seals(fd2, F_SEAL_SEAL);
0994 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
0995 mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
0996
0997 close(fd2);
0998 close(fd);
0999 }
1000
1001
1002
1003
1004
1005 static void test_share_fork(char *banner, char *b_suffix)
1006 {
1007 int fd;
1008 pid_t pid;
1009
1010 printf("%s %s %s\n", memfd_str, banner, b_suffix);
1011
1012 fd = mfd_assert_new("kern_memfd_share_fork",
1013 mfd_def_size,
1014 MFD_CLOEXEC | MFD_ALLOW_SEALING);
1015 mfd_assert_has_seals(fd, 0);
1016
1017 pid = spawn_idle_thread(0);
1018 mfd_assert_add_seals(fd, F_SEAL_SEAL);
1019 mfd_assert_has_seals(fd, F_SEAL_SEAL);
1020
1021 mfd_fail_add_seals(fd, F_SEAL_WRITE);
1022 mfd_assert_has_seals(fd, F_SEAL_SEAL);
1023
1024 join_idle_thread(pid);
1025
1026 mfd_fail_add_seals(fd, F_SEAL_WRITE);
1027 mfd_assert_has_seals(fd, F_SEAL_SEAL);
1028
1029 close(fd);
1030 }
1031
1032 int main(int argc, char **argv)
1033 {
1034 pid_t pid;
1035
1036 if (argc == 2) {
1037 if (!strcmp(argv[1], "hugetlbfs")) {
1038 unsigned long hpage_size = default_huge_page_size();
1039
1040 if (!hpage_size) {
1041 printf("Unable to determine huge page size\n");
1042 abort();
1043 }
1044
1045 hugetlbfs_test = 1;
1046 memfd_str = MEMFD_HUGE_STR;
1047 mfd_def_size = hpage_size * 2;
1048 } else {
1049 printf("Unknown option: %s\n", argv[1]);
1050 abort();
1051 }
1052 }
1053
1054 test_create();
1055 test_basic();
1056
1057 test_seal_write();
1058 test_seal_future_write();
1059 test_seal_shrink();
1060 test_seal_grow();
1061 test_seal_resize();
1062
1063 test_share_dup("SHARE-DUP", "");
1064 test_share_mmap("SHARE-MMAP", "");
1065 test_share_open("SHARE-OPEN", "");
1066 test_share_fork("SHARE-FORK", "");
1067
1068
1069
1070 pid = spawn_idle_thread(CLONE_FILES | CLONE_FS | CLONE_VM);
1071 test_share_dup("SHARE-DUP", SHARED_FT_STR);
1072 test_share_mmap("SHARE-MMAP", SHARED_FT_STR);
1073 test_share_open("SHARE-OPEN", SHARED_FT_STR);
1074 test_share_fork("SHARE-FORK", SHARED_FT_STR);
1075 join_idle_thread(pid);
1076
1077 printf("memfd: DONE\n");
1078
1079 return 0;
1080 }