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

     1  // Copyright 2018 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/capability.h>
    18  #include <linux/magic.h>
    19  #include <sched.h>
    20  #include <stdio.h>
    21  #include <sys/eventfd.h>
    22  #include <sys/mman.h>
    23  #include <sys/mount.h>
    24  #include <sys/resource.h>
    25  #include <sys/signalfd.h>
    26  #include <sys/socket.h>
    27  #include <sys/stat.h>
    28  #include <sys/statfs.h>
    29  #include <sys/un.h>
    30  #include <sys/vfs.h>
    31  #include <unistd.h>
    32  
    33  #include <cerrno>
    34  #include <cmath>
    35  #include <cstdint>
    36  #include <cstdlib>
    37  #include <functional>
    38  #include <iostream>
    39  #include <memory>
    40  #include <ostream>
    41  #include <string>
    42  #include <tuple>
    43  #include <utility>
    44  #include <vector>
    45  
    46  #include "gmock/gmock.h"
    47  #include "gtest/gtest.h"
    48  #include "absl/container/flat_hash_map.h"
    49  #include "absl/strings/match.h"
    50  #include "absl/strings/numbers.h"
    51  #include "absl/strings/str_cat.h"
    52  #include "absl/strings/str_format.h"
    53  #include "absl/strings/str_split.h"
    54  #include "absl/strings/string_view.h"
    55  #include "absl/strings/substitute.h"
    56  #include "absl/time/clock.h"
    57  #include "absl/time/time.h"
    58  #include "test/util/capability_util.h"
    59  #include "test/util/cleanup.h"
    60  #include "test/util/eventfd_util.h"
    61  #include "test/util/file_descriptor.h"
    62  #include "test/util/fs_util.h"
    63  #include "test/util/linux_capability_util.h"
    64  #include "test/util/logging.h"
    65  #include "test/util/mount_util.h"
    66  #include "test/util/multiprocess_util.h"
    67  #include "test/util/posix_error.h"
    68  #include "test/util/save_util.h"
    69  #include "test/util/temp_path.h"
    70  #include "test/util/test_util.h"
    71  #include "test/util/thread_util.h"
    72  
    73  namespace gvisor {
    74  namespace testing {
    75  
    76  namespace {
    77  
    78  using ::testing::AnyOf;
    79  using ::testing::Contains;
    80  using ::testing::Pair;
    81  
    82  constexpr char kTmpfs[] = "tmpfs";
    83  
    84  TEST(MountTest, MountBadFilesystem) {
    85    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
    86  
    87    // Linux expects a valid target before it checks the file system name.
    88    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
    89    EXPECT_THAT(mount("", dir.path().c_str(), "foobar", 0, ""),
    90                SyscallFailsWithErrno(ENODEV));
    91  }
    92  
    93  TEST(MountTest, MountInvalidTarget) {
    94    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
    95  
    96    auto const dir = NewTempAbsPath();
    97    EXPECT_THAT(mount("", dir.c_str(), kTmpfs, 0, ""),
    98                SyscallFailsWithErrno(ENOENT));
    99  }
   100  
   101  TEST(MountTest, MountPermDenied) {
   102    // Clear CAP_SYS_ADMIN.
   103    AutoCapability cap(CAP_SYS_ADMIN, false);
   104  
   105    // Linux expects a valid target before checking capability.
   106    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   107    EXPECT_THAT(mount("", dir.path().c_str(), "", 0, ""),
   108                SyscallFailsWithErrno(EPERM));
   109  }
   110  
   111  TEST(MountTest, UmountPermDenied) {
   112    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   113  
   114    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   115    auto const mount =
   116        ASSERT_NO_ERRNO_AND_VALUE(Mount("", dir.path(), kTmpfs, 0, "", 0));
   117  
   118    // Drop privileges in another thread, so we can still unmount the mounted
   119    // directory.
   120    ScopedThread([&]() {
   121      EXPECT_NO_ERRNO(SetCapability(CAP_SYS_ADMIN, false));
   122      EXPECT_THAT(umount(dir.path().c_str()), SyscallFailsWithErrno(EPERM));
   123    });
   124  }
   125  
   126  TEST(MountTest, MountOverBusy) {
   127    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   128  
   129    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   130    auto const fd = ASSERT_NO_ERRNO_AND_VALUE(
   131        Open(JoinPath(dir.path(), "foo"), O_CREAT | O_RDWR, 0777));
   132  
   133    // Should be able to mount over a busy directory.
   134    ASSERT_NO_ERRNO_AND_VALUE(Mount("", dir.path(), kTmpfs, 0, "", 0));
   135  }
   136  
   137  TEST(MountTest, OpenFileBusy) {
   138    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   139  
   140    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   141    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   142        Mount("", dir.path(), kTmpfs, 0, "mode=0700", 0));
   143    auto const fd = ASSERT_NO_ERRNO_AND_VALUE(
   144        Open(JoinPath(dir.path(), "foo"), O_CREAT | O_RDWR, 0777));
   145  
   146    // An open file should prevent unmounting.
   147    EXPECT_THAT(umount(dir.path().c_str()), SyscallFailsWithErrno(EBUSY));
   148  }
   149  
   150  TEST(MountTest, UmountNoFollow) {
   151    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   152  
   153    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   154  
   155    auto const mountPoint = NewTempAbsPathInDir(dir.path());
   156    ASSERT_THAT(mkdir(mountPoint.c_str(), 0777), SyscallSucceeds());
   157  
   158    // Create a symlink in dir which will point to the actual mountpoint.
   159    const std::string symlinkInDir = NewTempAbsPathInDir(dir.path());
   160    EXPECT_THAT(symlink(mountPoint.c_str(), symlinkInDir.c_str()),
   161                SyscallSucceeds());
   162  
   163    // Create a symlink to the dir.
   164    const std::string symlinkToDir = NewTempAbsPath();
   165    EXPECT_THAT(symlink(dir.path().c_str(), symlinkToDir.c_str()),
   166                SyscallSucceeds());
   167  
   168    // Should fail with ELOOP when UMOUNT_NOFOLLOW is specified and the last
   169    // component is a symlink.
   170    auto mount = ASSERT_NO_ERRNO_AND_VALUE(
   171        Mount("", mountPoint, kTmpfs, 0, "mode=0700", 0));
   172    EXPECT_THAT(umount2(symlinkInDir.c_str(), UMOUNT_NOFOLLOW),
   173                SyscallFailsWithErrno(EINVAL));
   174    EXPECT_THAT(unlink(symlinkInDir.c_str()), SyscallSucceeds());
   175  
   176    // UMOUNT_NOFOLLOW should only apply to the last path component. A symlink in
   177    // non-last path component should be just fine.
   178    EXPECT_THAT(umount2(JoinPath(symlinkToDir, Basename(mountPoint)).c_str(),
   179                        UMOUNT_NOFOLLOW),
   180                SyscallSucceeds());
   181    mount.Release();
   182  }
   183  
   184  TEST(MountTest, UmountDetach) {
   185    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   186  
   187    // structure:
   188    //
   189    // dir (mount point)
   190    //   subdir
   191    //   file
   192    //
   193    // We show that we can walk around in the mount after detach-unmount dir.
   194    //
   195    // We show that even though dir is unreachable from outside the mount, we can
   196    // still reach dir's (former) parent!
   197    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   198  
   199    const struct stat before = ASSERT_NO_ERRNO_AND_VALUE(Stat(dir.path()));
   200    auto mount =
   201        ASSERT_NO_ERRNO_AND_VALUE(Mount("", dir.path(), kTmpfs, 0, "mode=0700",
   202                                        /* umountflags= */ MNT_DETACH));
   203    const struct stat after = ASSERT_NO_ERRNO_AND_VALUE(Stat(dir.path()));
   204    EXPECT_FALSE(before.st_dev == after.st_dev && before.st_ino == after.st_ino)
   205        << "mount point has device number " << before.st_dev
   206        << " and inode number " << before.st_ino << " before and after mount";
   207  
   208    // Create files in the new mount.
   209    constexpr char kContents[] = "no no no";
   210    auto const subdir =
   211        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir.path()));
   212    auto const file = ASSERT_NO_ERRNO_AND_VALUE(
   213        TempPath::CreateFileWith(dir.path(), kContents, 0777));
   214  
   215    auto const dir_fd =
   216        ASSERT_NO_ERRNO_AND_VALUE(Open(subdir.path(), O_RDONLY | O_DIRECTORY));
   217    auto const fd = ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDONLY));
   218  
   219    // Unmount the tmpfs.
   220    mount.Release()();
   221  
   222    // Inode numbers for gofer-accessed files may change across save/restore.
   223    //
   224    // For overlayfs, if xino option is not enabled and if all overlayfs layers do
   225    // not belong to the same filesystem then "the value of st_ino for directory
   226    // objects may not be persistent and could change even while the overlay
   227    // filesystem is mounted."  -- Documentation/filesystems/overlayfs.txt
   228    if (!IsRunningWithSaveRestore() &&
   229        !ASSERT_NO_ERRNO_AND_VALUE(IsOverlayfs(dir.path()))) {
   230      const struct stat after2 = ASSERT_NO_ERRNO_AND_VALUE(Stat(dir.path()));
   231      EXPECT_EQ(before.st_ino, after2.st_ino);
   232    }
   233  
   234    // Can still read file after unmounting.
   235    std::vector<char> buf(sizeof(kContents));
   236    EXPECT_THAT(ReadFd(fd.get(), buf.data(), buf.size()), SyscallSucceeds());
   237  
   238    // Walk to dir.
   239    auto const mounted_dir = ASSERT_NO_ERRNO_AND_VALUE(
   240        OpenAt(dir_fd.get(), "..", O_DIRECTORY | O_RDONLY));
   241    // Walk to dir/file.
   242    auto const fd_again = ASSERT_NO_ERRNO_AND_VALUE(
   243        OpenAt(mounted_dir.get(), std::string(Basename(file.path())), O_RDONLY));
   244  
   245    std::vector<char> buf2(sizeof(kContents));
   246    EXPECT_THAT(ReadFd(fd_again.get(), buf2.data(), buf2.size()),
   247                SyscallSucceeds());
   248    EXPECT_EQ(buf, buf2);
   249  
   250    // Walking outside the unmounted realm should still work, too!
   251    auto const dir_parent = ASSERT_NO_ERRNO_AND_VALUE(
   252        OpenAt(mounted_dir.get(), "..", O_DIRECTORY | O_RDONLY));
   253  }
   254  
   255  TEST(MountTest, UmountMountsStackedOnDot) {
   256    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   257    // Verify that unmounting at "." properly unmounts the mount at the top of
   258    // mount stack.
   259    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   260    TEST_CHECK_SUCCESS(chdir(dir.path().c_str()));
   261    const struct stat before = ASSERT_NO_ERRNO_AND_VALUE(Stat("."));
   262  
   263    TEST_CHECK_SUCCESS(mount("", dir.path().c_str(), kTmpfs, 0, "mode=0700"));
   264    TEST_CHECK_SUCCESS(mount("", dir.path().c_str(), kTmpfs, 0, "mode=0700"));
   265  
   266    // Unmount the second mount at "."
   267    TEST_CHECK_SUCCESS(umount2(".", MNT_DETACH));
   268  
   269    // Unmount the first mount at "."; this will fail if umount does not resolve
   270    // "." to the topmost mount.
   271    TEST_CHECK_SUCCESS(umount2(".", MNT_DETACH));
   272    const struct stat after2 = ASSERT_NO_ERRNO_AND_VALUE(Stat("."));
   273    EXPECT_TRUE(before.st_dev == after2.st_dev && before.st_ino == after2.st_ino);
   274  }
   275  
   276  TEST(MountTest, ActiveSubmountBusy) {
   277    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   278  
   279    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   280    auto const mount1 = ASSERT_NO_ERRNO_AND_VALUE(
   281        Mount("", dir.path(), kTmpfs, 0, "mode=0700", 0));
   282  
   283    auto const dir2 =
   284        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir.path()));
   285    auto const mount2 =
   286        ASSERT_NO_ERRNO_AND_VALUE(Mount("", dir2.path(), kTmpfs, 0, "", 0));
   287  
   288    // Since dir now has an active submount, should not be able to unmount.
   289    EXPECT_THAT(umount(dir.path().c_str()), SyscallFailsWithErrno(EBUSY));
   290  }
   291  
   292  TEST(MountTest, MountTmpfs) {
   293    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   294  
   295    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   296  
   297    // NOTE(b/129868551): Inode IDs are only stable across S/R if we have an open
   298    // FD for that inode. Since we are going to compare inode IDs below, get a
   299    // FileDescriptor for this directory here, which will be closed automatically
   300    // at the end of the test.
   301    auto const fd =
   302        ASSERT_NO_ERRNO_AND_VALUE(Open(dir.path(), O_DIRECTORY, O_RDONLY));
   303  
   304    const struct stat before = ASSERT_NO_ERRNO_AND_VALUE(Stat(dir.path()));
   305  
   306    {
   307      auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   308          Mount("", dir.path(), kTmpfs, 0, "mode=0700", 0));
   309  
   310      const struct stat s = ASSERT_NO_ERRNO_AND_VALUE(Stat(dir.path()));
   311      EXPECT_EQ(s.st_mode, S_IFDIR | 0700);
   312      EXPECT_FALSE(before.st_dev == s.st_dev && before.st_ino == s.st_ino)
   313          << "mount point has device number " << before.st_dev
   314          << " and inode number " << before.st_ino << " before and after mount";
   315  
   316      EXPECT_NO_ERRNO(Open(JoinPath(dir.path(), "foo"), O_CREAT | O_RDWR, 0777));
   317    }
   318  
   319    // Now that dir is unmounted again, we should have the old inode back.
   320    //
   321    // Inode numbers for gofer-accessed files may change across save/restore.
   322    //
   323    // For overlayfs, if xino option is not enabled and if all overlayfs layers do
   324    // not belong to the same filesystem then "the value of st_ino for directory
   325    // objects may not be persistent and could change even while the overlay
   326    // filesystem is mounted."  -- Documentation/filesystems/overlayfs.txt
   327    if (!IsRunningWithSaveRestore() &&
   328        !ASSERT_NO_ERRNO_AND_VALUE(IsOverlayfs(dir.path()))) {
   329      const struct stat after = ASSERT_NO_ERRNO_AND_VALUE(Stat(dir.path()));
   330      EXPECT_EQ(before.st_ino, after.st_ino);
   331    }
   332  }
   333  
   334  TEST(MountTest, MountTmpfsMagicValIgnored) {
   335    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   336  
   337    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   338  
   339    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   340        Mount("", dir.path(), kTmpfs, MS_MGC_VAL, "mode=0700", 0));
   341  }
   342  
   343  // Passing nullptr to data is equivalent to "".
   344  TEST(MountTest, NullData) {
   345    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   346  
   347    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   348  
   349    EXPECT_THAT(mount("", dir.path().c_str(), kTmpfs, 0, nullptr),
   350                SyscallSucceeds());
   351    EXPECT_THAT(umount2(dir.path().c_str(), 0), SyscallSucceeds());
   352  }
   353  
   354  TEST(MountTest, MountReadonly) {
   355    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   356  
   357    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   358    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   359        Mount("", dir.path(), kTmpfs, MS_RDONLY, "mode=0777", 0));
   360  
   361    const struct stat s = ASSERT_NO_ERRNO_AND_VALUE(Stat(dir.path()));
   362    EXPECT_EQ(s.st_mode, S_IFDIR | 0777);
   363  
   364    EXPECT_THAT(access(dir.path().c_str(), W_OK), SyscallFailsWithErrno(EROFS));
   365  
   366    std::string const filename = JoinPath(dir.path(), "foo");
   367    EXPECT_THAT(open(filename.c_str(), O_RDWR | O_CREAT, 0777),
   368                SyscallFailsWithErrno(EROFS));
   369  }
   370  
   371  PosixErrorOr<absl::Time> ATime(absl::string_view file) {
   372    struct stat s = {};
   373    if (stat(std::string(file).c_str(), &s) == -1) {
   374      return PosixError(errno, "stat failed");
   375    }
   376    return absl::TimeFromTimespec(s.st_atim);
   377  }
   378  
   379  TEST(MountTest, MountNoAtime) {
   380    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   381  
   382    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   383    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   384        Mount("", dir.path(), kTmpfs, MS_NOATIME, "mode=0777", 0));
   385  
   386    std::string const contents = "No no no, don't follow the instructions!";
   387    auto const file = ASSERT_NO_ERRNO_AND_VALUE(
   388        TempPath::CreateFileWith(dir.path(), contents, 0777));
   389  
   390    absl::Time const before = ASSERT_NO_ERRNO_AND_VALUE(ATime(file.path()));
   391  
   392    // Reading from the file should change the atime, but the MS_NOATIME flag
   393    // should prevent that.
   394    auto const fd = ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR));
   395    char buf[100];
   396    int read_n;
   397    ASSERT_THAT(read_n = read(fd.get(), buf, sizeof(buf)), SyscallSucceeds());
   398    EXPECT_EQ(std::string(buf, read_n), contents);
   399  
   400    absl::Time const after = ASSERT_NO_ERRNO_AND_VALUE(ATime(file.path()));
   401  
   402    // Expect that atime hasn't changed.
   403    EXPECT_EQ(before, after);
   404  }
   405  
   406  TEST(MountTest, MountWithStrictAtime) {
   407    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   408  
   409    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   410    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(Mount(
   411        "", dir.path(), kTmpfs, MS_NOATIME | MS_STRICTATIME, "mode=0777", 0));
   412  
   413    std::string const contents = "No no no, don't follow the instructions!";
   414    auto const file = ASSERT_NO_ERRNO_AND_VALUE(
   415        TempPath::CreateFileWith(dir.path(), contents, 0777));
   416  
   417    absl::Time const before = ASSERT_NO_ERRNO_AND_VALUE(ATime(file.path()));
   418  
   419    absl::SleepFor(absl::Milliseconds(100));
   420  
   421    // MS_STRICTATIME should override MS_NOATIME and update the file's atime.
   422    auto const fd = ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR));
   423    char buf[100];
   424    int read_n;
   425    ASSERT_THAT(read_n = read(fd.get(), buf, sizeof(buf)), SyscallSucceeds());
   426    EXPECT_EQ(std::string(buf, read_n), contents);
   427  
   428    absl::Time const after = ASSERT_NO_ERRNO_AND_VALUE(ATime(file.path()));
   429  
   430    // The after atime is expected to be larger than the before atime.
   431    EXPECT_LT(before, after);
   432  }
   433  
   434  TEST(MountTest, MountNoExec) {
   435    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   436  
   437    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   438    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   439        Mount("", dir.path(), kTmpfs, MS_NOEXEC, "mode=0777", 0));
   440  
   441    std::string const contents = "No no no, don't follow the instructions!";
   442    auto const file = ASSERT_NO_ERRNO_AND_VALUE(
   443        TempPath::CreateFileWith(dir.path(), contents, 0777));
   444  
   445    int execve_errno;
   446    ASSERT_NO_ERRNO_AND_VALUE(
   447        ForkAndExec(file.path(), {}, {}, nullptr, &execve_errno));
   448    EXPECT_EQ(execve_errno, EACCES);
   449  }
   450  
   451  TEST(MountTest, RenameRemoveMountPoint) {
   452    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   453  
   454    auto const dir_parent = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   455    auto const dir =
   456        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir_parent.path()));
   457    auto const new_dir = NewTempAbsPath();
   458  
   459    auto const mount =
   460        ASSERT_NO_ERRNO_AND_VALUE(Mount("", dir.path(), kTmpfs, 0, "", 0));
   461  
   462    ASSERT_THAT(rename(dir.path().c_str(), new_dir.c_str()),
   463                SyscallFailsWithErrno(EBUSY));
   464  
   465    ASSERT_THAT(rmdir(dir.path().c_str()), SyscallFailsWithErrno(EBUSY));
   466  }
   467  
   468  TEST(MountTest, MountInfo) {
   469    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   470  
   471    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   472    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   473        Mount("", dir.path(), kTmpfs, MS_NOEXEC, "mode=0123", 0));
   474    const std::vector<ProcMountsEntry> mounts =
   475        ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountsEntries());
   476    for (const auto& e : mounts) {
   477      if (e.mount_point == dir.path()) {
   478        EXPECT_EQ(e.fstype, kTmpfs);
   479        auto mopts = ParseMountOptions(e.mount_opts);
   480        EXPECT_THAT(mopts, AnyOf(Contains(Pair("mode", "0123")),
   481                                 Contains(Pair("mode", "123"))));
   482      }
   483    }
   484  
   485    const std::vector<ProcMountInfoEntry> mountinfo =
   486        ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountInfoEntries());
   487  
   488    for (auto const& e : mountinfo) {
   489      if (e.mount_point == dir.path()) {
   490        EXPECT_EQ(e.fstype, kTmpfs);
   491        auto mopts = ParseMountOptions(e.super_opts);
   492        EXPECT_THAT(mopts, AnyOf(Contains(Pair("mode", "0123")),
   493                                 Contains(Pair("mode", "123"))));
   494      }
   495    }
   496  }
   497  
   498  TEST(MountTest, TmpfsSizeRoundUpSinglePageSize) {
   499    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   500    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   501    auto tmpfs_size_opt = absl::StrCat("size=", kPageSize / 2);
   502    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   503        Mount("", dir.path(), kTmpfs, 0, tmpfs_size_opt, 0));
   504    auto fd = ASSERT_NO_ERRNO_AND_VALUE(
   505        Open(JoinPath(dir.path(), "foo"), O_CREAT | O_RDWR, 0777));
   506  
   507    // Check that it starts at size zero.
   508    struct stat buf;
   509    ASSERT_THAT(fstat(fd.get(), &buf), SyscallSucceeds());
   510    EXPECT_EQ(buf.st_size, 0);
   511  
   512    // Grow to 1 Page Size.
   513    ASSERT_THAT(fallocate(fd.get(), 0, 0, kPageSize), SyscallSucceeds());
   514    ASSERT_THAT(fstat(fd.get(), &buf), SyscallSucceeds());
   515    EXPECT_EQ(buf.st_size, kPageSize);
   516  
   517    // Grow to size beyond tmpfs allocated bytes.
   518    ASSERT_THAT(fallocate(fd.get(), 0, 0, kPageSize + 1),
   519                SyscallFailsWithErrno(ENOSPC));
   520    ASSERT_THAT(fstat(fd.get(), &buf), SyscallSucceeds());
   521    EXPECT_EQ(buf.st_size, kPageSize);
   522  }
   523  
   524  TEST(MountTest, TmpfsSizeAllocationMultiplePages) {
   525    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   526    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   527    auto page_multiple = 2;
   528    auto size = kPageSize * page_multiple;
   529    auto tmpfs_size_opt = absl::StrCat("size=", size);
   530    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   531        Mount("", dir.path(), kTmpfs, 0, tmpfs_size_opt, 0));
   532    auto fd = ASSERT_NO_ERRNO_AND_VALUE(
   533        Open(JoinPath(dir.path(), "foo"), O_CREAT | O_RDWR, 0777));
   534  
   535    // Check that it starts at size zero.
   536    struct stat buf;
   537    ASSERT_THAT(fstat(fd.get(), &buf), SyscallSucceeds());
   538    EXPECT_EQ(buf.st_size, 0);
   539  
   540    // Ensure fallocate does not allow partial allocations.
   541    ASSERT_THAT(fallocate(fd.get(), 0, 0, size + 1),
   542                SyscallFailsWithErrno(ENOSPC));
   543    ASSERT_THAT(fstat(fd.get(), &buf), SyscallSucceeds());
   544    EXPECT_EQ(buf.st_size, 0);
   545  
   546    // Grow to multiple of page size.
   547    ASSERT_THAT(fallocate(fd.get(), 0, 0, size), SyscallSucceeds());
   548    ASSERT_THAT(fstat(fd.get(), &buf), SyscallSucceeds());
   549    EXPECT_EQ(buf.st_size, size);
   550  
   551    // Grow to beyond tmpfs size bytes.
   552    ASSERT_THAT(fallocate(fd.get(), 0, 0, size + 1),
   553                SyscallFailsWithErrno(ENOSPC));
   554    ASSERT_THAT(fstat(fd.get(), &buf), SyscallSucceeds());
   555    EXPECT_EQ(buf.st_size, size);
   556  }
   557  
   558  TEST(MountTest, TmpfsSizeMoreThanSinglePgSZMultipleFiles) {
   559    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   560    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   561    auto const page_multiple = 10;
   562    auto const size = kPageSize * page_multiple;
   563    auto tmpfs_size_opt = absl::StrCat("size=", size);
   564    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   565        Mount("", dir.path(), kTmpfs, 0, tmpfs_size_opt, 0));
   566    for (int i = 0; i < page_multiple; i++) {
   567      auto fd = ASSERT_NO_ERRNO_AND_VALUE(Open(
   568          JoinPath(dir.path(), absl::StrCat("foo_", i)), O_CREAT | O_RDWR, 0777));
   569      // Create buffer & Grow to 100 bytes.
   570      struct stat buf;
   571      ASSERT_THAT(fstat(fd.get(), &buf), SyscallSucceeds());
   572      ASSERT_THAT(fallocate(fd.get(), 0, 0, 100), SyscallSucceeds());
   573      ASSERT_THAT(fstat(fd.get(), &buf), SyscallSucceeds());
   574      EXPECT_EQ(buf.st_size, 100);
   575    }
   576    auto fd = ASSERT_NO_ERRNO_AND_VALUE(
   577        Open(JoinPath(dir.path(), absl::StrCat("foo_", page_multiple + 1)),
   578             O_CREAT | O_RDWR, 0777));
   579    // Grow to beyond tmpfs size bytes after exhausting the size.
   580    ASSERT_THAT(fallocate(fd.get(), 0, 0, kPageSize),
   581                SyscallFailsWithErrno(ENOSPC));
   582  }
   583  
   584  TEST(MountTest, TmpfsSizeFtruncate) {
   585    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   586    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   587    auto tmpfs_size_opt = absl::StrCat("size=", kPageSize);
   588    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   589        Mount("", dir.path(), kTmpfs, 0, tmpfs_size_opt, 0));
   590    auto fd = ASSERT_NO_ERRNO_AND_VALUE(
   591        Open(JoinPath(dir.path(), "foo"), O_CREAT | O_RDWR, 0777));
   592    ASSERT_THAT(fallocate(fd.get(), 0, 0, kPageSize), SyscallSucceeds());
   593    struct stat status;
   594    ASSERT_THAT(fstat(fd.get(), &status), SyscallSucceeds());
   595    EXPECT_EQ(status.st_size, kPageSize);
   596  
   597    ASSERT_THAT(ftruncate(fd.get(), kPageSize + 1), SyscallSucceeds());
   598    ASSERT_THAT(fstat(fd.get(), &status), SyscallSucceeds());
   599    EXPECT_EQ(status.st_size, kPageSize + 1);
   600  
   601    ASSERT_THAT(ftruncate(fd.get(), 0), SyscallSucceeds());
   602    ASSERT_THAT(fstat(fd.get(), &status), SyscallSucceeds());
   603    EXPECT_EQ(status.st_size, 0);
   604  
   605    ASSERT_THAT(fallocate(fd.get(), 0, 0, kPageSize), SyscallSucceeds());
   606    ASSERT_THAT(fstat(fd.get(), &status), SyscallSucceeds());
   607    EXPECT_EQ(status.st_size, kPageSize);
   608  }
   609  
   610  // Test shows directory does not take up any pages.
   611  TEST(MountTest, TmpfsDirectoryAllocCheck) {
   612    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   613    auto const dir_parent = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   614  
   615    auto tmpfs_size_opt = absl::StrCat("size=", kPageSize);
   616    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   617        Mount("", dir_parent.path(), kTmpfs, 0, tmpfs_size_opt, 0));
   618  
   619    auto const dir_tmp =
   620        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir_parent.path()));
   621  
   622    // Creating only 1 regular file allocates 1 page size.
   623    auto fd = ASSERT_NO_ERRNO_AND_VALUE(
   624        Open(JoinPath(dir_parent.path(), "foo"), O_CREAT | O_RDWR, 0777));
   625  
   626    // Check that it starts at size zero.
   627    struct stat buf;
   628    ASSERT_THAT(fstat(fd.get(), &buf), SyscallSucceeds());
   629    EXPECT_EQ(buf.st_size, 0);
   630  
   631    // Grow to 1 Page Size.
   632    ASSERT_THAT(fallocate(fd.get(), 0, 0, kPageSize), SyscallSucceeds());
   633    ASSERT_THAT(fstat(fd.get(), &buf), SyscallSucceeds());
   634    EXPECT_EQ(buf.st_size, kPageSize);
   635  
   636    // Grow to beyond 1 Page Size.
   637    ASSERT_THAT(fallocate(fd.get(), 0, 0, kPageSize + 1),
   638                SyscallFailsWithErrno(ENOSPC));
   639  }
   640  
   641  // Tests memory allocation for symlinks.
   642  TEST(MountTest, TmpfsSymlinkAllocCheck) {
   643    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   644    auto const dir_parent = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   645  
   646    auto tmpfs_size_opt = absl::StrCat("size=", kPageSize);
   647    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   648        Mount("", dir_parent.path(), kTmpfs, 0, tmpfs_size_opt, 0));
   649  
   650    const int target_size = 128;
   651    auto target = std::string(target_size - 1, 'a');
   652    auto pathname = JoinPath(dir_parent.path(), "foo1");
   653    EXPECT_THAT(symlink(target.c_str(), pathname.c_str()), SyscallSucceeds());
   654  
   655    target = std::string(target_size, 'a');
   656    pathname = absl::StrCat(dir_parent.path(), "/foo2");
   657    EXPECT_THAT(symlink(target.c_str(), pathname.c_str()), SyscallSucceeds());
   658  
   659    target = std::string(target_size, 'a');
   660    pathname = absl::StrCat(dir_parent.path(), "/foo3");
   661    EXPECT_THAT(symlink(target.c_str(), pathname.c_str()),
   662                SyscallFailsWithErrno(ENOSPC));
   663  
   664    target = std::string(target_size - 1, 'a');
   665    pathname = absl::StrCat(dir_parent.path(), "/foo4");
   666    EXPECT_THAT(symlink(target.c_str(), pathname.c_str()), SyscallSucceeds());
   667    EXPECT_THAT(unlink(pathname.c_str()), SyscallSucceeds());
   668  }
   669  
   670  // Tests memory unallocation for symlinks.
   671  TEST(MountTest, TmpfsSymlinkUnallocCheck) {
   672    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   673    auto const dir_parent = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   674  
   675    auto tmpfs_size_opt = absl::StrCat("size=", kPageSize);
   676    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   677        Mount("", dir_parent.path(), kTmpfs, 0, tmpfs_size_opt, 0));
   678  
   679    const int target_size = 128;
   680    auto pathname = JoinPath(dir_parent.path(), "foo1");
   681    auto target = std::string(target_size, 'a');
   682    EXPECT_THAT(symlink(target.c_str(), pathname.c_str()), SyscallSucceeds());
   683    auto const fd =
   684        ASSERT_NO_ERRNO_AND_VALUE(Open(pathname, O_CREAT | O_RDWR, 0777));
   685    ASSERT_THAT(fallocate(fd.get(), 0, 0, kPageSize),
   686                SyscallFailsWithErrno(ENOSPC));
   687    EXPECT_THAT(unlink(pathname.c_str()), SyscallSucceeds());
   688    ASSERT_THAT(fallocate(fd.get(), 0, 0, kPageSize), SyscallSucceeds());
   689  }
   690  
   691  // Tests memory allocation for Hard Links is not double allocated.
   692  TEST(MountTest, TmpfsHardLinkAllocCheck) {
   693    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   694    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   695    auto tmpfs_size_opt = absl::StrCat("size=", kPageSize);
   696    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   697        Mount("", dir.path(), kTmpfs, 0, tmpfs_size_opt, 0));
   698    const std::string fileOne = JoinPath(dir.path(), "foo1");
   699    const std::string fileTwo = JoinPath(dir.path(), "foo2");
   700    auto const fd =
   701        ASSERT_NO_ERRNO_AND_VALUE(Open(fileOne, O_CREAT | O_RDWR, 0777));
   702    EXPECT_THAT(link(fileOne.c_str(), fileTwo.c_str()), SyscallSucceeds());
   703  
   704    // Check that it starts at size zero.
   705    struct stat buf;
   706    ASSERT_THAT(fstat(fd.get(), &buf), SyscallSucceeds());
   707    EXPECT_EQ(buf.st_size, 0);
   708  
   709    // Grow to 1 Page Size.
   710    ASSERT_THAT(fallocate(fd.get(), 0, 0, kPageSize), SyscallSucceeds());
   711    ASSERT_THAT(fstat(fd.get(), &buf), SyscallSucceeds());
   712    EXPECT_EQ(buf.st_size, kPageSize);
   713  
   714    // Grow to size beyond tmpfs allocated bytes.
   715    ASSERT_THAT(fallocate(fd.get(), 0, 0, kPageSize + 1),
   716                SyscallFailsWithErrno(ENOSPC));
   717    ASSERT_THAT(fstat(fd.get(), &buf), SyscallSucceeds());
   718    EXPECT_EQ(buf.st_size, kPageSize);
   719    EXPECT_THAT(unlink(fileTwo.c_str()), SyscallSucceeds());
   720    EXPECT_THAT(unlink(fileOne.c_str()), SyscallSucceeds());
   721  }
   722  
   723  // Tests memory allocation for empty size.
   724  TEST(MountTest, TmpfsEmptySizeAllocCheck) {
   725    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   726    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   727    ASSERT_THAT(mount("", dir.path().c_str(), kTmpfs, 0, "size"),
   728                SyscallFailsWithErrno(EINVAL));
   729  }
   730  
   731  TEST(MountTest, TmpfsUnlinkRegularFileAllocCheck) {
   732    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   733    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   734    auto tmpfs_size_opt = absl::StrCat("size=", kPageSize);
   735    const int kTruncateSize = 2 * kPageSize;
   736    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   737        Mount("", dir.path(), kTmpfs, 0, tmpfs_size_opt, 0));
   738    const std::string fileOne = JoinPath(dir.path(), "foo1");
   739    auto fd = ASSERT_NO_ERRNO_AND_VALUE(Open(fileOne, O_CREAT | O_RDWR, 0777));
   740    EXPECT_THAT(unlink(fileOne.c_str()), SyscallSucceeds());
   741    EXPECT_THAT(ftruncate(fd.get(), kTruncateSize), SyscallSucceeds());
   742  }
   743  
   744  TEST(MountTest, TmpfsSizePartialWriteSinglePage) {
   745    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   746    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   747    auto tmpfs_size_opt = absl::StrCat("size=", kPageSize);
   748    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   749        Mount("", dir.path(), kTmpfs, 0, tmpfs_size_opt, 0));
   750  
   751    const std::string fileOne = JoinPath(dir.path(), "foo1");
   752    auto fd = ASSERT_NO_ERRNO_AND_VALUE(Open(fileOne, O_CREAT | O_RDWR, 0777));
   753    lseek(fd.get(), kPageSize - 2, SEEK_SET);
   754    char buf[4];
   755    EXPECT_THAT(write(fd.get(), buf, 4), SyscallSucceedsWithValue(2));
   756    EXPECT_THAT(write(fd.get(), buf, 4), SyscallFailsWithErrno(ENOSPC));
   757  }
   758  
   759  TEST(MountTest, TmpfsSizePartialWriteMultiplePages) {
   760    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   761    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   762    auto tmpfs_size_opt = absl::StrCat("size=", 3 * kPageSize);
   763    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   764        Mount("", dir.path(), kTmpfs, 0, tmpfs_size_opt, 0));
   765  
   766    const std::string fileOne = JoinPath(dir.path(), "foo1");
   767    auto fd = ASSERT_NO_ERRNO_AND_VALUE(Open(fileOne, O_CREAT | O_RDWR, 0777));
   768    lseek(fd.get(), kPageSize, SEEK_SET);
   769    std::vector<char> buf(kPageSize + 2);
   770    EXPECT_THAT(write(fd.get(), buf.data(), 4), SyscallSucceedsWithValue(4));
   771    struct stat status;
   772    ASSERT_THAT(fstat(fd.get(), &status), SyscallSucceeds());
   773    EXPECT_EQ(status.st_size, kPageSize + 4);
   774    EXPECT_THAT(write(fd.get(), buf.data(), 1), SyscallSucceedsWithValue(1));
   775  
   776    // Writing with size exactly until the end of page boundary.
   777    EXPECT_THAT(write(fd.get(), buf.data(), kPageSize - 5),
   778                SyscallSucceedsWithValue(kPageSize - 5));
   779  
   780    EXPECT_THAT(write(fd.get(), buf.data(), 1), SyscallSucceedsWithValue(1));
   781    // Writing with size more than page end & having extra page available as well.
   782    EXPECT_THAT(write(fd.get(), buf.data(), kPageSize + 1),
   783                SyscallSucceedsWithValue(kPageSize + 1));
   784  
   785    // Writing with size more than page end & having no page available.
   786    EXPECT_THAT(write(fd.get(), buf.data(), kPageSize + 1),
   787                SyscallSucceedsWithValue(kPageSize - 2));
   788    EXPECT_THAT(write(fd.get(), buf.data(), 1), SyscallFailsWithErrno(ENOSPC));
   789  }
   790  
   791  TEST(MountTest, TmpfsSizeMmap) {
   792    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   793    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   794    auto tmpfs_size_opt = absl::StrCat("size=", kPageSize);
   795    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   796        Mount("", dir.path(), kTmpfs, 0, tmpfs_size_opt, 0));
   797    const std::string fileOne = JoinPath(dir.path(), "foo");
   798    auto fd = ASSERT_NO_ERRNO_AND_VALUE(Open(fileOne, O_CREAT | O_RDWR, 0777));
   799    EXPECT_THAT(ftruncate(fd.get(), 2 * kPageSize), SyscallSucceeds());
   800    void* addr = mmap(NULL, 2 * kPageSize, PROT_READ, MAP_PRIVATE, fd.get(), 0);
   801    EXPECT_NE(addr, MAP_FAILED);
   802    // Access memory so that the first page to page fault occurs and is allocated.
   803    char data = ((char*)addr)[kPageSize - 2];
   804    EXPECT_EQ(data, 0);
   805    std::vector<char> in(kPageSize + 2);
   806    // Access memory such that it causes the second page to page fault. The page
   807    // fault should fail due to hitting tmpfs size limit which should cause
   808    // SIGBUS signal.
   809    EXPECT_EXIT(memcpy(in.data(), reinterpret_cast<char*>(addr), kPageSize + 2),
   810                ::testing::KilledBySignal(SIGBUS), "");
   811    EXPECT_THAT(munmap(addr, 2 * kPageSize), SyscallSucceeds());
   812  }
   813  
   814  TEST(MountTest, SimpleBind) {
   815    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   816  
   817    auto const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   818    auto const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   819    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   820        Mount("", dir1.path(), kTmpfs, 0, "mode=0123", 0));
   821    auto const child1 =
   822        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir1.path()));
   823    auto const child2 =
   824        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir1.path()));
   825    auto const bind_mount = Mount(dir1.path(), dir2.path(), "", MS_BIND, "", 0);
   826  
   827    // Write to child1 in dir1.
   828    const std::string filename = "foo.txt";
   829    const std::string contents = "barbaz";
   830    ASSERT_NO_ERRNO(
   831        CreateWithContents(JoinPath(child1.path(), filename), contents, 0666));
   832    // Verify both directories have the same nodes.
   833    std::vector<std::string> child_names = {std::string(Basename(child1.path())),
   834                                            std::string(Basename(child2.path()))};
   835    ASSERT_NO_ERRNO(DirContains(dir1.path(), child_names, {}));
   836    ASSERT_NO_ERRNO(DirContains(dir2.path(), child_names, {}));
   837  
   838    const std::string dir1_filepath =
   839        JoinPath(dir1.path(), Basename(child1.path()), filename);
   840    const std::string dir2_filepath =
   841        JoinPath(dir2.path(), Basename(child1.path()), filename);
   842  
   843    std::string output;
   844    ASSERT_NO_ERRNO(GetContents(dir1_filepath, &output));
   845    EXPECT_EQ(output, contents);
   846    ASSERT_NO_ERRNO(GetContents(dir2_filepath, &output));
   847    EXPECT_EQ(output, contents);
   848  }
   849  
   850  TEST(MountTest, BindToSelf) {
   851    // Test that we can turn a normal directory into a mount with MS_BIND.
   852    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   853    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   854  
   855    const std::vector<ProcMountsEntry> mounts_before =
   856        ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountsEntries());
   857    for (const auto& e : mounts_before) {
   858      ASSERT_NE(e.mount_point, dir.path());
   859    }
   860  
   861    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
   862        Mount(dir.path(), dir.path(), "", MS_BIND, "", 0));
   863  
   864    const std::vector<ProcMountsEntry> mounts_after =
   865        ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountsEntries());
   866    bool found = false;
   867    for (const auto& e : mounts_after) {
   868      if (e.mount_point == dir.path()) {
   869        found = true;
   870      }
   871    }
   872    ASSERT_TRUE(found);
   873  }
   874  
   875  TEST(MountTest, MaxMounts) {
   876    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   877  
   878    auto const parent = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   879    ASSERT_THAT(mount("", parent.path().c_str(), kTmpfs, 0, ""),
   880                SyscallSucceeds());
   881    auto const dir =
   882        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(parent.path()));
   883    ASSERT_THAT(
   884        mount(dir.path().c_str(), dir.path().c_str(), nullptr, MS_BIND, nullptr),
   885        SyscallSucceeds());
   886    ASSERT_THAT(mount("", dir.path().c_str(), "", MS_SHARED, ""),
   887                SyscallSucceeds());
   888  
   889    // Each bind mount doubles the number of mounts in the peer group. The number
   890    // of binds we can do before failing is log2(max_mounts-num_current_mounts).
   891    int mount_max = 10000;
   892    bool mount_max_exists =
   893        ASSERT_NO_ERRNO_AND_VALUE(Exists("/proc/sys/fs/mount-max"));
   894    if (mount_max_exists) {
   895      std::string mount_max_string;
   896      ASSERT_NO_ERRNO(GetContents("/proc/sys/fs/mount-max", &mount_max_string));
   897      ASSERT_TRUE(absl::SimpleAtoi(mount_max_string, &mount_max));
   898    }
   899  
   900    const std::vector<ProcMountInfoEntry> mounts =
   901        ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountInfoEntries());
   902    int num_binds = static_cast<int>(std::log2(mount_max - mounts.size()));
   903  
   904    for (int i = 0; i < num_binds; i++) {
   905      ASSERT_THAT(mount(dir.path().c_str(), dir.path().c_str(), nullptr, MS_BIND,
   906                        nullptr),
   907                  SyscallSucceeds());
   908    }
   909    ASSERT_THAT(
   910        mount(dir.path().c_str(), dir.path().c_str(), nullptr, MS_BIND, nullptr),
   911        SyscallFailsWithErrno(ENOSPC));
   912    umount2(parent.path().c_str(), MNT_DETACH);
   913  }
   914  
   915  TEST(MountTest, PropagateToSameMountpointStacksMounts) {
   916    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   917    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   918    auto const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   919    auto const mnt = ASSERT_NO_ERRNO_AND_VALUE(Mount(
   920        dir.path().c_str(), dir.path().c_str(), "", MS_BIND, "", MNT_DETACH));
   921    auto const child =
   922        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir.path()));
   923    ASSERT_THAT(mount(child.path().c_str(), child.path().c_str(), "", MS_BIND, 0),
   924                SyscallSucceeds());
   925    ASSERT_THAT(mount("", dir.path().c_str(), "", MS_SHARED, 0),
   926                SyscallSucceeds());
   927    auto const mnt2 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
   928        dir.path().c_str(), dir2.path().c_str(), "", MS_BIND, "", MNT_DETACH));
   929  
   930    std::string dir2_child_path = JoinPath(dir2.path(), Basename(child.path()));
   931    ASSERT_THAT(
   932        mount(dir2_child_path.c_str(), dir2_child_path.c_str(), "", MS_BIND, 0),
   933        SyscallSucceeds());
   934  
   935    // Check that mounts at the child mount point have distinct parents.
   936    std::vector<ProcMountInfoEntry> mounts =
   937        ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountInfoEntries());
   938    uint64_t parent_id = 0;
   939    for (auto& minfo : mounts) {
   940      if (minfo.mount_point == child.path()) {
   941        if (parent_id == 0) {
   942          parent_id = minfo.parent_id;
   943        } else {
   944          EXPECT_NE(parent_id, minfo.parent_id);
   945        }
   946      }
   947    }
   948  }
   949  
   950  TEST(MountTest, UmountReparentsCoveredMounts) {
   951    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   952    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   953    auto const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   954    auto const mnt = ASSERT_NO_ERRNO_AND_VALUE(
   955        Mount("", dir.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
   956    ASSERT_THAT(mount("", dir.path().c_str(), "", MS_SHARED, 0),
   957                SyscallSucceeds());
   958    auto const child =
   959        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir.path()));
   960    ASSERT_THAT(mount("", child.path().c_str(), kTmpfs, 0, 0), SyscallSucceeds());
   961    auto const mnt2 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
   962        dir.path().c_str(), dir2.path().c_str(), "", MS_BIND, "", MNT_DETACH));
   963  
   964    std::string dir2_child_path = JoinPath(dir2.path(), Basename(child.path()));
   965    ASSERT_THAT(mount("", dir2_child_path.c_str(), kTmpfs, 0, 0),
   966                SyscallSucceeds());
   967  
   968    umount2(dir2_child_path.c_str(), MNT_DETACH);
   969  
   970    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
   971    ASSERT_FALSE(optionals[child.path()].empty());
   972    EXPECT_NE(optionals[child.path()][0].shared, 0);
   973    EXPECT_TRUE(optionals[dir2_child_path].empty());
   974  }
   975  
   976  // Tests that it is possible to make a shared mount.
   977  TEST(MountTest, MakeShared) {
   978    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   979  
   980    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   981    auto const mnt = ASSERT_NO_ERRNO_AND_VALUE(
   982        Mount("", dir.path().c_str(), kTmpfs, 0, "", 0));
   983    ASSERT_THAT(mount("", dir.path().c_str(), "", MS_SHARED, 0),
   984                SyscallSucceeds());
   985  
   986    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
   987    ASSERT_FALSE(optionals[dir.path()].empty());
   988    EXPECT_NE(optionals[dir.path()][0].shared, 0);
   989  }
   990  
   991  // Tests that shared mounts have different group IDs.
   992  TEST(MountTest, MakeMultipleShared) {
   993    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   994  
   995    auto const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   996    auto const mount1 =
   997        ASSERT_NO_ERRNO_AND_VALUE(Mount("", dir1.path(), kTmpfs, 0, "", 0));
   998    ASSERT_THAT(mount("", dir1.path().c_str(), "", MS_SHARED, 0),
   999                SyscallSucceeds());
  1000  
  1001    auto const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1002    auto const mount2 =
  1003        ASSERT_NO_ERRNO_AND_VALUE(Mount("", dir2.path(), kTmpfs, 0, "", 0));
  1004    ASSERT_THAT(mount("", dir2.path().c_str(), "", MS_SHARED, 0),
  1005                SyscallSucceeds());
  1006  
  1007    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1008    ASSERT_FALSE(optionals[dir1.path()].empty());
  1009    ASSERT_FALSE(optionals[dir2.path()].empty());
  1010    EXPECT_NE(optionals[dir1.path()][0].shared, optionals[dir2.path()][0].shared);
  1011  }
  1012  
  1013  // Tests that shared mounts reused group IDs from deleted groups.
  1014  TEST(MountTest, ReuseGroupIDs) {
  1015    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1016  
  1017    auto const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1018    auto const mount1 =
  1019        ASSERT_NO_ERRNO_AND_VALUE(Mount("", dir1.path(), kTmpfs, 0, "", 0));
  1020    ASSERT_THAT(mount("", dir1.path().c_str(), "", MS_SHARED, 0),
  1021                SyscallSucceeds());
  1022  
  1023    auto const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1024    int reused_group_id;
  1025    {
  1026      auto const mount2 =
  1027          ASSERT_NO_ERRNO_AND_VALUE(Mount("", dir2.path(), kTmpfs, 0, "", 0));
  1028      ASSERT_THAT(mount("", dir2.path().c_str(), "", MS_SHARED, 0),
  1029                  SyscallSucceeds());
  1030      auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1031      ASSERT_FALSE(optionals[dir2.path()].empty());
  1032      reused_group_id = optionals[dir2.path()][0].shared;
  1033    }
  1034  
  1035    // Check that created a new shared mount reuses the ID 2.
  1036    auto const mount2 =
  1037        ASSERT_NO_ERRNO_AND_VALUE(Mount("", dir2.path(), kTmpfs, 0, "", 0));
  1038    ASSERT_THAT(mount("", dir2.path().c_str(), "", MS_SHARED, 0),
  1039                SyscallSucceeds());
  1040    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1041    ASSERT_FALSE(optionals[dir2.path()].empty());
  1042    EXPECT_EQ(reused_group_id, optionals[dir2.path()][0].shared);
  1043  }
  1044  
  1045  // Tests that a child mount inherits the propagation type of its parent.
  1046  TEST(MountTest, InerheritPropagation) {
  1047    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1048  
  1049    auto const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1050    auto const mount1 =
  1051        ASSERT_NO_ERRNO_AND_VALUE(Mount("", dir1.path(), kTmpfs, 0, "", 0));
  1052    ASSERT_THAT(mount("", dir1.path().c_str(), "", MS_SHARED, 0),
  1053                SyscallSucceeds());
  1054  
  1055    auto const dir2 =
  1056        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir1.path()));
  1057    auto const mount2 =
  1058        ASSERT_NO_ERRNO_AND_VALUE(Mount("", dir2.path(), kTmpfs, 0, "", 0));
  1059  
  1060    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1061    ASSERT_FALSE(optionals[dir2.path()].empty());
  1062    EXPECT_NE(optionals[dir2.path()][0].shared, 0);
  1063  }
  1064  
  1065  // Tests that it is possible to make a mount private again after it is shared.
  1066  TEST(MountTest, MakePrivate) {
  1067    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1068  
  1069    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1070    auto const mnt =
  1071        ASSERT_NO_ERRNO_AND_VALUE(Mount("", dir.path(), kTmpfs, 0, "", 0));
  1072    ASSERT_THAT(mount("", dir.path().c_str(), "", MS_SHARED, 0),
  1073                SyscallSucceeds());
  1074    ASSERT_THAT(mount("", dir.path().c_str(), "", MS_PRIVATE, 0),
  1075                SyscallSucceeds());
  1076  
  1077    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1078    ASSERT_FALSE(optionals[dir.path()].empty());
  1079    EXPECT_EQ(optionals[dir.path()][0].shared, 0);
  1080  }
  1081  
  1082  TEST(MountTest, ArgumentsAreIgnored) {
  1083    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1084    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1085    // These mounts should not fail even though string arguments are passed as
  1086    // NULL.
  1087    auto const mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1088        Mount(dir.path(), dir.path(), "", MS_BIND, "", MNT_DETACH));
  1089    ASSERT_THAT(mount(NULL, dir.path().c_str(), NULL, MS_SHARED, NULL),
  1090                SyscallSucceeds());
  1091    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1092    ASSERT_FALSE(optionals[dir.path()].empty());
  1093    EXPECT_NE(optionals[dir.path()][0].shared, 0);
  1094  }
  1095  
  1096  TEST(MountTest, MultiplePropagationFlagsFails) {
  1097    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1098  
  1099    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1100    auto const mnt =
  1101        ASSERT_NO_ERRNO_AND_VALUE(Mount("", dir.path(), kTmpfs, 0, "", 0));
  1102    EXPECT_THAT(mount("", dir.path().c_str(), "", MS_SHARED | MS_PRIVATE, 0),
  1103                SyscallFailsWithErrno(EINVAL));
  1104  }
  1105  
  1106  TEST(MountTest, SetMountPropagationOfStackedMounts) {
  1107    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1108    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1109    auto const mnt1 = ASSERT_NO_ERRNO_AND_VALUE(
  1110        Mount("", dir.path().c_str(), kTmpfs, 0, "", 0));
  1111    // Only the topmost mount on the stack should be shared.
  1112    auto const mnt2 = ASSERT_NO_ERRNO_AND_VALUE(
  1113        Mount("", dir.path().c_str(), kTmpfs, 0, "", 0));
  1114    ASSERT_THAT(mount("", dir.path().c_str(), "", MS_SHARED, 0),
  1115                SyscallSucceeds());
  1116  
  1117    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1118    ASSERT_FALSE(optionals[dir.path()].empty());
  1119    EXPECT_EQ(optionals[dir.path()][0].shared, 0);
  1120    EXPECT_NE(optionals[dir.path()][1].shared, 0);
  1121  }
  1122  
  1123  TEST(MountTest, MakePeer) {
  1124    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1125    auto const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1126    auto const mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1127        Mount("", dir1.path().c_str(), kTmpfs, 0, "", 0));
  1128    ASSERT_THAT(mount("", dir1.path().c_str(), "", MS_SHARED, 0),
  1129                SyscallSucceeds());
  1130  
  1131    auto const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1132    auto const mnt2 = ASSERT_NO_ERRNO_AND_VALUE(
  1133        Mount(dir1.path(), dir2.path(), "", MS_BIND, "", MNT_DETACH));
  1134  
  1135    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1136    ASSERT_FALSE(optionals[dir1.path()].empty());
  1137    ASSERT_FALSE(optionals[dir2.path()].empty());
  1138    EXPECT_EQ(optionals[dir1.path()][0].shared, optionals[dir2.path()][0].shared);
  1139    EXPECT_NE(optionals[dir1.path()][0].shared, 0);
  1140  }
  1141  
  1142  TEST(MountTest, PropagateMountEvent) {
  1143    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1144    auto const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1145    auto const mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1146        Mount("", dir1.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
  1147    auto const child_dir =
  1148        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir1.path()));
  1149    ASSERT_THAT(mount("", dir1.path().c_str(), "", MS_SHARED, 0),
  1150                SyscallSucceeds());
  1151    auto const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1152    auto const mnt2 = ASSERT_NO_ERRNO_AND_VALUE(
  1153        Mount(dir1.path(), dir2.path(), "", MS_BIND, "", MNT_DETACH));
  1154    // This mount should propagate to dir2.
  1155    auto const child_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1156        Mount("", child_dir.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
  1157  
  1158    const std::string child_path1 =
  1159        JoinPath(dir1.path(), Basename(child_dir.path()));
  1160    const std::string child_path2 =
  1161        JoinPath(dir2.path(), Basename(child_dir.path()));
  1162  
  1163    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1164    ASSERT_FALSE(optionals[dir1.path()].empty());
  1165    ASSERT_FALSE(optionals[dir2.path()].empty());
  1166    ASSERT_FALSE(optionals[child_path1].empty());
  1167    ASSERT_FALSE(optionals[child_path2].empty());
  1168    EXPECT_EQ(optionals[dir1.path()][0].shared, optionals[dir2.path()][0].shared);
  1169    EXPECT_NE(optionals[dir1.path()][0].shared, 0);
  1170    EXPECT_EQ(optionals[child_path1][0].shared, optionals[child_path2][0].shared);
  1171    EXPECT_NE(optionals[child_path1][0].shared, 0);
  1172  }
  1173  
  1174  TEST(MountTest, PropagateUmountEvent) {
  1175    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1176    auto const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1177    auto const mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1178        Mount("", dir1.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
  1179    auto const child_dir =
  1180        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir1.path()));
  1181    ASSERT_THAT(mount("", dir1.path().c_str(), "", MS_SHARED, 0),
  1182                SyscallSucceeds());
  1183    auto const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1184    auto const mnt2 = ASSERT_NO_ERRNO_AND_VALUE(
  1185        Mount(dir1.path(), dir2.path(), "", MS_BIND, "", MNT_DETACH));
  1186    // This mount will propagate to dir2. Once the block ends it will be
  1187    // unmounted, which should also propagate to dir2.
  1188    {
  1189      auto const child_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1190          Mount("", child_dir.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
  1191    }
  1192  
  1193    const std::string child_path1 =
  1194        JoinPath(dir1.path(), Basename(child_dir.path()));
  1195    const std::string child_path2 =
  1196        JoinPath(dir2.path(), Basename(child_dir.path()));
  1197  
  1198    std::vector<ProcMountInfoEntry> mounts =
  1199        ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountInfoEntries());
  1200    for (const auto& e : mounts) {
  1201      EXPECT_NE(e.mount_point, child_path1);
  1202      EXPECT_NE(e.mount_point, child_path2);
  1203    }
  1204  }
  1205  
  1206  TEST(MountTest, PropagateChildUmountEvent) {
  1207    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1208  
  1209    TempPath const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1210    ASSERT_THAT(mount("", dir1.path().c_str(), kTmpfs, 0, ""), SyscallSucceeds());
  1211  
  1212    TempPath const child =
  1213        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir1.path()));
  1214    ASSERT_THAT(mount("", child.path().c_str(), kTmpfs, 0, ""),
  1215                SyscallSucceeds());
  1216    ASSERT_THAT(mount("", child.path().c_str(), "", MS_SHARED, 0),
  1217                SyscallSucceeds());
  1218  
  1219    TempPath const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1220    ASSERT_THAT(mount(child.path().c_str(), dir2.path().c_str(), "", MS_BIND, 0),
  1221                SyscallSucceeds());
  1222    ASSERT_THAT(mount("", child.path().c_str(), kTmpfs, 0, ""),
  1223                SyscallSucceeds());
  1224    ASSERT_THAT(umount2(dir1.path().c_str(), MNT_DETACH), SyscallSucceeds());
  1225  
  1226    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1227    EXPECT_EQ(optionals[dir2.path()].size(), 1);
  1228  
  1229    ASSERT_EQ(umount2(dir2.path().c_str(), MNT_DETACH), 0);
  1230  }
  1231  
  1232  TEST(MountTest, UmountIgnoresPeersWithChildren) {
  1233    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1234    auto const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1235    ASSERT_THAT(mount("", dir1.path().c_str(), kTmpfs, 0, ""), SyscallSucceeds());
  1236    ASSERT_THAT(mount("", dir1.path().c_str(), "", MS_SHARED, 0),
  1237                SyscallSucceeds());
  1238    auto const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1239    ASSERT_THAT(mount(dir1.path().c_str(), dir2.path().c_str(), "", MS_BIND, 0),
  1240                SyscallSucceeds());
  1241  
  1242    auto const child_dir =
  1243        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir1.path()));
  1244    ASSERT_THAT(mount("", child_dir.path().c_str(), kTmpfs, 0, ""),
  1245                SyscallSucceeds());
  1246    auto const grandchild_dir =
  1247        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(child_dir.path()));
  1248    ASSERT_THAT(mount("", grandchild_dir.path().c_str(), kTmpfs, 0, ""),
  1249                SyscallSucceeds());
  1250  
  1251    const std::string child_path1 =
  1252        JoinPath(dir1.path(), Basename(child_dir.path()));
  1253    const std::string child_path2 =
  1254        JoinPath(dir2.path(), Basename(child_dir.path()));
  1255    ASSERT_THAT(mount("", child_path2.c_str(), "", MS_PRIVATE, 0),
  1256                SyscallSucceeds());
  1257    const std::string grandchild_path2 =
  1258        JoinPath(child_path2, Basename(grandchild_dir.path()));
  1259    ASSERT_THAT(umount2(grandchild_path2.c_str(), MNT_DETACH), SyscallSucceeds());
  1260  
  1261    // This umount event should not propagate to the peer at dir1 because its
  1262    // child mount still has its own child mount.
  1263    ASSERT_THAT(umount2(child_path2.c_str(), MNT_DETACH), SyscallSucceeds());
  1264    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1265    EXPECT_EQ(optionals[child_path2].size(), 0);
  1266    EXPECT_EQ(optionals[child_path1].size(), 1);
  1267  
  1268    ASSERT_THAT(umount2(dir1.path().c_str(), MNT_DETACH), SyscallSucceeds());
  1269    ASSERT_THAT(umount2(dir2.path().c_str(), MNT_DETACH), SyscallSucceeds());
  1270  }
  1271  
  1272  TEST(MountTest, BindSharedOnShared) {
  1273    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1274    auto const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1275    auto const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1276    auto const dir3 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1277    auto const dir4 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1278    // Dir 1 and 2 are part of peer group 'A', dir 3 and 4 are part of peer group
  1279    // 'B'.
  1280    auto const mnt1 = ASSERT_NO_ERRNO_AND_VALUE(
  1281        Mount("", dir1.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
  1282    auto const dir5 =
  1283        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir1.path()));
  1284    ASSERT_THAT(mount("", dir1.path().c_str(), "", MS_SHARED, 0),
  1285                SyscallSucceeds());
  1286    auto const mnt2 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1287        dir1.path().c_str(), dir2.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1288    auto const mnt3 = ASSERT_NO_ERRNO_AND_VALUE(
  1289        Mount("", dir3.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
  1290    ASSERT_THAT(mount("", dir3.path().c_str(), "", MS_SHARED, 0),
  1291                SyscallSucceeds());
  1292    auto const mnt4 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1293        dir3.path().c_str(), dir4.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1294  
  1295    const std::string dir5_path2 = JoinPath(dir2.path(), Basename(dir5.path()));
  1296  
  1297    // Bind peer group 'A' to peer group 'B'.
  1298    auto const mnt5 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1299        dir4.path().c_str(), dir5.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1300  
  1301    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1302    ASSERT_FALSE(optionals[dir1.path()].empty());
  1303    ASSERT_FALSE(optionals[dir2.path()].empty());
  1304    ASSERT_FALSE(optionals[dir3.path()].empty());
  1305    ASSERT_FALSE(optionals[dir4.path()].empty());
  1306    ASSERT_FALSE(optionals[dir5.path()].empty());
  1307    ASSERT_FALSE(optionals[dir5_path2].empty());
  1308    EXPECT_EQ(optionals[dir3.path()][0].shared, optionals[dir4.path()][0].shared);
  1309    EXPECT_EQ(optionals[dir4.path()][0].shared, optionals[dir5.path()][0].shared);
  1310    EXPECT_EQ(optionals[dir5.path()][0].shared, optionals[dir5_path2][0].shared);
  1311    EXPECT_NE(optionals[dir3.path()][0].shared, 0);
  1312  }
  1313  
  1314  TEST(MountTest, BindSharedOnPrivate) {
  1315    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1316    auto const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1317    auto const mnt1 = ASSERT_NO_ERRNO_AND_VALUE(
  1318        Mount("", dir1.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
  1319    auto const dir2 =
  1320        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir1.path()));
  1321    auto const dir3 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1322    auto const dir4 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1323    auto const mnt3 = ASSERT_NO_ERRNO_AND_VALUE(
  1324        Mount("", dir3.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
  1325    ASSERT_THAT(mount("", dir3.path().c_str(), "", MS_SHARED, 0),
  1326                SyscallSucceeds());
  1327    auto const mnt4 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1328        dir3.path().c_str(), dir4.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1329  
  1330    // bind to private mount.
  1331    auto const mnt2 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1332        dir3.path().c_str(), dir2.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1333  
  1334    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1335    ASSERT_FALSE(optionals[dir1.path()].empty());
  1336    ASSERT_FALSE(optionals[dir2.path()].empty());
  1337    ASSERT_FALSE(optionals[dir3.path()].empty());
  1338    ASSERT_FALSE(optionals[dir4.path()].empty());
  1339    EXPECT_EQ(optionals[dir1.path()][0].shared, 0);
  1340    EXPECT_EQ(optionals[dir2.path()][0].shared, optionals[dir3.path()][0].shared);
  1341    EXPECT_EQ(optionals[dir3.path()][0].shared, optionals[dir4.path()][0].shared);
  1342  }
  1343  
  1344  TEST(MountTest, BindPeerGroupsWithChildren) {
  1345    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1346    auto const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1347    auto const mnt1 = ASSERT_NO_ERRNO_AND_VALUE(
  1348        Mount("", dir1.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
  1349    ASSERT_THAT(mount("", dir1.path().c_str(), "", MS_SHARED, 0),
  1350                SyscallSucceeds());
  1351    auto const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1352    auto const mnt2 = ASSERT_NO_ERRNO_AND_VALUE(
  1353        Mount("", dir2.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
  1354    ASSERT_THAT(mount("", dir2.path().c_str(), "", MS_SHARED, 0),
  1355                SyscallSucceeds());
  1356    // dir3 and dir4 are child mounts of dir1.
  1357    auto const dir3 =
  1358        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir1.path()));
  1359    auto const mnt3 = ASSERT_NO_ERRNO_AND_VALUE(
  1360        Mount("", dir3.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
  1361    auto const dir4 =
  1362        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir1.path()));
  1363    auto const mnt4 = ASSERT_NO_ERRNO_AND_VALUE(
  1364        Mount("", dir4.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
  1365    auto const mnt5 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1366        dir1.path().c_str(), dir2.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1367  
  1368    const std::string dir3_path2 = JoinPath(dir2.path(), Basename(dir3.path()));
  1369    const std::string dir4_path2 = JoinPath(dir2.path(), Basename(dir4.path()));
  1370  
  1371    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1372    ASSERT_FALSE(optionals[dir1.path()].empty());
  1373    ASSERT_FALSE(optionals[dir2.path()].empty());
  1374    ASSERT_FALSE(optionals[dir3.path()].empty());
  1375  
  1376    EXPECT_NE(optionals[dir1.path()][0].shared, optionals[dir3.path()][0].shared);
  1377    EXPECT_NE(optionals[dir3.path()][0].shared, optionals[dir4.path()][0].shared);
  1378    EXPECT_NE(optionals[dir4.path()][0].shared, optionals[dir1.path()][0].shared);
  1379    EXPECT_EQ(optionals[dir3_path2].size(), 0);
  1380    EXPECT_EQ(optionals[dir4_path2].size(), 0);
  1381  }
  1382  
  1383  TEST(MountTest, BindParentToChild) {
  1384    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1385    auto const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1386    auto const mnt1 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1387        dir1.path().c_str(), dir1.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1388    ASSERT_THAT(mount("", dir1.path().c_str(), "", MS_SHARED, 0),
  1389                SyscallSucceeds());
  1390    auto const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1391    auto const mnt2 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1392        dir1.path().c_str(), dir2.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1393    auto const child_dir =
  1394        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir1.path()));
  1395    auto const mnt3 = ASSERT_NO_ERRNO_AND_VALUE(
  1396        Mount(dir1.path().c_str(), child_dir.path().c_str(), "", MS_BIND, "",
  1397              MNT_DETACH));
  1398  
  1399    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1400    ASSERT_FALSE(optionals[dir1.path()].empty());
  1401    ASSERT_FALSE(optionals[dir2.path()].empty());
  1402    ASSERT_FALSE(optionals[child_dir.path()].empty());
  1403  
  1404    EXPECT_EQ(optionals[dir1.path()][0].shared, optionals[dir2.path()][0].shared);
  1405    EXPECT_EQ(optionals[dir2.path()][0].shared,
  1406              optionals[child_dir.path()][0].shared);
  1407    EXPECT_NE(optionals[dir1.path()][0].shared, 0);
  1408  }
  1409  
  1410  TEST(MountTest, MountInfoHasRoot) {
  1411    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1412    auto const parent = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1413    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
  1414        Mount("", parent.path(), kTmpfs, 0, "mode=0123", 0));
  1415    auto const child =
  1416        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(parent.path()));
  1417    auto const bind_mount = Mount(child.path(), child.path(), "", MS_BIND, "", 0);
  1418    std::vector<ProcMountInfoEntry> mounts =
  1419        ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountInfoEntries());
  1420    for (const auto& e : mounts) {
  1421      if (e.mount_point == child.path()) {
  1422        EXPECT_EQ(e.root, JoinPath("/", Basename(child.path())))
  1423            << "Offending mount ID is: " << e.id;
  1424      }
  1425      if (e.mount_point == parent.path()) {
  1426        EXPECT_EQ(e.root, "/") << "Offending mount ID is: " << e.id;
  1427      }
  1428    }
  1429  }
  1430  
  1431  TEST(MountTest, DeadMountsAreDecRefd) {
  1432    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1433    DisableSave ds;
  1434    std::string home = NewTempAbsPath();
  1435    ASSERT_NO_ERRNO(Mkdir(home));
  1436    ASSERT_THAT(chdir(home.c_str()), SyscallSucceeds());
  1437    constexpr char dirpath[] = "./file";
  1438  
  1439    for (int i = 0; i < 10; ++i) {
  1440      const auto rest = [&] {
  1441        mkdir(dirpath, 0);
  1442        mount(dirpath, ".", 0, MS_BIND, 0);
  1443        rmdir(dirpath);
  1444        mkdir(dirpath, 0);
  1445        mount(dirpath, ".", 0, MS_BIND, 0);
  1446      };
  1447      EXPECT_THAT(InForkedProcess(rest), IsPosixErrorOkAndHolds(0));
  1448    }
  1449  }
  1450  
  1451  TEST(MountTest, UmountSharedBind) {
  1452    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1453    std::string home = NewTempAbsPath();
  1454    ASSERT_NO_ERRNO(Mkdir(home));
  1455    ASSERT_THAT(chdir(home.c_str()), SyscallSucceeds());
  1456    constexpr char dirpath[] = "./file";
  1457  
  1458    ASSERT_THAT(mkdir(dirpath, 0), SyscallSucceeds());
  1459    ASSERT_THAT(mount(dirpath, dirpath, 0, MS_BIND, 0), SyscallSucceeds());
  1460    ASSERT_THAT(mount(0, dirpath, 0, MS_SHARED, 0), SyscallSucceeds());
  1461    ASSERT_THAT(mount(dirpath, dirpath, 0, MS_BIND, 0), SyscallSucceeds());
  1462    ASSERT_THAT(mount(0, dirpath, 0, MS_SHARED, 0), SyscallSucceeds());
  1463    ASSERT_THAT(umount2(dirpath, MNT_DETACH), SyscallSucceeds());
  1464    ASSERT_THAT(umount2(dirpath, MNT_DETACH), SyscallSucceeds());
  1465  }
  1466  
  1467  TEST(MountTest, MakeSlave) {
  1468    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1469    auto const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1470    auto const mnt1 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1471        dir1.path().c_str(), dir1.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1472    ASSERT_THAT(mount("", dir1.path().c_str(), "", MS_SHARED, 0),
  1473                SyscallSucceeds());
  1474    auto const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1475    auto const mnt2 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1476        dir1.path().c_str(), dir2.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1477  
  1478    ASSERT_THAT(mount(0, dir2.path().c_str(), 0, MS_SLAVE, 0), SyscallSucceeds());
  1479    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1480    ASSERT_NE(optionals[dir1.path()][0].shared, 0);
  1481    ASSERT_NE(optionals[dir2.path()][0].master, 0);
  1482  }
  1483  
  1484  TEST(MountTest, MakeSharedSlave) {
  1485    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1486  
  1487    auto const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1488    auto const mnt1 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1489        dir1.path().c_str(), dir1.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1490    ASSERT_THAT(mount("", dir1.path().c_str(), "", MS_SHARED, 0),
  1491                SyscallSucceeds());
  1492    auto const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1493    auto const mnt2 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1494        dir1.path().c_str(), dir2.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1495  
  1496    ASSERT_THAT(mount(0, dir2.path().c_str(), 0, MS_SLAVE, 0), SyscallSucceeds());
  1497    ASSERT_THAT(mount(0, dir2.path().c_str(), 0, MS_SHARED, 0),
  1498                SyscallSucceeds());
  1499  
  1500    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1501    ASSERT_NE(optionals[dir1.path()][0].shared, 0);
  1502    ASSERT_NE(optionals[dir2.path()][0].shared, 0);
  1503    ASSERT_NE(optionals[dir2.path()][0].master, 0);
  1504  }
  1505  
  1506  TEST(MountTest, PrivateMasterUnslaves) {
  1507    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1508    auto const base = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1509    auto const base_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1510        Mount("", base.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
  1511    ASSERT_THAT(mount("", base.path().c_str(), "", MS_PRIVATE, 0),
  1512                SyscallSucceeds());
  1513  
  1514    auto const dir1 =
  1515        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(base.path()));
  1516    auto const mnt1 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1517        dir1.path().c_str(), dir1.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1518    ASSERT_THAT(mount("", dir1.path().c_str(), "", MS_SHARED, 0),
  1519                SyscallSucceeds());
  1520    auto const dir2 =
  1521        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(base.path()));
  1522    auto const mnt2 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1523        dir1.path().c_str(), dir2.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1524    ASSERT_THAT(mount(0, dir2.path().c_str(), 0, MS_SLAVE, 0), SyscallSucceeds());
  1525    ASSERT_THAT(mount(0, dir2.path().c_str(), 0, MS_SHARED, 0),
  1526                SyscallSucceeds());
  1527  
  1528    ASSERT_THAT(mount(0, dir1.path().c_str(), 0, MS_PRIVATE, 0),
  1529                SyscallSucceeds());
  1530  
  1531    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1532    ASSERT_EQ(optionals[dir1.path()][0].shared, 0);
  1533    ASSERT_EQ(optionals[dir2.path()][0].master, 0);
  1534    ASSERT_NE(optionals[dir2.path()][0].shared, 0);
  1535  }
  1536  
  1537  TEST(MountTest, SlaveMaster) {
  1538    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1539  
  1540    auto const dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1541    auto const mnt1 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1542        dir1.path().c_str(), dir1.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1543    ASSERT_THAT(mount("", dir1.path().c_str(), "", MS_SHARED, 0),
  1544                SyscallSucceeds());
  1545    auto const dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1546    auto const mnt2 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1547        dir1.path().c_str(), dir2.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1548    ASSERT_THAT(mount(0, dir2.path().c_str(), 0, MS_SLAVE, 0), SyscallSucceeds());
  1549    ASSERT_THAT(mount(0, dir2.path().c_str(), 0, MS_SHARED, 0),
  1550                SyscallSucceeds());
  1551    auto const dir3 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1552    auto const mnt3 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1553        dir2.path().c_str(), dir3.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1554    ASSERT_THAT(mount(0, dir3.path().c_str(), 0, MS_SLAVE, 0), SyscallSucceeds());
  1555  
  1556    ASSERT_THAT(mount(0, dir2.path().c_str(), 0, MS_PRIVATE, 0),
  1557                SyscallSucceeds());
  1558  
  1559    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1560    ASSERT_NE(optionals[dir1.path()][0].shared, 0);
  1561    ASSERT_EQ(optionals[dir2.path()][0].shared, 0);
  1562    ASSERT_EQ(optionals[dir2.path()][0].master, 0);
  1563    ASSERT_EQ(optionals[dir3.path()][0].master, optionals[dir1.path()][0].shared);
  1564  }
  1565  
  1566  TEST(MountTest, BindSharedToSlave) {
  1567    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1568  
  1569    auto const src = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1570    auto const src_mnt = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1571        src.path().c_str(), src.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1572    ASSERT_THAT(mount("", src.path().c_str(), "", MS_SHARED, 0),
  1573                SyscallSucceeds());
  1574    auto const dst_master = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1575    auto const dst_master_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1576        Mount(dst_master.path().c_str(), dst_master.path().c_str(), "", MS_BIND,
  1577              "", MNT_DETACH));
  1578    ASSERT_THAT(mount("", dst_master.path().c_str(), "", MS_SHARED, 0),
  1579                SyscallSucceeds());
  1580    auto const dst = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1581    auto const dst_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1582        Mount(dst_master.path().c_str(), dst.path().c_str(), "", MS_BIND, "",
  1583              MNT_DETACH));
  1584    ASSERT_THAT(mount("", dst.path().c_str(), "", MS_SLAVE, 0),
  1585                SyscallSucceeds());
  1586  
  1587    auto const dst_mnt2 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1588        src.path().c_str(), dst.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1589    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1590  
  1591    ASSERT_EQ(optionals[src.path()][0].shared, optionals[dst.path()][1].shared);
  1592    ASSERT_EQ(optionals[dst.path()][0].master,
  1593              optionals[dst_master.path()][0].shared);
  1594  }
  1595  
  1596  TEST(MountTest, BindSlaveToShared) {
  1597    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1598  
  1599    auto const src = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1600    auto const src_mnt = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1601        src.path().c_str(), src.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1602    ASSERT_THAT(mount("", src.path().c_str(), "", MS_SHARED, 0),
  1603                SyscallSucceeds());
  1604    auto const src_master = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1605    auto const src_master_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1606        Mount(src.path().c_str(), src_master.path().c_str(), "", MS_BIND, "",
  1607              MNT_DETACH));
  1608    ASSERT_THAT(mount("", src.path().c_str(), "", MS_SLAVE, 0),
  1609                SyscallSucceeds());
  1610  
  1611    auto const dst = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1612    auto const dst_mnt = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1613        dst.path().c_str(), dst.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1614    ASSERT_THAT(mount("", dst.path().c_str(), "", MS_SHARED, 0),
  1615                SyscallSucceeds());
  1616    auto const dst_peer = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1617    auto const dst_peer_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1618        Mount(dst.path().c_str(), dst_peer.path().c_str(), "", MS_BIND, "",
  1619              MNT_DETACH));
  1620  
  1621    auto const dst_mnt2 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1622        src.path().c_str(), dst.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1623  
  1624    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1625    ASSERT_EQ(optionals[dst.path()][1].shared,
  1626              optionals[dst_peer.path()][1].shared);
  1627    ASSERT_EQ(optionals[dst.path()][1].master,
  1628              optionals[dst_peer.path()][1].master);
  1629    ASSERT_EQ(optionals[dst.path()][1].master,
  1630              optionals[src_master.path()][0].shared);
  1631  }
  1632  
  1633  TEST(MountTest, BindSlaveToSlave) {
  1634    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1635  
  1636    auto const src = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1637    auto const src_mnt = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1638        src.path().c_str(), src.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1639    ASSERT_THAT(mount("", src.path().c_str(), "", MS_SHARED, 0),
  1640                SyscallSucceeds());
  1641    auto const src_master = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1642    auto const src_master_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1643        Mount(src.path().c_str(), src_master.path().c_str(), "", MS_BIND, "",
  1644              MNT_DETACH));
  1645    ASSERT_THAT(mount("", src.path().c_str(), "", MS_SLAVE, 0),
  1646                SyscallSucceeds());
  1647  
  1648    auto const dst = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1649    auto const dst_mnt = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1650        dst.path().c_str(), dst.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1651    ASSERT_THAT(mount("", dst.path().c_str(), "", MS_SHARED, 0),
  1652                SyscallSucceeds());
  1653    auto const dst_master = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1654    auto const dst_master_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1655        Mount(dst.path().c_str(), dst_master.path().c_str(), "", MS_BIND, "",
  1656              MNT_DETACH));
  1657    ASSERT_THAT(mount("", dst.path().c_str(), "", MS_SLAVE, 0),
  1658                SyscallSucceeds());
  1659  
  1660    auto const dst_mnt2 = ASSERT_NO_ERRNO_AND_VALUE(Mount(
  1661        src.path().c_str(), dst.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1662  
  1663    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1664    ASSERT_EQ(optionals[dst.path()][1].master, optionals[src.path()][0].master);
  1665  }
  1666  
  1667  // Test that mounting on a slave mount does not propagate to the master.
  1668  TEST(MountTest, SlavePropagationEvent) {
  1669    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1670  
  1671    auto const dst_master = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1672    auto const dst_master_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1673        Mount(dst_master.path().c_str(), dst_master.path().c_str(), "", MS_BIND,
  1674              "", MNT_DETACH));
  1675    ASSERT_THAT(mount("", dst_master.path().c_str(), "", MS_SHARED, 0),
  1676                SyscallSucceeds());
  1677    auto const dst = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1678    auto const dst_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1679        Mount(dst_master.path().c_str(), dst.path().c_str(), "", MS_BIND, "",
  1680              MNT_DETACH));
  1681    ASSERT_THAT(mount("", dst.path().c_str(), "", MS_SLAVE, 0),
  1682                SyscallSucceeds());
  1683    auto const child =
  1684        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dst_master.path()));
  1685  
  1686    const std::string master_child_path =
  1687        JoinPath(dst_master.path(), Basename(child.path()));
  1688    const std::string slave_child_path =
  1689        JoinPath(dst.path(), Basename(child.path()));
  1690    auto const slave_child_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1691        Mount("", slave_child_path.c_str(), kTmpfs, 0, "", MNT_DETACH));
  1692  
  1693    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1694    ASSERT_EQ(optionals[child.path()].size(), 0);
  1695  }
  1696  
  1697  // We are building a propagation tree that looks like this:
  1698  /*
  1699      A <--> B <--> C <---> D
  1700     /|\           /|       |\
  1701    / F G         J K       H I
  1702   /
  1703  E<-->O
  1704      /|\
  1705     M L N
  1706  */
  1707  // Propagating mount events across this tree should cover most propagation
  1708  // cases.
  1709  TEST(MountTest, LargeTreePropagationEvent) {
  1710    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1711  
  1712    // 15 total mounts that should all get propagated to if we mount on A.
  1713    auto const a = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1714    auto const b = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1715    auto const c = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1716    auto const d = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1717    auto const e = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1718    auto const f = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1719    auto const g = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1720    auto const h = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1721    auto const i = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1722    auto const j = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1723    auto const k = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1724    auto const l = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1725    auto const m = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1726    auto const n = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1727    auto const o = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1728  
  1729    auto const a_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1730        Mount(a.path().c_str(), a.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1731    ASSERT_THAT(mount("", a.path().c_str(), "", MS_SHARED, 0), SyscallSucceeds());
  1732  
  1733    // Place E, F, and G in A's peer group, then make them slaves.
  1734    auto const e_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1735        Mount(a.path().c_str(), e.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1736    auto const f_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1737        Mount(a.path().c_str(), f.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1738    auto const g_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1739        Mount(a.path().c_str(), g.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1740    ASSERT_THAT(mount("", e.path().c_str(), "", MS_SLAVE, 0), SyscallSucceeds());
  1741    ASSERT_THAT(mount("", f.path().c_str(), "", MS_SLAVE, 0), SyscallSucceeds());
  1742    ASSERT_THAT(mount("", g.path().c_str(), "", MS_SLAVE, 0), SyscallSucceeds());
  1743  
  1744    // Add B to A's shared group.
  1745    auto const b_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1746        Mount(a.path().c_str(), b.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1747  
  1748    // Add C to A's shared group and place J and K in C's peer group, then make
  1749    // them slaves.
  1750    auto const c_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1751        Mount(a.path().c_str(), c.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1752    auto const j_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1753        Mount(c.path().c_str(), j.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1754    auto const k_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1755        Mount(c.path().c_str(), k.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1756    ASSERT_THAT(mount("", j.path().c_str(), "", MS_SLAVE, 0), SyscallSucceeds());
  1757    ASSERT_THAT(mount("", k.path().c_str(), "", MS_SLAVE, 0), SyscallSucceeds());
  1758  
  1759    // Add D to A's shared group and place H and I in Ds peer group, then make
  1760    // them slaves.
  1761    auto const d_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1762        Mount(a.path().c_str(), d.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1763    auto const h_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1764        Mount(d.path().c_str(), h.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1765    auto const i_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1766        Mount(d.path().c_str(), i.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1767    ASSERT_THAT(mount("", h.path().c_str(), "", MS_SLAVE, 0), SyscallSucceeds());
  1768    ASSERT_THAT(mount("", i.path().c_str(), "", MS_SLAVE, 0), SyscallSucceeds());
  1769  
  1770    // Make E shared and create a group with O.
  1771    ASSERT_THAT(mount("", e.path().c_str(), "", MS_SHARED, 0), SyscallSucceeds());
  1772    auto const o_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1773        Mount(e.path().c_str(), o.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1774  
  1775    // Add M, L and N to K's shared group and make them slaves of O.
  1776    auto const m_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1777        Mount(o.path().c_str(), m.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1778    auto const l_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1779        Mount(o.path().c_str(), l.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1780    auto const n_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1781        Mount(o.path().c_str(), n.path().c_str(), "", MS_BIND, "", MNT_DETACH));
  1782    ASSERT_THAT(mount("", m.path().c_str(), "", MS_SLAVE, 0), SyscallSucceeds());
  1783    ASSERT_THAT(mount("", l.path().c_str(), "", MS_SLAVE, 0), SyscallSucceeds());
  1784    ASSERT_THAT(mount("", n.path().c_str(), "", MS_SLAVE, 0), SyscallSucceeds());
  1785  
  1786    std::vector<ProcMountInfoEntry> mounts =
  1787        ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountInfoEntries());
  1788  
  1789    ASSERT_THAT(mount("", a.path().c_str(), kTmpfs, 0, ""), SyscallSucceeds());
  1790  
  1791    std::vector<ProcMountInfoEntry> mounts_after_mount =
  1792        ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountInfoEntries());
  1793    ASSERT_EQ(mounts_after_mount.size(), mounts.size() + 15);
  1794  
  1795    auto optionals = ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1796  
  1797    // A, B, C, and D are all mounted over and in a peer group.
  1798    ASSERT_NE(optionals[a.path()][1].shared, 0);
  1799    ASSERT_EQ(optionals[a.path()][1].shared, optionals[b.path()][1].shared);
  1800    ASSERT_EQ(optionals[a.path()][1].shared, optionals[c.path()][1].shared);
  1801    ASSERT_EQ(optionals[a.path()][1].shared, optionals[d.path()][1].shared);
  1802  
  1803    // E, F, G, H, I, J, K are all mounted over and slave to A's peer group.
  1804    ASSERT_EQ(optionals[a.path()][1].shared, optionals[e.path()][1].master);
  1805    ASSERT_EQ(optionals[a.path()][1].shared, optionals[f.path()][1].master);
  1806    ASSERT_EQ(optionals[a.path()][1].shared, optionals[g.path()][1].master);
  1807    ASSERT_EQ(optionals[a.path()][1].shared, optionals[h.path()][1].master);
  1808    ASSERT_EQ(optionals[a.path()][1].shared, optionals[i.path()][1].master);
  1809    ASSERT_EQ(optionals[a.path()][1].shared, optionals[j.path()][1].master);
  1810    ASSERT_EQ(optionals[a.path()][1].shared, optionals[k.path()][1].master);
  1811  
  1812    // E and O are all mounted over and in a peer group.
  1813    ASSERT_EQ(optionals[e.path()][1].shared, optionals[o.path()][1].shared);
  1814  
  1815    // L, M, and N are all mounted over and slaves to E's peer group.
  1816    ASSERT_EQ(optionals[e.path()][1].shared, optionals[l.path()][1].master);
  1817    ASSERT_EQ(optionals[e.path()][1].shared, optionals[m.path()][1].master);
  1818    ASSERT_EQ(optionals[e.path()][1].shared, optionals[n.path()][1].master);
  1819  
  1820    ASSERT_THAT(umount2(a.path().c_str(), MNT_DETACH), SyscallSucceeds());
  1821    std::vector<ProcMountInfoEntry> mounts_after_umount =
  1822        ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountInfoEntries());
  1823    ASSERT_EQ(mounts_after_umount.size(), mounts.size());
  1824  }
  1825  
  1826  TEST(MountTest, MaxMountsWithSlave) {
  1827    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1828  
  1829    auto const parent = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1830    auto const parent_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1831        Mount("test", parent.path(), kTmpfs, 0, "mode=0123", MNT_DETACH));
  1832    auto const a =
  1833        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(parent.path()));
  1834    auto const b =
  1835        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(parent.path()));
  1836    auto const c =
  1837        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(parent.path()));
  1838  
  1839    auto const a_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1840        Mount("test", a.path(), kTmpfs, 0, "mode=0123", MNT_DETACH));
  1841    ASSERT_THAT(mount("", a.path().c_str(), "", MS_SHARED, 0), SyscallSucceeds());
  1842  
  1843    auto const b_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1844        Mount(a.path(), b.path(), "", MS_BIND, "", MNT_DETACH));
  1845    ASSERT_THAT(mount("", b.path().c_str(), "", MS_SLAVE, 0), SyscallSucceeds());
  1846    ASSERT_THAT(mount("", b.path().c_str(), "", MS_SHARED, 0), SyscallSucceeds());
  1847  
  1848    auto const c_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1849        Mount(b.path(), c.path(), "", MS_BIND, "", MNT_DETACH));
  1850    ASSERT_THAT(mount("", c.path().c_str(), "", MS_SLAVE, 0), SyscallSucceeds());
  1851  
  1852    auto const d = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(a.path()));
  1853    auto const e = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(a.path()));
  1854  
  1855    int mount_max = 10000;
  1856    bool mount_max_exists =
  1857        ASSERT_NO_ERRNO_AND_VALUE(Exists("/proc/sys/fs/mount-max"));
  1858    if (mount_max_exists) {
  1859      std::string mount_max_string;
  1860      ASSERT_NO_ERRNO(GetContents("/proc/sys/fs/mount-max", &mount_max_string));
  1861      ASSERT_TRUE(absl::SimpleAtoi(mount_max_string, &mount_max));
  1862    }
  1863  
  1864    // Each bind mount doubles the number of mounts in the propagation tree
  1865    // starting with 3. The number of binds we can do before failing is
  1866    // log2((max_mounts-num_current_mounts)/3).
  1867    std::vector<ProcMountInfoEntry> mounts =
  1868        ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountInfoEntries());
  1869    int num_binds = static_cast<int>(std::log2((mount_max - mounts.size()) / 3));
  1870  
  1871    for (int i = 0; i < num_binds; i++) {
  1872      ASSERT_THAT(
  1873          mount(d.path().c_str(), d.path().c_str(), nullptr, MS_BIND, nullptr),
  1874          SyscallSucceeds());
  1875      ASSERT_THAT(mount("", d.path().c_str(), "", MS_SHARED, 0),
  1876                  SyscallSucceeds());
  1877    }
  1878    for (int i = 0; i < 2; i++) {
  1879      EXPECT_THAT(
  1880          mount(d.path().c_str(), d.path().c_str(), nullptr, MS_BIND, nullptr),
  1881          SyscallFailsWithErrno(ENOSPC));
  1882    }
  1883  }
  1884  
  1885  TEST(MountTest, SetPropagationRecursive) {
  1886    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1887  
  1888    const TempPath a = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1889    auto const a_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1890        Mount("test", a.path(), kTmpfs, 0, "mode=0123", MNT_DETACH));
  1891    const auto b = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(a.path()));
  1892    auto const b_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1893        Mount("test", b.path(), kTmpfs, 0, "mode=0123", MNT_DETACH));
  1894    const auto c = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(b.path()));
  1895    auto const c_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1896        Mount("test", c.path(), kTmpfs, 0, "mode=0123", MNT_DETACH));
  1897    const auto d = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(c.path()));
  1898    auto const d_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1899        Mount("test", d.path(), kTmpfs, 0, "mode=0123", MNT_DETACH));
  1900  
  1901    ASSERT_THAT(mount("", a.path().c_str(), "", MS_SHARED | MS_REC, 0),
  1902                SyscallSucceeds());
  1903    absl::flat_hash_map<std::string, std::vector<MountOptional>> optionals =
  1904        ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1905    EXPECT_NE(optionals[a.path()][0].shared, 0);
  1906    EXPECT_NE(optionals[b.path()][0].shared, 0);
  1907    EXPECT_NE(optionals[c.path()][0].shared, 0);
  1908    EXPECT_NE(optionals[d.path()][0].shared, 0);
  1909  }
  1910  
  1911  TEST(MountTest, SetSlaveRecursive) {
  1912    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1913  
  1914    const auto a = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1915    auto const a_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1916        Mount(a.path(), a.path(), "", MS_BIND, "", MNT_DETACH));
  1917    ASSERT_THAT(mount("", a.path().c_str(), "", MS_SHARED, 0), SyscallSucceeds());
  1918    const auto a_master = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1919    auto const a_master_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1920        Mount(a.path(), a_master.path(), "", MS_BIND, "", MNT_DETACH));
  1921  
  1922    const auto b = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(a.path()));
  1923    auto const b_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1924        Mount(a.path(), b.path(), "", MS_BIND, "", MNT_DETACH));
  1925    const auto b_master = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1926    auto const b_master_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1927        Mount(b.path(), b_master.path(), "", MS_BIND, "", MNT_DETACH));
  1928  
  1929    ASSERT_THAT(mount("", a.path().c_str(), "", MS_SLAVE | MS_REC, 0),
  1930                SyscallSucceeds());
  1931  
  1932    absl::flat_hash_map<std::string, std::vector<MountOptional>> optionals =
  1933        ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  1934    EXPECT_EQ(optionals[a.path()][0].master,
  1935              optionals[a_master.path()][0].shared);
  1936    EXPECT_EQ(optionals[b.path()][0].master,
  1937              optionals[b_master.path()][0].shared);
  1938  }
  1939  
  1940  TEST(MountTest, RecursiveBind) {
  1941    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1942  
  1943    const auto a = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1944    auto const a_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1945        Mount(a.path(), a.path(), "", MS_BIND, "", MNT_DETACH));
  1946    const auto b = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(a.path()));
  1947    auto const b_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1948        Mount(b.path(), b.path(), "", MS_BIND, "", MNT_DETACH));
  1949    const auto c = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(b.path()));
  1950    const auto d = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1951    auto const d_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1952        Mount(a.path(), d.path(), "", MS_BIND | MS_REC, "", MNT_DETACH));
  1953  
  1954    // Write to child1 in dir1.
  1955    const std::string filename = "foo.txt";
  1956    const std::string contents = "barbaz";
  1957    ASSERT_NO_ERRNO(
  1958        CreateWithContents(JoinPath(c.path(), filename), contents, 0666));
  1959    // Verify both directories have the same nodes.
  1960    const std::string path =
  1961        JoinPath(d.path(), Basename(b.path()), Basename(c.path()), filename);
  1962  
  1963    std::string output;
  1964    ASSERT_NO_ERRNO(GetContents(path, &output));
  1965    EXPECT_EQ(output, contents);
  1966  }
  1967  
  1968  TEST(MountTest, MaxRecursiveBind) {
  1969    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  1970  
  1971    const auto a = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  1972    auto const a_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  1973        Mount(a.path(), a.path(), "", MS_BIND, "", MNT_DETACH));
  1974    const auto b = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(a.path()));
  1975  
  1976    int mount_max = 10000;
  1977    bool mount_max_exists =
  1978        ASSERT_NO_ERRNO_AND_VALUE(Exists("/proc/sys/fs/mount-max"));
  1979    if (mount_max_exists) {
  1980      std::string mount_max_string;
  1981      ASSERT_NO_ERRNO(GetContents("/proc/sys/fs/mount-max", &mount_max_string));
  1982      ASSERT_TRUE(absl::SimpleAtoi(mount_max_string, &mount_max));
  1983    }
  1984  
  1985    const std::vector<ProcMountInfoEntry> mounts =
  1986        ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountInfoEntries());
  1987    int num_binds = static_cast<int>(std::log2(mount_max - mounts.size()));
  1988  
  1989    for (int i = 0; i < num_binds; i++) {
  1990      ASSERT_THAT(mount(a.path().c_str(), b.path().c_str(), nullptr,
  1991                        MS_BIND | MS_REC, nullptr),
  1992                  SyscallSucceeds());
  1993    }
  1994    ASSERT_THAT(mount(a.path().c_str(), b.path().c_str(), nullptr,
  1995                      MS_BIND | MS_REC, nullptr),
  1996                SyscallFailsWithErrno(ENOSPC));
  1997  }
  1998  
  1999  TEST(MountTest, RecursiveBindPropagation) {
  2000    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  2001  
  2002    const auto parent = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  2003    auto const parent_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  2004        Mount(parent.path(), parent.path(), "", MS_BIND, "", MNT_DETACH));
  2005    const auto a =
  2006        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(parent.path()));
  2007    const auto b =
  2008        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(parent.path()));
  2009    const auto c =
  2010        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(parent.path()));
  2011  
  2012    auto const a_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  2013        Mount("test", a.path(), kTmpfs, 0, "", MNT_DETACH));
  2014    ASSERT_THAT(mount("", a.path().c_str(), "", MS_SHARED, 0), SyscallSucceeds());
  2015  
  2016    auto const b_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  2017        Mount(a.path(), b.path(), "", MS_BIND, "", MNT_DETACH));
  2018    auto const c_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  2019        Mount(a.path(), c.path(), "", MS_BIND, "", MNT_DETACH));
  2020  
  2021    const auto d =
  2022        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(parent.path()));
  2023    const auto f = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(a.path()));
  2024    auto const d_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  2025        Mount(d.path(), d.path(), "", MS_BIND, "", MNT_DETACH));
  2026  
  2027    const auto e = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(d.path()));
  2028    auto const e_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  2029        Mount(e.path(), e.path(), "", MS_BIND, "", MNT_DETACH));
  2030  
  2031    auto const f_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  2032        Mount(d.path(), f.path(), "", MS_BIND | MS_REC, "", MNT_DETACH));
  2033  
  2034    absl::flat_hash_map<std::string, std::vector<MountOptional>> optionals =
  2035        ASSERT_NO_ERRNO_AND_VALUE(MountOptionals());
  2036    auto b_e_path = JoinPath(b.path(), Basename(f.path()), Basename(e.path()));
  2037    ASSERT_FALSE(optionals[b_e_path].empty());
  2038    auto c_e_path = JoinPath(c.path(), Basename(f.path()), Basename(e.path()));
  2039    ASSERT_FALSE(optionals[c_e_path].empty());
  2040  }
  2041  
  2042  TEST(MountTest, MountNamespace) {
  2043    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  2044  
  2045    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  2046    auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
  2047        Mount("", dir.path(), kTmpfs, 0, "mode=0700", 0));
  2048    auto const file_path = JoinPath(dir.path(), "foo");
  2049    EXPECT_NO_ERRNO(Open(file_path, O_CREAT | O_RDWR, 0777));
  2050  
  2051    pid_t child = fork();
  2052    if (child == 0) {
  2053      // Create a new mount namespace and umount the test mount from it.
  2054      TEST_PCHECK(unshare(CLONE_NEWNS) == 0);
  2055      TEST_PCHECK(access(file_path.c_str(), F_OK) == 0);
  2056      TEST_PCHECK(umount2(dir.path().c_str(), MNT_DETACH) == 0);
  2057      _exit(0);
  2058    }
  2059    ASSERT_THAT(child, SyscallSucceeds());
  2060    int status;
  2061    ASSERT_THAT(waitpid(child, &status, 0), SyscallSucceedsWithValue(child));
  2062    ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
  2063  
  2064    // Check that the test mount is still here.
  2065    EXPECT_NO_ERRNO(Open(file_path, O_RDWR));
  2066  }
  2067  
  2068  TEST(MountTest, MountNamespaceSetns) {
  2069    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  2070  
  2071    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  2072    auto const mnt = ASSERT_NO_ERRNO_AND_VALUE(
  2073        Mount("", dir.path(), kTmpfs, 0, "mode=0700", MNT_DETACH));
  2074    auto const file_path = JoinPath(dir.path(), "foo");
  2075    EXPECT_NO_ERRNO(Open(file_path, O_CREAT | O_RDWR, 0777));
  2076    const FileDescriptor nsfd =
  2077        ASSERT_NO_ERRNO_AND_VALUE(Open("/proc/thread-self/ns/mnt", O_RDONLY));
  2078  
  2079    pid_t child = fork();
  2080    if (child == 0) {
  2081      TEST_PCHECK(unshare(CLONE_NEWNS) == 0);
  2082      TEST_PCHECK(umount2(dir.path().c_str(), MNT_DETACH) == 0);
  2083      TEST_PCHECK(setns(nsfd.get(), CLONE_NEWNS) == 0);
  2084      TEST_PCHECK(access(file_path.c_str(), F_OK) == 0);
  2085      _exit(0);
  2086    }
  2087    ASSERT_THAT(child, SyscallSucceeds());
  2088    int status;
  2089    ASSERT_THAT(waitpid(child, &status, 0), SyscallSucceedsWithValue(child));
  2090    ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
  2091  }
  2092  
  2093  TEST(MountTest, MountNamespacePropagation) {
  2094    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  2095  
  2096    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  2097    auto const mnt = ASSERT_NO_ERRNO_AND_VALUE(
  2098        Mount("", dir.path(), kTmpfs, 0, "mode=0700", MNT_DETACH));
  2099    auto child_dir = JoinPath(dir.path(), "test");
  2100    auto const file_path = JoinPath(child_dir, "foo");
  2101    auto const file2_path = JoinPath(child_dir, "boo");
  2102  
  2103    ASSERT_THAT(mount(NULL, dir.path().c_str(), NULL, MS_SHARED, NULL),
  2104                SyscallSucceeds());
  2105    ASSERT_THAT(mkdir(child_dir.c_str(), 0700), SyscallSucceeds());
  2106    ASSERT_THAT(mount("child", child_dir.c_str(), kTmpfs, 0, NULL),
  2107                SyscallSucceeds());
  2108    EXPECT_NO_ERRNO(Open(file_path, O_CREAT | O_RDWR, 0777));
  2109  
  2110    pid_t child = fork();
  2111    if (child == 0) {
  2112      TEST_PCHECK(unshare(CLONE_NEWNS) == 0);
  2113      TEST_PCHECK(access(file_path.c_str(), F_OK) == 0);
  2114      // The test mount has to be umounted from the second mount namespace too.
  2115      TEST_PCHECK(umount2(child_dir.c_str(), MNT_DETACH) == 0);
  2116      // The new mount has to be propagated to the second mount namespace.
  2117      TEST_PCHECK(mount("test2", child_dir.c_str(), kTmpfs, 0, NULL) == 0);
  2118      TEST_PCHECK(mknod(file2_path.c_str(), 0777 | S_IFREG, 0) == 0);
  2119      _exit(0);
  2120    }
  2121    ASSERT_THAT(child, SyscallSucceeds());
  2122    int status;
  2123    ASSERT_THAT(waitpid(child, &status, 0), SyscallSucceedsWithValue(child));
  2124    ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
  2125  
  2126    // Check that the test mount is still here.
  2127    EXPECT_NO_ERRNO(Open(file2_path, O_RDWR));
  2128    EXPECT_THAT(umount2(child_dir.c_str(), MNT_DETACH), SyscallSucceeds());
  2129  }
  2130  
  2131  TEST(MountTest, MountNamespaceSlavesNewUserNamespace) {
  2132    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  2133    SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(IsOverlayfs(GetAbsoluteTestTmpdir())));
  2134    const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  2135  
  2136    const Cleanup dir_mount = ASSERT_NO_ERRNO_AND_VALUE(
  2137        Mount("", dir.path(), kTmpfs, 0, "", MNT_DETACH));
  2138    ASSERT_THAT(mount(NULL, dir.path().c_str(), NULL, MS_SHARED, NULL),
  2139                SyscallSucceeds());
  2140    const TempPath child_dir =
  2141        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir.path()));
  2142    const std::string file_path = JoinPath(child_dir.path(), "foo");
  2143    const std::string file2_path = JoinPath(child_dir.path(), "boo");
  2144  
  2145    const std::function<void()> parent = [&] {
  2146      TEST_CHECK_SUCCESS(
  2147          mount("child", child_dir.path().c_str(), kTmpfs, 0, NULL));
  2148      TEST_CHECK_SUCCESS(open(file_path.c_str(), O_CREAT | O_RDWR, 0777));
  2149    };
  2150    const std::function<void()> child = [&] {
  2151      TEST_CHECK_SUCCESS(access(JoinPath(child_dir.path(), "foo").c_str(), F_OK));
  2152  
  2153      // These mount operations will not propagate to the other namespace
  2154      // because it is a slave mount.
  2155      TEST_CHECK_SUCCESS(umount2(child_dir.path().c_str(), MNT_DETACH));
  2156      TEST_CHECK_SUCCESS(
  2157          mount("test2", child_dir.path().c_str(), kTmpfs, 0, NULL));
  2158      TEST_CHECK_SUCCESS(mknod(file2_path.c_str(), 0777 | S_IFREG, 0));
  2159  
  2160      TEST_CHECK_SUCCESS(umount2(child_dir.path().c_str(), MNT_DETACH));
  2161      // This should fail because the mount is locked.
  2162      TEST_CHECK_ERRNO(umount2(child_dir.path().c_str(), MNT_DETACH), EINVAL);
  2163  
  2164      // Check that there is a master entry in mountinfo.
  2165      int fd = open("/proc/self/mountinfo", O_RDONLY);
  2166      TEST_CHECK(fd >= 0);
  2167      char child_mountinfo[0x8000];
  2168      int size = 0;
  2169      while (true) {
  2170        int ret =
  2171            read(fd, child_mountinfo + size, sizeof(child_mountinfo) - size);
  2172        TEST_CHECK(ret != -1);
  2173        size += ret;
  2174        if (ret == 0) {
  2175          break;
  2176        }
  2177      }
  2178      TEST_CHECK(absl::StrContains(child_mountinfo, "master:"));
  2179    };
  2180    EXPECT_THAT(InForkedUserMountNamespace(parent, child),
  2181                IsPosixErrorOkAndHolds(0));
  2182  
  2183    // Check that the test mount is still here.
  2184    EXPECT_EQ(Open(file2_path, O_RDWR).error().errno_value(), ENOENT);
  2185    EXPECT_THAT(umount2(child_dir.path().c_str(), MNT_DETACH), SyscallSucceeds());
  2186  }
  2187  
  2188  TEST(MountTest, LockedMountStopsNonRecBind) {
  2189    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  2190    SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(IsOverlayfs(GetAbsoluteTestTmpdir())));
  2191  
  2192    const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  2193    const Cleanup dir_mount = ASSERT_NO_ERRNO_AND_VALUE(
  2194        Mount("", dir.path(), kTmpfs, 0, "", MNT_DETACH));
  2195    const TempPath child_dir =
  2196        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir.path()));
  2197    const Cleanup child_mount = ASSERT_NO_ERRNO_AND_VALUE(
  2198        Mount("", child_dir.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
  2199    const std::string foo_dir = JoinPath(dir.path(), "foo");
  2200  
  2201    const std::function<void()> child_fn = [&] {
  2202      TEST_CHECK_SUCCESS(mkdir(foo_dir.c_str(), 0700));
  2203      TEST_CHECK_ERRNO(
  2204          mount(dir.path().c_str(), foo_dir.c_str(), "", MS_BIND, ""), EINVAL);
  2205      TEST_CHECK_SUCCESS(
  2206          mount(dir.path().c_str(), foo_dir.c_str(), "", MS_BIND | MS_REC, ""));
  2207    };
  2208    EXPECT_THAT(InForkedUserMountNamespace([] {}, child_fn),
  2209                IsPosixErrorOkAndHolds(0));
  2210  }
  2211  
  2212  // This test checks that a mount tree that propagates from a more privileged
  2213  // mount namespace cannot be partially unmounted. It must be unmounted as a
  2214  // single unit as described in point 4 of the notes in
  2215  // https://man7.org/linux/man-pages/man7/mount_namespaces.7.html. This test
  2216  // also checks that unmounting a propagated mount tree does not reveal the
  2217  // contents of overmounted filesystems from the more privileged mount namespace.
  2218  TEST(MountTest, UmountPropagatedSubtreeFromPrivilegedNS) {
  2219    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  2220    SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(IsOverlayfs(GetAbsoluteTestTmpdir())));
  2221  
  2222    const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  2223    const Cleanup dir_mount = ASSERT_NO_ERRNO_AND_VALUE(
  2224        Mount(dir.path(), dir.path(), "", MS_BIND, "", MNT_DETACH));
  2225    ASSERT_THAT(mount(NULL, dir.path().c_str(), NULL, MS_SHARED, NULL),
  2226                SyscallSucceeds());
  2227  
  2228    const TempPath child_dir =
  2229        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir.path()));
  2230    const TempPath sibling_dir =
  2231        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(dir.path()));
  2232    const Cleanup child_mount = ASSERT_NO_ERRNO_AND_VALUE(
  2233        Mount("", child_dir.path(), kTmpfs, 0, "", MNT_DETACH));
  2234    ASSERT_THAT(mount(NULL, child_dir.path().c_str(), NULL, MS_PRIVATE, NULL),
  2235                SyscallSucceeds());
  2236  
  2237    const TempPath grandchild_dir =
  2238        ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(child_dir.path()));
  2239    ASSERT_THAT(open(JoinPath(grandchild_dir.path(), "foo").c_str(),
  2240                     O_CREAT | O_RDWR, 0777),
  2241                SyscallSucceeds());
  2242    const Cleanup grandchild_mnt = ASSERT_NO_ERRNO_AND_VALUE(
  2243        Mount("", grandchild_dir.path(), kTmpfs, 0, "", MNT_DETACH));
  2244    ASSERT_THAT(
  2245        mount(NULL, grandchild_dir.path().c_str(), NULL, MS_PRIVATE, NULL),
  2246        SyscallSucceeds());
  2247    const std::string grandsibling_dir =
  2248        JoinPath(sibling_dir.path(), Basename(grandchild_dir.path()));
  2249  
  2250    const std::function<void()> parent = [&] {
  2251      TEST_CHECK_SUCCESS(mount(child_dir.path().c_str(),
  2252                               sibling_dir.path().c_str(), "", MS_BIND | MS_REC,
  2253                               ""));
  2254      TEST_CHECK_SUCCESS(
  2255          mount("", sibling_dir.path().c_str(), "", MS_PRIVATE | MS_REC, ""));
  2256    };
  2257    // You can umount an entire subtree that propagated from a more privileged
  2258    // mount namespace, but can't umount only part of the subtree.
  2259    const std::string file_path =
  2260        JoinPath(Basename(grandchild_dir.path()), "foo");
  2261    const std::function<void()> child = [&] {
  2262      TEST_CHECK_ERRNO(umount2(grandsibling_dir.c_str(), MNT_DETACH), EINVAL);
  2263      int dirfd = open(sibling_dir.path().c_str(), O_RDONLY | O_DIRECTORY);
  2264      TEST_PCHECK(dirfd >= 0);
  2265      TEST_CHECK_SUCCESS(umount2(sibling_dir.path().c_str(), MNT_DETACH));
  2266      // Check to ensure you cannot access an overmounted file with openat after
  2267      // the mount unit has been destroyed.
  2268      TEST_CHECK_ERRNO(openat(dirfd, file_path.c_str(), O_RDONLY), ENOENT);
  2269    };
  2270    EXPECT_THAT(InForkedUserMountNamespace(parent, child),
  2271                IsPosixErrorOkAndHolds(0));
  2272  }
  2273  
  2274  TEST(MountTest, MountFailsOnPseudoFilesystemMountpoint) {
  2275    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  2276    auto const fd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, 0));
  2277    std::string path = absl::StrCat("/proc/self/fd/", fd.get());
  2278    EXPECT_THAT(mount("test", path.c_str(), kTmpfs, 0, 0),
  2279                SyscallFailsWithErrno(EINVAL));
  2280  }
  2281  
  2282  TEST(MountTest, ChangeMountFlags) {
  2283    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  2284  
  2285    const auto flag = MS_NODEV;
  2286    const auto dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  2287    const auto dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  2288    const auto mount_cleanup = ASSERT_NO_ERRNO_AND_VALUE(
  2289        Mount(dir1.path(), dir2.path(), kTmpfs, MS_BIND, "", 0));
  2290  
  2291    struct statfs st;
  2292    EXPECT_THAT(mount(dir1.path().c_str(), dir2.path().c_str(), kTmpfs,
  2293                      MS_REMOUNT | MS_BIND | flag, ""),
  2294                SyscallSucceeds());
  2295    EXPECT_THAT(statfs(dir2.path().c_str(), &st), SyscallSucceeds());
  2296    EXPECT_EQ(st.f_flags & flag, flag);
  2297    // Resets mount flags.
  2298    EXPECT_THAT(mount(dir1.path().c_str(), dir2.path().c_str(), kTmpfs,
  2299                      MS_REMOUNT | MS_BIND, ""),
  2300                SyscallSucceeds());
  2301    ASSERT_THAT(statfs(dir2.path().c_str(), &st), SyscallSucceeds());
  2302    ASSERT_EQ(st.f_flags & flag, 0);
  2303  }
  2304  
  2305  TEST(MountTest, RemountUnmounted) {
  2306    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  2307  
  2308    auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  2309  
  2310    EXPECT_THAT(mount("", dir.path().c_str(), kTmpfs, MS_REMOUNT, ""),
  2311                SyscallFailsWithErrno(EINVAL));
  2312  }
  2313  
  2314  TEST(MountTest, DetachedMountBindFails) {
  2315    SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
  2316  
  2317    const TempPath path1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  2318    Cleanup mount_cleanup = ASSERT_NO_ERRNO_AND_VALUE(
  2319        Mount("", path1.path().c_str(), kTmpfs, 0, "", MNT_DETACH));
  2320    mount_cleanup.Release();
  2321    const FileDescriptor fd =
  2322        ASSERT_NO_ERRNO_AND_VALUE(Open(path1.path().c_str(), O_RDONLY));
  2323    std::string fd_path = absl::Substitute("/proc/self/fd/$0", fd.get());
  2324    ASSERT_THAT(umount2(path1.path().c_str(), MNT_DETACH), SyscallSucceeds());
  2325    const TempPath path2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  2326  
  2327    EXPECT_THAT(mount(fd_path.c_str(), path2.path().c_str(), "", MS_BIND, 0),
  2328                SyscallFailsWithErrno(EINVAL));
  2329  }
  2330  
  2331  }  // namespace
  2332  
  2333  }  // namespace testing
  2334  }  // namespace gvisor