root/tools/testing/selftests/memfd/memfd_test.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mfd_assert_new
  2. mfd_assert_reopen_fd
  3. mfd_fail_new
  4. mfd_assert_get_seals
  5. mfd_assert_has_seals
  6. mfd_assert_add_seals
  7. mfd_fail_add_seals
  8. mfd_assert_size
  9. mfd_assert_dup
  10. mfd_assert_mmap_shared
  11. mfd_assert_mmap_private
  12. mfd_assert_open
  13. mfd_fail_open
  14. mfd_assert_read
  15. mfd_assert_read_shared
  16. mfd_assert_write
  17. mfd_fail_write
  18. mfd_assert_shrink
  19. mfd_fail_shrink
  20. mfd_assert_grow
  21. mfd_fail_grow
  22. mfd_assert_grow_write
  23. mfd_fail_grow_write
  24. idle_thread_fn
  25. spawn_idle_thread
  26. join_idle_thread
  27. test_create
  28. test_basic
  29. test_seal_write
  30. test_seal_future_write
  31. test_seal_shrink
  32. test_seal_grow
  33. test_seal_resize
  34. test_share_dup
  35. test_share_mmap
  36. test_share_open
  37. test_share_fork
  38. main

   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 <linux/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 
  22 #include "common.h"
  23 
  24 #define MEMFD_STR       "memfd:"
  25 #define MEMFD_HUGE_STR  "memfd-hugetlb:"
  26 #define SHARED_FT_STR   "(shared file-table)"
  27 
  28 #define MFD_DEF_SIZE 8192
  29 #define STACK_SIZE 65536
  30 
  31 /*
  32  * Default is not to test hugetlbfs
  33  */
  34 static size_t mfd_def_size = MFD_DEF_SIZE;
  35 static const char *memfd_str = MEMFD_STR;
  36 
  37 static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags)
  38 {
  39         int r, fd;
  40 
  41         fd = sys_memfd_create(name, flags);
  42         if (fd < 0) {
  43                 printf("memfd_create(\"%s\", %u) failed: %m\n",
  44                        name, flags);
  45                 abort();
  46         }
  47 
  48         r = ftruncate(fd, sz);
  49         if (r < 0) {
  50                 printf("ftruncate(%llu) failed: %m\n", (unsigned long long)sz);
  51                 abort();
  52         }
  53 
  54         return fd;
  55 }
  56 
  57 static int mfd_assert_reopen_fd(int fd_in)
  58 {
  59         int r, fd;
  60         char path[100];
  61 
  62         sprintf(path, "/proc/self/fd/%d", fd_in);
  63 
  64         fd = open(path, O_RDWR);
  65         if (fd < 0) {
  66                 printf("re-open of existing fd %d failed\n", fd_in);
  67                 abort();
  68         }
  69 
  70         return fd;
  71 }
  72 
  73 static void mfd_fail_new(const char *name, unsigned int flags)
  74 {
  75         int r;
  76 
  77         r = sys_memfd_create(name, flags);
  78         if (r >= 0) {
  79                 printf("memfd_create(\"%s\", %u) succeeded, but failure expected\n",
  80                        name, flags);
  81                 close(r);
  82                 abort();
  83         }
  84 }
  85 
  86 static unsigned int mfd_assert_get_seals(int fd)
  87 {
  88         int r;
  89 
  90         r = fcntl(fd, F_GET_SEALS);
  91         if (r < 0) {
  92                 printf("GET_SEALS(%d) failed: %m\n", fd);
  93                 abort();
  94         }
  95 
  96         return (unsigned int)r;
  97 }
  98 
  99 static void mfd_assert_has_seals(int fd, unsigned int seals)
 100 {
 101         unsigned int s;
 102 
 103         s = mfd_assert_get_seals(fd);
 104         if (s != seals) {
 105                 printf("%u != %u = GET_SEALS(%d)\n", seals, s, fd);
 106                 abort();
 107         }
 108 }
 109 
 110 static void mfd_assert_add_seals(int fd, unsigned int seals)
 111 {
 112         int r;
 113         unsigned int s;
 114 
 115         s = mfd_assert_get_seals(fd);
 116         r = fcntl(fd, F_ADD_SEALS, seals);
 117         if (r < 0) {
 118                 printf("ADD_SEALS(%d, %u -> %u) failed: %m\n", fd, s, seals);
 119                 abort();
 120         }
 121 }
 122 
 123 static void mfd_fail_add_seals(int fd, unsigned int seals)
 124 {
 125         int r;
 126         unsigned int s;
 127 
 128         r = fcntl(fd, F_GET_SEALS);
 129         if (r < 0)
 130                 s = 0;
 131         else
 132                 s = (unsigned int)r;
 133 
 134         r = fcntl(fd, F_ADD_SEALS, seals);
 135         if (r >= 0) {
 136                 printf("ADD_SEALS(%d, %u -> %u) didn't fail as expected\n",
 137                                 fd, s, seals);
 138                 abort();
 139         }
 140 }
 141 
 142 static void mfd_assert_size(int fd, size_t size)
 143 {
 144         struct stat st;
 145         int r;
 146 
 147         r = fstat(fd, &st);
 148         if (r < 0) {
 149                 printf("fstat(%d) failed: %m\n", fd);
 150                 abort();
 151         } else if (st.st_size != size) {
 152                 printf("wrong file size %lld, but expected %lld\n",
 153                        (long long)st.st_size, (long long)size);
 154                 abort();
 155         }
 156 }
 157 
 158 static int mfd_assert_dup(int fd)
 159 {
 160         int r;
 161 
 162         r = dup(fd);
 163         if (r < 0) {
 164                 printf("dup(%d) failed: %m\n", fd);
 165                 abort();
 166         }
 167 
 168         return r;
 169 }
 170 
 171 static void *mfd_assert_mmap_shared(int fd)
 172 {
 173         void *p;
 174 
 175         p = mmap(NULL,
 176                  mfd_def_size,
 177                  PROT_READ | PROT_WRITE,
 178                  MAP_SHARED,
 179                  fd,
 180                  0);
 181         if (p == MAP_FAILED) {
 182                 printf("mmap() failed: %m\n");
 183                 abort();
 184         }
 185 
 186         return p;
 187 }
 188 
 189 static void *mfd_assert_mmap_private(int fd)
 190 {
 191         void *p;
 192 
 193         p = mmap(NULL,
 194                  mfd_def_size,
 195                  PROT_READ,
 196                  MAP_PRIVATE,
 197                  fd,
 198                  0);
 199         if (p == MAP_FAILED) {
 200                 printf("mmap() failed: %m\n");
 201                 abort();
 202         }
 203 
 204         return p;
 205 }
 206 
 207 static int mfd_assert_open(int fd, int flags, mode_t mode)
 208 {
 209         char buf[512];
 210         int r;
 211 
 212         sprintf(buf, "/proc/self/fd/%d", fd);
 213         r = open(buf, flags, mode);
 214         if (r < 0) {
 215                 printf("open(%s) failed: %m\n", buf);
 216                 abort();
 217         }
 218 
 219         return r;
 220 }
 221 
 222 static void mfd_fail_open(int fd, int flags, mode_t mode)
 223 {
 224         char buf[512];
 225         int r;
 226 
 227         sprintf(buf, "/proc/self/fd/%d", fd);
 228         r = open(buf, flags, mode);
 229         if (r >= 0) {
 230                 printf("open(%s) didn't fail as expected\n", buf);
 231                 abort();
 232         }
 233 }
 234 
 235 static void mfd_assert_read(int fd)
 236 {
 237         char buf[16];
 238         void *p;
 239         ssize_t l;
 240 
 241         l = read(fd, buf, sizeof(buf));
 242         if (l != sizeof(buf)) {
 243                 printf("read() failed: %m\n");
 244                 abort();
 245         }
 246 
 247         /* verify PROT_READ *is* allowed */
 248         p = mmap(NULL,
 249                  mfd_def_size,
 250                  PROT_READ,
 251                  MAP_PRIVATE,
 252                  fd,
 253                  0);
 254         if (p == MAP_FAILED) {
 255                 printf("mmap() failed: %m\n");
 256                 abort();
 257         }
 258         munmap(p, mfd_def_size);
 259 
 260         /* verify MAP_PRIVATE is *always* allowed (even writable) */
 261         p = mmap(NULL,
 262                  mfd_def_size,
 263                  PROT_READ | PROT_WRITE,
 264                  MAP_PRIVATE,
 265                  fd,
 266                  0);
 267         if (p == MAP_FAILED) {
 268                 printf("mmap() failed: %m\n");
 269                 abort();
 270         }
 271         munmap(p, mfd_def_size);
 272 }
 273 
 274 /* Test that PROT_READ + MAP_SHARED mappings work. */
 275 static void mfd_assert_read_shared(int fd)
 276 {
 277         void *p;
 278 
 279         /* verify PROT_READ and MAP_SHARED *is* allowed */
 280         p = mmap(NULL,
 281                  mfd_def_size,
 282                  PROT_READ,
 283                  MAP_SHARED,
 284                  fd,
 285                  0);
 286         if (p == MAP_FAILED) {
 287                 printf("mmap() failed: %m\n");
 288                 abort();
 289         }
 290         munmap(p, mfd_def_size);
 291 }
 292 
 293 static void mfd_assert_write(int fd)
 294 {
 295         ssize_t l;
 296         void *p;
 297         int r;
 298 
 299         /*
 300          * huegtlbfs does not support write, but we want to
 301          * verify everything else here.
 302          */
 303         if (!hugetlbfs_test) {
 304                 /* verify write() succeeds */
 305                 l = write(fd, "\0\0\0\0", 4);
 306                 if (l != 4) {
 307                         printf("write() failed: %m\n");
 308                         abort();
 309                 }
 310         }
 311 
 312         /* verify PROT_READ | PROT_WRITE is allowed */
 313         p = mmap(NULL,
 314                  mfd_def_size,
 315                  PROT_READ | PROT_WRITE,
 316                  MAP_SHARED,
 317                  fd,
 318                  0);
 319         if (p == MAP_FAILED) {
 320                 printf("mmap() failed: %m\n");
 321                 abort();
 322         }
 323         *(char *)p = 0;
 324         munmap(p, mfd_def_size);
 325 
 326         /* verify PROT_WRITE is allowed */
 327         p = mmap(NULL,
 328                  mfd_def_size,
 329                  PROT_WRITE,
 330                  MAP_SHARED,
 331                  fd,
 332                  0);
 333         if (p == MAP_FAILED) {
 334                 printf("mmap() failed: %m\n");
 335                 abort();
 336         }
 337         *(char *)p = 0;
 338         munmap(p, mfd_def_size);
 339 
 340         /* verify PROT_READ with MAP_SHARED is allowed and a following
 341          * mprotect(PROT_WRITE) allows writing */
 342         p = mmap(NULL,
 343                  mfd_def_size,
 344                  PROT_READ,
 345                  MAP_SHARED,
 346                  fd,
 347                  0);
 348         if (p == MAP_FAILED) {
 349                 printf("mmap() failed: %m\n");
 350                 abort();
 351         }
 352 
 353         r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE);
 354         if (r < 0) {
 355                 printf("mprotect() failed: %m\n");
 356                 abort();
 357         }
 358 
 359         *(char *)p = 0;
 360         munmap(p, mfd_def_size);
 361 
 362         /* verify PUNCH_HOLE works */
 363         r = fallocate(fd,
 364                       FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
 365                       0,
 366                       mfd_def_size);
 367         if (r < 0) {
 368                 printf("fallocate(PUNCH_HOLE) failed: %m\n");
 369                 abort();
 370         }
 371 }
 372 
 373 static void mfd_fail_write(int fd)
 374 {
 375         ssize_t l;
 376         void *p;
 377         int r;
 378 
 379         /* verify write() fails */
 380         l = write(fd, "data", 4);
 381         if (l != -EPERM) {
 382                 printf("expected EPERM on write(), but got %d: %m\n", (int)l);
 383                 abort();
 384         }
 385 
 386         /* verify PROT_READ | PROT_WRITE is not allowed */
 387         p = mmap(NULL,
 388                  mfd_def_size,
 389                  PROT_READ | PROT_WRITE,
 390                  MAP_SHARED,
 391                  fd,
 392                  0);
 393         if (p != MAP_FAILED) {
 394                 printf("mmap() didn't fail as expected\n");
 395                 abort();
 396         }
 397 
 398         /* verify PROT_WRITE is not allowed */
 399         p = mmap(NULL,
 400                  mfd_def_size,
 401                  PROT_WRITE,
 402                  MAP_SHARED,
 403                  fd,
 404                  0);
 405         if (p != MAP_FAILED) {
 406                 printf("mmap() didn't fail as expected\n");
 407                 abort();
 408         }
 409 
 410         /* Verify PROT_READ with MAP_SHARED with a following mprotect is not
 411          * allowed. Note that for r/w the kernel already prevents the mmap. */
 412         p = mmap(NULL,
 413                  mfd_def_size,
 414                  PROT_READ,
 415                  MAP_SHARED,
 416                  fd,
 417                  0);
 418         if (p != MAP_FAILED) {
 419                 r = mprotect(p, mfd_def_size, PROT_READ | PROT_WRITE);
 420                 if (r >= 0) {
 421                         printf("mmap()+mprotect() didn't fail as expected\n");
 422                         abort();
 423                 }
 424         }
 425 
 426         /* verify PUNCH_HOLE fails */
 427         r = fallocate(fd,
 428                       FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
 429                       0,
 430                       mfd_def_size);
 431         if (r >= 0) {
 432                 printf("fallocate(PUNCH_HOLE) didn't fail as expected\n");
 433                 abort();
 434         }
 435 }
 436 
 437 static void mfd_assert_shrink(int fd)
 438 {
 439         int r, fd2;
 440 
 441         r = ftruncate(fd, mfd_def_size / 2);
 442         if (r < 0) {
 443                 printf("ftruncate(SHRINK) failed: %m\n");
 444                 abort();
 445         }
 446 
 447         mfd_assert_size(fd, mfd_def_size / 2);
 448 
 449         fd2 = mfd_assert_open(fd,
 450                               O_RDWR | O_CREAT | O_TRUNC,
 451                               S_IRUSR | S_IWUSR);
 452         close(fd2);
 453 
 454         mfd_assert_size(fd, 0);
 455 }
 456 
 457 static void mfd_fail_shrink(int fd)
 458 {
 459         int r;
 460 
 461         r = ftruncate(fd, mfd_def_size / 2);
 462         if (r >= 0) {
 463                 printf("ftruncate(SHRINK) didn't fail as expected\n");
 464                 abort();
 465         }
 466 
 467         mfd_fail_open(fd,
 468                       O_RDWR | O_CREAT | O_TRUNC,
 469                       S_IRUSR | S_IWUSR);
 470 }
 471 
 472 static void mfd_assert_grow(int fd)
 473 {
 474         int r;
 475 
 476         r = ftruncate(fd, mfd_def_size * 2);
 477         if (r < 0) {
 478                 printf("ftruncate(GROW) failed: %m\n");
 479                 abort();
 480         }
 481 
 482         mfd_assert_size(fd, mfd_def_size * 2);
 483 
 484         r = fallocate(fd,
 485                       0,
 486                       0,
 487                       mfd_def_size * 4);
 488         if (r < 0) {
 489                 printf("fallocate(ALLOC) failed: %m\n");
 490                 abort();
 491         }
 492 
 493         mfd_assert_size(fd, mfd_def_size * 4);
 494 }
 495 
 496 static void mfd_fail_grow(int fd)
 497 {
 498         int r;
 499 
 500         r = ftruncate(fd, mfd_def_size * 2);
 501         if (r >= 0) {
 502                 printf("ftruncate(GROW) didn't fail as expected\n");
 503                 abort();
 504         }
 505 
 506         r = fallocate(fd,
 507                       0,
 508                       0,
 509                       mfd_def_size * 4);
 510         if (r >= 0) {
 511                 printf("fallocate(ALLOC) didn't fail as expected\n");
 512                 abort();
 513         }
 514 }
 515 
 516 static void mfd_assert_grow_write(int fd)
 517 {
 518         static char *buf;
 519         ssize_t l;
 520 
 521         /* hugetlbfs does not support write */
 522         if (hugetlbfs_test)
 523                 return;
 524 
 525         buf = malloc(mfd_def_size * 8);
 526         if (!buf) {
 527                 printf("malloc(%zu) failed: %m\n", mfd_def_size * 8);
 528                 abort();
 529         }
 530 
 531         l = pwrite(fd, buf, mfd_def_size * 8, 0);
 532         if (l != (mfd_def_size * 8)) {
 533                 printf("pwrite() failed: %m\n");
 534                 abort();
 535         }
 536 
 537         mfd_assert_size(fd, mfd_def_size * 8);
 538 }
 539 
 540 static void mfd_fail_grow_write(int fd)
 541 {
 542         static char *buf;
 543         ssize_t l;
 544 
 545         /* hugetlbfs does not support write */
 546         if (hugetlbfs_test)
 547                 return;
 548 
 549         buf = malloc(mfd_def_size * 8);
 550         if (!buf) {
 551                 printf("malloc(%zu) failed: %m\n", mfd_def_size * 8);
 552                 abort();
 553         }
 554 
 555         l = pwrite(fd, buf, mfd_def_size * 8, 0);
 556         if (l == (mfd_def_size * 8)) {
 557                 printf("pwrite() didn't fail as expected\n");
 558                 abort();
 559         }
 560 }
 561 
 562 static int idle_thread_fn(void *arg)
 563 {
 564         sigset_t set;
 565         int sig;
 566 
 567         /* dummy waiter; SIGTERM terminates us anyway */
 568         sigemptyset(&set);
 569         sigaddset(&set, SIGTERM);
 570         sigwait(&set, &sig);
 571 
 572         return 0;
 573 }
 574 
 575 static pid_t spawn_idle_thread(unsigned int flags)
 576 {
 577         uint8_t *stack;
 578         pid_t pid;
 579 
 580         stack = malloc(STACK_SIZE);
 581         if (!stack) {
 582                 printf("malloc(STACK_SIZE) failed: %m\n");
 583                 abort();
 584         }
 585 
 586         pid = clone(idle_thread_fn,
 587                     stack + STACK_SIZE,
 588                     SIGCHLD | flags,
 589                     NULL);
 590         if (pid < 0) {
 591                 printf("clone() failed: %m\n");
 592                 abort();
 593         }
 594 
 595         return pid;
 596 }
 597 
 598 static void join_idle_thread(pid_t pid)
 599 {
 600         kill(pid, SIGTERM);
 601         waitpid(pid, NULL, 0);
 602 }
 603 
 604 /*
 605  * Test memfd_create() syscall
 606  * Verify syscall-argument validation, including name checks, flag validation
 607  * and more.
 608  */
 609 static void test_create(void)
 610 {
 611         char buf[2048];
 612         int fd;
 613 
 614         printf("%s CREATE\n", memfd_str);
 615 
 616         /* test NULL name */
 617         mfd_fail_new(NULL, 0);
 618 
 619         /* test over-long name (not zero-terminated) */
 620         memset(buf, 0xff, sizeof(buf));
 621         mfd_fail_new(buf, 0);
 622 
 623         /* test over-long zero-terminated name */
 624         memset(buf, 0xff, sizeof(buf));
 625         buf[sizeof(buf) - 1] = 0;
 626         mfd_fail_new(buf, 0);
 627 
 628         /* verify "" is a valid name */
 629         fd = mfd_assert_new("", 0, 0);
 630         close(fd);
 631 
 632         /* verify invalid O_* open flags */
 633         mfd_fail_new("", 0x0100);
 634         mfd_fail_new("", ~MFD_CLOEXEC);
 635         mfd_fail_new("", ~MFD_ALLOW_SEALING);
 636         mfd_fail_new("", ~0);
 637         mfd_fail_new("", 0x80000000U);
 638 
 639         /* verify MFD_CLOEXEC is allowed */
 640         fd = mfd_assert_new("", 0, MFD_CLOEXEC);
 641         close(fd);
 642 
 643         /* verify MFD_ALLOW_SEALING is allowed */
 644         fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING);
 645         close(fd);
 646 
 647         /* verify MFD_ALLOW_SEALING | MFD_CLOEXEC is allowed */
 648         fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC);
 649         close(fd);
 650 }
 651 
 652 /*
 653  * Test basic sealing
 654  * A very basic sealing test to see whether setting/retrieving seals works.
 655  */
 656 static void test_basic(void)
 657 {
 658         int fd;
 659 
 660         printf("%s BASIC\n", memfd_str);
 661 
 662         fd = mfd_assert_new("kern_memfd_basic",
 663                             mfd_def_size,
 664                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
 665 
 666         /* add basic seals */
 667         mfd_assert_has_seals(fd, 0);
 668         mfd_assert_add_seals(fd, F_SEAL_SHRINK |
 669                                  F_SEAL_WRITE);
 670         mfd_assert_has_seals(fd, F_SEAL_SHRINK |
 671                                  F_SEAL_WRITE);
 672 
 673         /* add them again */
 674         mfd_assert_add_seals(fd, F_SEAL_SHRINK |
 675                                  F_SEAL_WRITE);
 676         mfd_assert_has_seals(fd, F_SEAL_SHRINK |
 677                                  F_SEAL_WRITE);
 678 
 679         /* add more seals and seal against sealing */
 680         mfd_assert_add_seals(fd, F_SEAL_GROW | F_SEAL_SEAL);
 681         mfd_assert_has_seals(fd, F_SEAL_SHRINK |
 682                                  F_SEAL_GROW |
 683                                  F_SEAL_WRITE |
 684                                  F_SEAL_SEAL);
 685 
 686         /* verify that sealing no longer works */
 687         mfd_fail_add_seals(fd, F_SEAL_GROW);
 688         mfd_fail_add_seals(fd, 0);
 689 
 690         close(fd);
 691 
 692         /* verify sealing does not work without MFD_ALLOW_SEALING */
 693         fd = mfd_assert_new("kern_memfd_basic",
 694                             mfd_def_size,
 695                             MFD_CLOEXEC);
 696         mfd_assert_has_seals(fd, F_SEAL_SEAL);
 697         mfd_fail_add_seals(fd, F_SEAL_SHRINK |
 698                                F_SEAL_GROW |
 699                                F_SEAL_WRITE);
 700         mfd_assert_has_seals(fd, F_SEAL_SEAL);
 701         close(fd);
 702 }
 703 
 704 /*
 705  * Test SEAL_WRITE
 706  * Test whether SEAL_WRITE actually prevents modifications.
 707  */
 708 static void test_seal_write(void)
 709 {
 710         int fd;
 711 
 712         printf("%s SEAL-WRITE\n", memfd_str);
 713 
 714         fd = mfd_assert_new("kern_memfd_seal_write",
 715                             mfd_def_size,
 716                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
 717         mfd_assert_has_seals(fd, 0);
 718         mfd_assert_add_seals(fd, F_SEAL_WRITE);
 719         mfd_assert_has_seals(fd, F_SEAL_WRITE);
 720 
 721         mfd_assert_read(fd);
 722         mfd_fail_write(fd);
 723         mfd_assert_shrink(fd);
 724         mfd_assert_grow(fd);
 725         mfd_fail_grow_write(fd);
 726 
 727         close(fd);
 728 }
 729 
 730 /*
 731  * Test SEAL_FUTURE_WRITE
 732  * Test whether SEAL_FUTURE_WRITE actually prevents modifications.
 733  */
 734 static void test_seal_future_write(void)
 735 {
 736         int fd, fd2;
 737         void *p;
 738 
 739         printf("%s SEAL-FUTURE-WRITE\n", memfd_str);
 740 
 741         fd = mfd_assert_new("kern_memfd_seal_future_write",
 742                             mfd_def_size,
 743                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
 744 
 745         p = mfd_assert_mmap_shared(fd);
 746 
 747         mfd_assert_has_seals(fd, 0);
 748 
 749         mfd_assert_add_seals(fd, F_SEAL_FUTURE_WRITE);
 750         mfd_assert_has_seals(fd, F_SEAL_FUTURE_WRITE);
 751 
 752         /* read should pass, writes should fail */
 753         mfd_assert_read(fd);
 754         mfd_assert_read_shared(fd);
 755         mfd_fail_write(fd);
 756 
 757         fd2 = mfd_assert_reopen_fd(fd);
 758         /* read should pass, writes should still fail */
 759         mfd_assert_read(fd2);
 760         mfd_assert_read_shared(fd2);
 761         mfd_fail_write(fd2);
 762 
 763         munmap(p, mfd_def_size);
 764         close(fd2);
 765         close(fd);
 766 }
 767 
 768 /*
 769  * Test SEAL_SHRINK
 770  * Test whether SEAL_SHRINK actually prevents shrinking
 771  */
 772 static void test_seal_shrink(void)
 773 {
 774         int fd;
 775 
 776         printf("%s SEAL-SHRINK\n", memfd_str);
 777 
 778         fd = mfd_assert_new("kern_memfd_seal_shrink",
 779                             mfd_def_size,
 780                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
 781         mfd_assert_has_seals(fd, 0);
 782         mfd_assert_add_seals(fd, F_SEAL_SHRINK);
 783         mfd_assert_has_seals(fd, F_SEAL_SHRINK);
 784 
 785         mfd_assert_read(fd);
 786         mfd_assert_write(fd);
 787         mfd_fail_shrink(fd);
 788         mfd_assert_grow(fd);
 789         mfd_assert_grow_write(fd);
 790 
 791         close(fd);
 792 }
 793 
 794 /*
 795  * Test SEAL_GROW
 796  * Test whether SEAL_GROW actually prevents growing
 797  */
 798 static void test_seal_grow(void)
 799 {
 800         int fd;
 801 
 802         printf("%s SEAL-GROW\n", memfd_str);
 803 
 804         fd = mfd_assert_new("kern_memfd_seal_grow",
 805                             mfd_def_size,
 806                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
 807         mfd_assert_has_seals(fd, 0);
 808         mfd_assert_add_seals(fd, F_SEAL_GROW);
 809         mfd_assert_has_seals(fd, F_SEAL_GROW);
 810 
 811         mfd_assert_read(fd);
 812         mfd_assert_write(fd);
 813         mfd_assert_shrink(fd);
 814         mfd_fail_grow(fd);
 815         mfd_fail_grow_write(fd);
 816 
 817         close(fd);
 818 }
 819 
 820 /*
 821  * Test SEAL_SHRINK | SEAL_GROW
 822  * Test whether SEAL_SHRINK | SEAL_GROW actually prevents resizing
 823  */
 824 static void test_seal_resize(void)
 825 {
 826         int fd;
 827 
 828         printf("%s SEAL-RESIZE\n", memfd_str);
 829 
 830         fd = mfd_assert_new("kern_memfd_seal_resize",
 831                             mfd_def_size,
 832                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
 833         mfd_assert_has_seals(fd, 0);
 834         mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
 835         mfd_assert_has_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
 836 
 837         mfd_assert_read(fd);
 838         mfd_assert_write(fd);
 839         mfd_fail_shrink(fd);
 840         mfd_fail_grow(fd);
 841         mfd_fail_grow_write(fd);
 842 
 843         close(fd);
 844 }
 845 
 846 /*
 847  * Test sharing via dup()
 848  * Test that seals are shared between dupped FDs and they're all equal.
 849  */
 850 static void test_share_dup(char *banner, char *b_suffix)
 851 {
 852         int fd, fd2;
 853 
 854         printf("%s %s %s\n", memfd_str, banner, b_suffix);
 855 
 856         fd = mfd_assert_new("kern_memfd_share_dup",
 857                             mfd_def_size,
 858                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
 859         mfd_assert_has_seals(fd, 0);
 860 
 861         fd2 = mfd_assert_dup(fd);
 862         mfd_assert_has_seals(fd2, 0);
 863 
 864         mfd_assert_add_seals(fd, F_SEAL_WRITE);
 865         mfd_assert_has_seals(fd, F_SEAL_WRITE);
 866         mfd_assert_has_seals(fd2, F_SEAL_WRITE);
 867 
 868         mfd_assert_add_seals(fd2, F_SEAL_SHRINK);
 869         mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
 870         mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
 871 
 872         mfd_assert_add_seals(fd, F_SEAL_SEAL);
 873         mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
 874         mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
 875 
 876         mfd_fail_add_seals(fd, F_SEAL_GROW);
 877         mfd_fail_add_seals(fd2, F_SEAL_GROW);
 878         mfd_fail_add_seals(fd, F_SEAL_SEAL);
 879         mfd_fail_add_seals(fd2, F_SEAL_SEAL);
 880 
 881         close(fd2);
 882 
 883         mfd_fail_add_seals(fd, F_SEAL_GROW);
 884         close(fd);
 885 }
 886 
 887 /*
 888  * Test sealing with active mmap()s
 889  * Modifying seals is only allowed if no other mmap() refs exist.
 890  */
 891 static void test_share_mmap(char *banner, char *b_suffix)
 892 {
 893         int fd;
 894         void *p;
 895 
 896         printf("%s %s %s\n", memfd_str,  banner, b_suffix);
 897 
 898         fd = mfd_assert_new("kern_memfd_share_mmap",
 899                             mfd_def_size,
 900                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
 901         mfd_assert_has_seals(fd, 0);
 902 
 903         /* shared/writable ref prevents sealing WRITE, but allows others */
 904         p = mfd_assert_mmap_shared(fd);
 905         mfd_fail_add_seals(fd, F_SEAL_WRITE);
 906         mfd_assert_has_seals(fd, 0);
 907         mfd_assert_add_seals(fd, F_SEAL_SHRINK);
 908         mfd_assert_has_seals(fd, F_SEAL_SHRINK);
 909         munmap(p, mfd_def_size);
 910 
 911         /* readable ref allows sealing */
 912         p = mfd_assert_mmap_private(fd);
 913         mfd_assert_add_seals(fd, F_SEAL_WRITE);
 914         mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
 915         munmap(p, mfd_def_size);
 916 
 917         close(fd);
 918 }
 919 
 920 /*
 921  * Test sealing with open(/proc/self/fd/%d)
 922  * Via /proc we can get access to a separate file-context for the same memfd.
 923  * This is *not* like dup(), but like a real separate open(). Make sure the
 924  * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR.
 925  */
 926 static void test_share_open(char *banner, char *b_suffix)
 927 {
 928         int fd, fd2;
 929 
 930         printf("%s %s %s\n", memfd_str, banner, b_suffix);
 931 
 932         fd = mfd_assert_new("kern_memfd_share_open",
 933                             mfd_def_size,
 934                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
 935         mfd_assert_has_seals(fd, 0);
 936 
 937         fd2 = mfd_assert_open(fd, O_RDWR, 0);
 938         mfd_assert_add_seals(fd, F_SEAL_WRITE);
 939         mfd_assert_has_seals(fd, F_SEAL_WRITE);
 940         mfd_assert_has_seals(fd2, F_SEAL_WRITE);
 941 
 942         mfd_assert_add_seals(fd2, F_SEAL_SHRINK);
 943         mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
 944         mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
 945 
 946         close(fd);
 947         fd = mfd_assert_open(fd2, O_RDONLY, 0);
 948 
 949         mfd_fail_add_seals(fd, F_SEAL_SEAL);
 950         mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
 951         mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
 952 
 953         close(fd2);
 954         fd2 = mfd_assert_open(fd, O_RDWR, 0);
 955 
 956         mfd_assert_add_seals(fd2, F_SEAL_SEAL);
 957         mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
 958         mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
 959 
 960         close(fd2);
 961         close(fd);
 962 }
 963 
 964 /*
 965  * Test sharing via fork()
 966  * Test whether seal-modifications work as expected with forked childs.
 967  */
 968 static void test_share_fork(char *banner, char *b_suffix)
 969 {
 970         int fd;
 971         pid_t pid;
 972 
 973         printf("%s %s %s\n", memfd_str, banner, b_suffix);
 974 
 975         fd = mfd_assert_new("kern_memfd_share_fork",
 976                             mfd_def_size,
 977                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
 978         mfd_assert_has_seals(fd, 0);
 979 
 980         pid = spawn_idle_thread(0);
 981         mfd_assert_add_seals(fd, F_SEAL_SEAL);
 982         mfd_assert_has_seals(fd, F_SEAL_SEAL);
 983 
 984         mfd_fail_add_seals(fd, F_SEAL_WRITE);
 985         mfd_assert_has_seals(fd, F_SEAL_SEAL);
 986 
 987         join_idle_thread(pid);
 988 
 989         mfd_fail_add_seals(fd, F_SEAL_WRITE);
 990         mfd_assert_has_seals(fd, F_SEAL_SEAL);
 991 
 992         close(fd);
 993 }
 994 
 995 int main(int argc, char **argv)
 996 {
 997         pid_t pid;
 998 
 999         if (argc == 2) {
1000                 if (!strcmp(argv[1], "hugetlbfs")) {
1001                         unsigned long hpage_size = default_huge_page_size();
1002 
1003                         if (!hpage_size) {
1004                                 printf("Unable to determine huge page size\n");
1005                                 abort();
1006                         }
1007 
1008                         hugetlbfs_test = 1;
1009                         memfd_str = MEMFD_HUGE_STR;
1010                         mfd_def_size = hpage_size * 2;
1011                 } else {
1012                         printf("Unknown option: %s\n", argv[1]);
1013                         abort();
1014                 }
1015         }
1016 
1017         test_create();
1018         test_basic();
1019 
1020         test_seal_write();
1021         test_seal_future_write();
1022         test_seal_shrink();
1023         test_seal_grow();
1024         test_seal_resize();
1025 
1026         test_share_dup("SHARE-DUP", "");
1027         test_share_mmap("SHARE-MMAP", "");
1028         test_share_open("SHARE-OPEN", "");
1029         test_share_fork("SHARE-FORK", "");
1030 
1031         /* Run test-suite in a multi-threaded environment with a shared
1032          * file-table. */
1033         pid = spawn_idle_thread(CLONE_FILES | CLONE_FS | CLONE_VM);
1034         test_share_dup("SHARE-DUP", SHARED_FT_STR);
1035         test_share_mmap("SHARE-MMAP", SHARED_FT_STR);
1036         test_share_open("SHARE-OPEN", SHARED_FT_STR);
1037         test_share_fork("SHARE-FORK", SHARED_FT_STR);
1038         join_idle_thread(pid);
1039 
1040         printf("memfd: DONE\n");
1041 
1042         return 0;
1043 }

/* [<][>][^][v][top][bottom][index][help] */