gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/memfd.cc (about)

     1  // Copyright 2019 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  #include <errno.h>
    16  #include <fcntl.h>
    17  #include <linux/memfd.h>
    18  #include <linux/unistd.h>
    19  #include <string.h>
    20  #include <sys/mman.h>
    21  #include <sys/syscall.h>
    22  
    23  #include <vector>
    24  
    25  #include "gtest/gtest.h"
    26  #include "test/util/file_descriptor.h"
    27  #include "test/util/fs_util.h"
    28  #include "test/util/memory_util.h"
    29  #include "test/util/multiprocess_util.h"
    30  #include "test/util/temp_path.h"
    31  #include "test/util/test_util.h"
    32  
    33  namespace gvisor {
    34  namespace testing {
    35  namespace {
    36  
    37  // The header sys/memfd.h isn't available on all systems, so redefining some of
    38  // the constants here.
    39  #define F_LINUX_SPECIFIC_BASE 1024
    40  
    41  #ifndef F_ADD_SEALS
    42  #define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
    43  #endif /* F_ADD_SEALS */
    44  
    45  #ifndef F_GET_SEALS
    46  #define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
    47  #endif /* F_GET_SEALS */
    48  
    49  #define F_SEAL_SEAL 0x0001
    50  #define F_SEAL_SHRINK 0x0002
    51  #define F_SEAL_GROW 0x0004
    52  #define F_SEAL_WRITE 0x0008
    53  
    54  using ::gvisor::testing::IsTmpfs;
    55  using ::testing::StartsWith;
    56  
    57  const std::string kMemfdName = "some-memfd";
    58  
    59  int memfd_create(const std::string& name, unsigned int flags) {
    60    return syscall(__NR_memfd_create, name.c_str(), flags);
    61  }
    62  
    63  PosixErrorOr<FileDescriptor> MemfdCreate(const std::string& name,
    64                                           uint32_t flags) {
    65    int fd = memfd_create(name, flags);
    66    if (fd < 0) {
    67      return PosixError(
    68          errno, absl::StrFormat("memfd_create(\"%s\", %#x)", name, flags));
    69    }
    70    MaybeSave();
    71    return FileDescriptor(fd);
    72  }
    73  
    74  // Procfs entries for memfds display the appropriate name.
    75  TEST(MemfdTest, Name) {
    76    const FileDescriptor memfd =
    77        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, 0));
    78    const std::string proc_name = ASSERT_NO_ERRNO_AND_VALUE(
    79        ReadLink(absl::StrFormat("/proc/self/fd/%d", memfd.get())));
    80    EXPECT_THAT(proc_name, StartsWith("/memfd:" + kMemfdName));
    81  }
    82  
    83  // Memfds support read/write syscalls.
    84  TEST(MemfdTest, WriteRead) {
    85    const FileDescriptor memfd =
    86        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, 0));
    87  
    88    // Write a random page of data to the memfd via write(2).
    89    std::vector<char> buf(kPageSize);
    90    RandomizeBuffer(buf.data(), buf.size());
    91    ASSERT_THAT(write(memfd.get(), buf.data(), buf.size()),
    92                SyscallSucceedsWithValue(kPageSize));
    93  
    94    // Read back the same data and verify.
    95    std::vector<char> buf2(kPageSize);
    96    ASSERT_THAT(lseek(memfd.get(), 0, SEEK_SET), SyscallSucceeds());
    97    EXPECT_THAT(read(memfd.get(), buf2.data(), buf2.size()),
    98                SyscallSucceedsWithValue(kPageSize));
    99    EXPECT_EQ(buf, buf2);
   100  }
   101  
   102  // Memfds can be mapped and used as usual.
   103  TEST(MemfdTest, Mmap) {
   104    const FileDescriptor memfd =
   105        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, 0));
   106    const Mapping m1 = ASSERT_NO_ERRNO_AND_VALUE(Mmap(
   107        nullptr, kPageSize, PROT_READ | PROT_WRITE, MAP_SHARED, memfd.get(), 0));
   108  
   109    // Write a random page of data to the memfd via mmap m1.
   110    std::vector<char> buf(kPageSize);
   111    RandomizeBuffer(buf.data(), buf.size());
   112    ASSERT_THAT(ftruncate(memfd.get(), kPageSize), SyscallSucceeds());
   113    memcpy(m1.ptr(), buf.data(), buf.size());
   114  
   115    // Read the data back via a read syscall on the memfd.
   116    std::vector<char> buf2(kPageSize);
   117    EXPECT_THAT(read(memfd.get(), buf2.data(), buf2.size()),
   118                SyscallSucceedsWithValue(kPageSize));
   119    EXPECT_EQ(buf, buf2);
   120  
   121    // The same data should be accessible via a new mapping m2.
   122    const Mapping m2 = ASSERT_NO_ERRNO_AND_VALUE(Mmap(
   123        nullptr, kPageSize, PROT_READ | PROT_WRITE, MAP_SHARED, memfd.get(), 0));
   124    EXPECT_EQ(0, memcmp(m1.ptr(), m2.ptr(), kPageSize));
   125  }
   126  
   127  TEST(MemfdTest, DuplicateFDsShareContent) {
   128    const FileDescriptor memfd =
   129        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, 0));
   130    const Mapping m1 = ASSERT_NO_ERRNO_AND_VALUE(Mmap(
   131        nullptr, kPageSize, PROT_READ | PROT_WRITE, MAP_SHARED, memfd.get(), 0));
   132    const FileDescriptor memfd2 = ASSERT_NO_ERRNO_AND_VALUE(memfd.Dup());
   133  
   134    // Write a random page of data to the memfd via mmap m1.
   135    std::vector<char> buf(kPageSize);
   136    RandomizeBuffer(buf.data(), buf.size());
   137    ASSERT_THAT(ftruncate(memfd.get(), kPageSize), SyscallSucceeds());
   138    memcpy(m1.ptr(), buf.data(), buf.size());
   139  
   140    // Read the data back via a read syscall on a duplicate fd.
   141    std::vector<char> buf2(kPageSize);
   142    EXPECT_THAT(read(memfd2.get(), buf2.data(), buf2.size()),
   143                SyscallSucceedsWithValue(kPageSize));
   144    EXPECT_EQ(buf, buf2);
   145  }
   146  
   147  // File seals are disabled by default on memfds.
   148  TEST(MemfdTest, SealingDisabledByDefault) {
   149    const FileDescriptor memfd =
   150        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, 0));
   151    EXPECT_THAT(fcntl(memfd.get(), F_GET_SEALS),
   152                SyscallSucceedsWithValue(F_SEAL_SEAL));
   153    // Attempting to set any seal should fail.
   154    EXPECT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_WRITE),
   155                SyscallFailsWithErrno(EPERM));
   156  }
   157  
   158  // Seals can be retrieved and updated for memfds.
   159  TEST(MemfdTest, SealsGetSet) {
   160    const FileDescriptor memfd =
   161        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, MFD_ALLOW_SEALING));
   162    int seals;
   163    ASSERT_THAT(seals = fcntl(memfd.get(), F_GET_SEALS), SyscallSucceeds());
   164    // No seals are set yet.
   165    EXPECT_EQ(0, seals);
   166  
   167    // Set a seal and check that we can get it back.
   168    ASSERT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_WRITE), SyscallSucceeds());
   169    EXPECT_THAT(fcntl(memfd.get(), F_GET_SEALS),
   170                SyscallSucceedsWithValue(F_SEAL_WRITE));
   171  
   172    // Set some more seals and verify.
   173    ASSERT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SHRINK),
   174                SyscallSucceeds());
   175    EXPECT_THAT(
   176        fcntl(memfd.get(), F_GET_SEALS),
   177        SyscallSucceedsWithValue(F_SEAL_WRITE | F_SEAL_GROW | F_SEAL_SHRINK));
   178  
   179    // Attempting to set a seal that is already set is a no-op.
   180    ASSERT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_WRITE), SyscallSucceeds());
   181    EXPECT_THAT(
   182        fcntl(memfd.get(), F_GET_SEALS),
   183        SyscallSucceedsWithValue(F_SEAL_WRITE | F_SEAL_GROW | F_SEAL_SHRINK));
   184  
   185    // Add remaining seals and verify.
   186    ASSERT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_SEAL), SyscallSucceeds());
   187    EXPECT_THAT(fcntl(memfd.get(), F_GET_SEALS),
   188                SyscallSucceedsWithValue(F_SEAL_WRITE | F_SEAL_GROW |
   189                                         F_SEAL_SHRINK | F_SEAL_SEAL));
   190  }
   191  
   192  // F_SEAL_GROW prevents a memfd from being grown using ftruncate.
   193  TEST(MemfdTest, SealGrowWithTruncate) {
   194    const FileDescriptor memfd =
   195        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, MFD_ALLOW_SEALING));
   196    ASSERT_THAT(ftruncate(memfd.get(), kPageSize), SyscallSucceeds());
   197    ASSERT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_GROW), SyscallSucceeds());
   198  
   199    // Try grow the memfd by 1 page.
   200    ASSERT_THAT(ftruncate(memfd.get(), kPageSize * 2),
   201                SyscallFailsWithErrno(EPERM));
   202  
   203    // Ftruncate calls that don't actually grow the memfd are allowed.
   204    ASSERT_THAT(ftruncate(memfd.get(), kPageSize), SyscallSucceeds());
   205    ASSERT_THAT(ftruncate(memfd.get(), kPageSize / 2), SyscallSucceeds());
   206  
   207    // After shrinking, growing back is not allowed.
   208    ASSERT_THAT(ftruncate(memfd.get(), kPageSize), SyscallFailsWithErrno(EPERM));
   209  }
   210  
   211  // F_SEAL_GROW prevents a memfd from being grown using the write syscall.
   212  TEST(MemfdTest, SealGrowWithWrite) {
   213    const FileDescriptor memfd =
   214        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, MFD_ALLOW_SEALING));
   215  
   216    // Initially, writing to the memfd succeeds.
   217    const std::vector<char> buf(kPageSize);
   218    EXPECT_THAT(write(memfd.get(), buf.data(), buf.size()),
   219                SyscallSucceedsWithValue(kPageSize));
   220  
   221    // Apply F_SEAL_GROW, subsequent writes which extend the memfd should fail.
   222    ASSERT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_GROW), SyscallSucceeds());
   223    EXPECT_THAT(write(memfd.get(), buf.data(), buf.size()),
   224                SyscallFailsWithErrno(EPERM));
   225  
   226    // However, zero-length writes are ok since they don't grow the memfd.
   227    EXPECT_THAT(write(memfd.get(), buf.data(), 0), SyscallSucceeds());
   228  
   229    // Writing to existing parts of the memfd is also ok.
   230    ASSERT_THAT(lseek(memfd.get(), 0, SEEK_SET), SyscallSucceeds());
   231    EXPECT_THAT(write(memfd.get(), buf.data(), buf.size()),
   232                SyscallSucceedsWithValue(kPageSize));
   233  
   234    // Returning the end of the file and writing still not allowed.
   235    EXPECT_THAT(write(memfd.get(), buf.data(), buf.size()),
   236                SyscallFailsWithErrno(EPERM));
   237  }
   238  
   239  // F_SEAL_GROW causes writes which partially extend off the current EOF to
   240  // partially succeed, up to the page containing the EOF.
   241  TEST(MemfdTest, SealGrowPartialWriteTruncated) {
   242    const FileDescriptor memfd =
   243        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, MFD_ALLOW_SEALING));
   244    ASSERT_THAT(ftruncate(memfd.get(), kPageSize), SyscallSucceeds());
   245    ASSERT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_GROW), SyscallSucceeds());
   246  
   247    // FD offset: 1 page, EOF: 1 page.
   248  
   249    ASSERT_THAT(lseek(memfd.get(), kPageSize * 3 / 4, SEEK_SET),
   250                SyscallSucceeds());
   251  
   252    // FD offset: 3/4 page. Writing a full page now should only write 1/4 page
   253    // worth of data. This partially succeeds because the first page is entirely
   254    // within the file and requires no growth, but attempting to write the final
   255    // 3/4 page would require growing the file.
   256    const std::vector<char> buf(kPageSize);
   257    EXPECT_THAT(write(memfd.get(), buf.data(), buf.size()),
   258                SyscallSucceedsWithValue(kPageSize / 4));
   259  }
   260  
   261  // F_SEAL_GROW causes writes which partially extend off the current EOF to fail
   262  // in its entirety if the only data written would be to the page containing the
   263  // EOF.
   264  TEST(MemfdTest, SealGrowPartialWriteTruncatedSamePage) {
   265    const FileDescriptor memfd =
   266        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, MFD_ALLOW_SEALING));
   267    ASSERT_THAT(ftruncate(memfd.get(), kPageSize * 3 / 4), SyscallSucceeds());
   268    ASSERT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_GROW), SyscallSucceeds());
   269  
   270    // EOF: 3/4 page, writing 1/2 page starting at 1/2 page would cause the file
   271    // to grow. Since this would require only the page containing the EOF to be
   272    // modified, the write is rejected entirely.
   273    const std::vector<char> buf(kPageSize / 2);
   274    EXPECT_THAT(pwrite(memfd.get(), buf.data(), buf.size(), kPageSize / 2),
   275                SyscallFailsWithErrno(EPERM));
   276  
   277    // However, writing up to EOF is fine.
   278    EXPECT_THAT(pwrite(memfd.get(), buf.data(), buf.size() / 2, kPageSize / 2),
   279                SyscallSucceedsWithValue(kPageSize / 4));
   280  }
   281  
   282  // F_SEAL_SHRINK prevents a memfd from being shrunk using ftruncate.
   283  TEST(MemfdTest, SealShrink) {
   284    const FileDescriptor memfd =
   285        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, MFD_ALLOW_SEALING));
   286    ASSERT_THAT(ftruncate(memfd.get(), kPageSize), SyscallSucceeds());
   287    ASSERT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_SHRINK),
   288                SyscallSucceeds());
   289  
   290    // Shrink by half a page.
   291    ASSERT_THAT(ftruncate(memfd.get(), kPageSize / 2),
   292                SyscallFailsWithErrno(EPERM));
   293  
   294    // Ftruncate calls that don't actually shrink the file are allowed.
   295    ASSERT_THAT(ftruncate(memfd.get(), kPageSize), SyscallSucceeds());
   296    ASSERT_THAT(ftruncate(memfd.get(), kPageSize * 2), SyscallSucceeds());
   297  
   298    // After growing, shrinking is still not allowed.
   299    ASSERT_THAT(ftruncate(memfd.get(), kPageSize), SyscallFailsWithErrno(EPERM));
   300  }
   301  
   302  // F_SEAL_WRITE prevents a memfd from being written to through a write
   303  // syscall.
   304  TEST(MemfdTest, SealWriteWithWrite) {
   305    const FileDescriptor memfd =
   306        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, MFD_ALLOW_SEALING));
   307    const std::vector<char> buf(kPageSize);
   308    ASSERT_THAT(write(memfd.get(), buf.data(), buf.size()),
   309                SyscallSucceedsWithValue(kPageSize));
   310    ASSERT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_WRITE), SyscallSucceeds());
   311  
   312    // Attemping to write at the end of the file fails.
   313    EXPECT_THAT(write(memfd.get(), buf.data(), 1), SyscallFailsWithErrno(EPERM));
   314  
   315    // Attemping to overwrite an existing part of the memfd fails.
   316    EXPECT_THAT(pwrite(memfd.get(), buf.data(), 1, 0),
   317                SyscallFailsWithErrno(EPERM));
   318    EXPECT_THAT(pwrite(memfd.get(), buf.data(), buf.size() / 2, kPageSize / 2),
   319                SyscallFailsWithErrno(EPERM));
   320    EXPECT_THAT(pwrite(memfd.get(), buf.data(), buf.size(), kPageSize / 2),
   321                SyscallFailsWithErrno(EPERM));
   322  
   323    // Zero-length writes however do not fail.
   324    EXPECT_THAT(write(memfd.get(), buf.data(), 0), SyscallSucceeds());
   325  }
   326  
   327  // F_SEAL_WRITE prevents a memfd from being written to through an mmap.
   328  TEST(MemfdTest, SealWriteWithMmap) {
   329    const FileDescriptor memfd =
   330        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, MFD_ALLOW_SEALING));
   331    const std::vector<char> buf(kPageSize);
   332    ASSERT_THAT(write(memfd.get(), buf.data(), buf.size()),
   333                SyscallSucceedsWithValue(kPageSize));
   334    ASSERT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_WRITE), SyscallSucceeds());
   335  
   336    // Can't create a shared mapping with writes sealed.
   337    void* ret = mmap(nullptr, kPageSize, PROT_WRITE, MAP_SHARED, memfd.get(), 0);
   338    EXPECT_EQ(ret, MAP_FAILED);
   339    EXPECT_EQ(errno, EPERM);
   340    ret = mmap(nullptr, kPageSize, PROT_READ, MAP_SHARED, memfd.get(), 0);
   341    EXPECT_EQ(ret, MAP_FAILED);
   342    EXPECT_EQ(errno, EPERM);
   343  
   344    // However, private mappings are ok.
   345    EXPECT_NO_ERRNO(Mmap(nullptr, kPageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE,
   346                         memfd.get(), 0));
   347  }
   348  
   349  // Adding F_SEAL_WRITE fails when there are outstanding writable mappings to a
   350  // memfd.
   351  TEST(MemfdTest, SealWriteWithOutstandingWritbleMapping) {
   352    const FileDescriptor memfd =
   353        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, MFD_ALLOW_SEALING));
   354    const std::vector<char> buf(kPageSize);
   355    ASSERT_THAT(write(memfd.get(), buf.data(), buf.size()),
   356                SyscallSucceedsWithValue(kPageSize));
   357  
   358    // Attempting to add F_SEAL_WRITE with active shared mapping with any set of
   359    // permissions fails.
   360  
   361    // Read-only shared mapping.
   362    {
   363      const Mapping m = ASSERT_NO_ERRNO_AND_VALUE(
   364          Mmap(nullptr, kPageSize, PROT_READ, MAP_SHARED, memfd.get(), 0));
   365      EXPECT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_WRITE),
   366                  SyscallFailsWithErrno(EBUSY));
   367    }
   368  
   369    // Write-only shared mapping.
   370    {
   371      const Mapping m = ASSERT_NO_ERRNO_AND_VALUE(
   372          Mmap(nullptr, kPageSize, PROT_WRITE, MAP_SHARED, memfd.get(), 0));
   373      EXPECT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_WRITE),
   374                  SyscallFailsWithErrno(EBUSY));
   375    }
   376  
   377    // Read-write shared mapping.
   378    {
   379      const Mapping m = ASSERT_NO_ERRNO_AND_VALUE(
   380          Mmap(nullptr, kPageSize, PROT_READ | PROT_WRITE, MAP_SHARED,
   381               memfd.get(), 0));
   382      EXPECT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_WRITE),
   383                  SyscallFailsWithErrno(EBUSY));
   384    }
   385  
   386    // F_SEAL_WRITE can be set with private mappings with any permissions.
   387    {
   388      const Mapping m = ASSERT_NO_ERRNO_AND_VALUE(
   389          Mmap(nullptr, kPageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE,
   390               memfd.get(), 0));
   391      EXPECT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_WRITE),
   392                  SyscallSucceeds());
   393    }
   394  }
   395  
   396  // When applying F_SEAL_WRITE fails due to outstanding writable mappings, any
   397  // additional seals passed to the same add seal call are also rejected.
   398  TEST(MemfdTest, NoPartialSealApplicationWhenWriteSealRejected) {
   399    const FileDescriptor memfd =
   400        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, MFD_ALLOW_SEALING));
   401    const Mapping m = ASSERT_NO_ERRNO_AND_VALUE(Mmap(
   402        nullptr, kPageSize, PROT_READ | PROT_WRITE, MAP_SHARED, memfd.get(), 0));
   403  
   404    // Try add some seals along with F_SEAL_WRITE. The seal application should
   405    // fail since there exists an active shared mapping.
   406    EXPECT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_WRITE | F_SEAL_GROW),
   407                SyscallFailsWithErrno(EBUSY));
   408  
   409    // None of the seals should be applied.
   410    EXPECT_THAT(fcntl(memfd.get(), F_GET_SEALS), SyscallSucceedsWithValue(0));
   411  }
   412  
   413  // Seals are inode level properties, and apply to all file descriptors referring
   414  // to a memfd.
   415  TEST(MemfdTest, SealsAreInodeLevelProperties) {
   416    const FileDescriptor memfd =
   417        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, MFD_ALLOW_SEALING));
   418    const FileDescriptor memfd2 = ASSERT_NO_ERRNO_AND_VALUE(memfd.Dup());
   419  
   420    // Add seal through the original memfd, and verify that it appears on the
   421    // dupped fd.
   422    ASSERT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_WRITE), SyscallSucceeds());
   423    EXPECT_THAT(fcntl(memfd2.get(), F_GET_SEALS),
   424                SyscallSucceedsWithValue(F_SEAL_WRITE));
   425  
   426    // Verify the seal actually applies to both fds.
   427    std::vector<char> buf(kPageSize);
   428    EXPECT_THAT(write(memfd.get(), buf.data(), buf.size()),
   429                SyscallFailsWithErrno(EPERM));
   430    EXPECT_THAT(write(memfd2.get(), buf.data(), buf.size()),
   431                SyscallFailsWithErrno(EPERM));
   432  
   433    // Seals are enforced on new FDs that are dupped after the seal is already
   434    // applied.
   435    const FileDescriptor memfd3 = ASSERT_NO_ERRNO_AND_VALUE(memfd2.Dup());
   436    EXPECT_THAT(write(memfd3.get(), buf.data(), buf.size()),
   437                SyscallFailsWithErrno(EPERM));
   438  
   439    // Try a new seal applied to one of the dupped fds.
   440    ASSERT_THAT(fcntl(memfd3.get(), F_ADD_SEALS, F_SEAL_GROW), SyscallSucceeds());
   441    EXPECT_THAT(ftruncate(memfd.get(), kPageSize), SyscallFailsWithErrno(EPERM));
   442    EXPECT_THAT(ftruncate(memfd2.get(), kPageSize), SyscallFailsWithErrno(EPERM));
   443    EXPECT_THAT(ftruncate(memfd3.get(), kPageSize), SyscallFailsWithErrno(EPERM));
   444  }
   445  
   446  // Tmpfs files also support seals, but are created with F_SEAL_SEAL.
   447  TEST(MemfdTest, TmpfsFilesHaveSealSeal) {
   448    std::string tmpdir = GetAbsoluteTestTmpdir();
   449    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(IsTmpfs(tmpdir.c_str())));
   450    const TempPath tmpfs_file =
   451        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileIn(tmpdir.c_str()));
   452    const FileDescriptor fd =
   453        ASSERT_NO_ERRNO_AND_VALUE(Open(tmpfs_file.path(), O_RDWR, 0644));
   454    EXPECT_THAT(fcntl(fd.get(), F_GET_SEALS),
   455                SyscallSucceedsWithValue(F_SEAL_SEAL));
   456  }
   457  
   458  // Can open a memfd from procfs and use as normal.
   459  TEST(MemfdTest, CanOpenFromProcfs) {
   460    const FileDescriptor memfd =
   461        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, MFD_ALLOW_SEALING));
   462  
   463    // Write a random page of data to the memfd via write(2).
   464    std::vector<char> buf(kPageSize);
   465    RandomizeBuffer(buf.data(), buf.size());
   466    ASSERT_THAT(write(memfd.get(), buf.data(), buf.size()),
   467                SyscallSucceedsWithValue(kPageSize));
   468  
   469    // Read back the same data from the fd obtained from procfs and verify.
   470    const FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(
   471        Open(absl::StrFormat("/proc/self/fd/%d", memfd.get()), O_RDWR));
   472    std::vector<char> buf2(kPageSize);
   473    EXPECT_THAT(pread(fd.get(), buf2.data(), buf2.size(), 0),
   474                SyscallSucceedsWithValue(kPageSize));
   475    EXPECT_EQ(buf, buf2);
   476  }
   477  
   478  // Test that memfd permissions are set up correctly to allow another process to
   479  // open it from procfs.
   480  TEST(MemfdTest, OtherProcessCanOpenFromProcfs) {
   481    const FileDescriptor memfd =
   482        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, MFD_ALLOW_SEALING));
   483    const auto memfd_path =
   484        absl::StrFormat("/proc/%d/fd/%d", getpid(), memfd.get());
   485    const auto rest = [&] {
   486      int fd = open(memfd_path.c_str(), O_RDWR);
   487      TEST_PCHECK(fd >= 0);
   488      TEST_PCHECK(close(fd) >= 0);
   489    };
   490    EXPECT_THAT(InForkedProcess(rest), IsPosixErrorOkAndHolds(0));
   491  }
   492  
   493  // Test that only files opened as writable can have seals applied to them.
   494  // Normally there's no way to specify file permissions on memfds, but we can
   495  // obtain a read-only memfd by opening the corresponding procfs fd entry as
   496  // read-only.
   497  TEST(MemfdTest, MemfdMustBeWritableToModifySeals) {
   498    const FileDescriptor memfd =
   499        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, MFD_ALLOW_SEALING));
   500  
   501    // Initially adding a seal works.
   502    EXPECT_THAT(fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_WRITE), SyscallSucceeds());
   503  
   504    // Re-open the memfd as read-only from procfs.
   505    const FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(
   506        Open(absl::StrFormat("/proc/self/fd/%d", memfd.get()), O_RDONLY));
   507  
   508    // Can't add seals through an unwritable fd.
   509    EXPECT_THAT(fcntl(fd.get(), F_ADD_SEALS, F_SEAL_GROW),
   510                SyscallFailsWithErrno(EPERM));
   511  }
   512  
   513  // Test that the memfd implementation internally tracks potentially writable
   514  // maps correctly.
   515  TEST(MemfdTest, MultipleWritableAndNonWritableRefsToSameFileRegion) {
   516    const FileDescriptor memfd =
   517        ASSERT_NO_ERRNO_AND_VALUE(MemfdCreate(kMemfdName, 0));
   518  
   519    // Populate with a random page of data.
   520    std::vector<char> buf(kPageSize);
   521    RandomizeBuffer(buf.data(), buf.size());
   522    ASSERT_THAT(write(memfd.get(), buf.data(), buf.size()),
   523                SyscallSucceedsWithValue(kPageSize));
   524  
   525    // Read-only map to the page. This should cause an initial mapping to be
   526    // created.
   527    Mapping m1 = ASSERT_NO_ERRNO_AND_VALUE(
   528        Mmap(nullptr, kPageSize, PROT_READ, MAP_PRIVATE, memfd.get(), 0));
   529  
   530    // Create a shared writable map to the page. This should cause the internal
   531    // mapping to become potentially writable.
   532    Mapping m2 = ASSERT_NO_ERRNO_AND_VALUE(Mmap(
   533        nullptr, kPageSize, PROT_READ | PROT_WRITE, MAP_SHARED, memfd.get(), 0));
   534  
   535    // Drop the read-only mapping first. If writable-ness isn't tracked correctly,
   536    // this can cause some misaccounting, which can trigger asserts internally.
   537    m1.reset();
   538    m2.reset();
   539  }
   540  
   541  }  // namespace
   542  }  // namespace testing
   543  }  // namespace gvisor