diff --git a/pkg/sentry/vfs/mount.go b/pkg/sentry/vfs/mount.go index ca154986d..269b805d8 100644 --- a/pkg/sentry/vfs/mount.go +++ b/pkg/sentry/vfs/mount.go @@ -221,6 +221,12 @@ func (vfs *VirtualFilesystem) ConnectMountAt(ctx context.Context, creds *auth.Cr if err != nil { return err } + // This is equivalent to checking for SB_NOUSER in Linux, which is set on all + // anon mounts and sentry-internal filesystems like pipefs. + if vd.mount.ns == nil { + vd.DecRef(ctx) + return linuxerr.EINVAL + } vfs.lockMounts() defer vfs.unlockMounts(ctx) tree := vfs.preparePropagationTree(mnt, vd) @@ -373,6 +379,12 @@ func (vfs *VirtualFilesystem) BindAt(ctx context.Context, creds *auth.Credential if err != nil { return nil, err } + // This is equivalent to checking for SB_NOUSER in Linux, which is set on all + // anon mounts. + if targetVd.mount == vfs.anonMount { + targetVd.DecRef(ctx) + return nil, linuxerr.EINVAL + } vfs.lockMounts() defer vfs.unlockMounts(ctx) diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD index eeb357302..294be7380 100644 --- a/test/syscalls/linux/BUILD +++ b/test/syscalls/linux/BUILD @@ -1409,6 +1409,7 @@ cc_binary( "@com_google_absl//absl/strings", "@com_google_absl//absl/time", gtest, + "//test/util:eventfd_util", "//test/util:mount_util", "//test/util:multiprocess_util", "//test/util:posix_error", diff --git a/test/syscalls/linux/mount.cc b/test/syscalls/linux/mount.cc index a0d1b3aab..984759353 100644 --- a/test/syscalls/linux/mount.cc +++ b/test/syscalls/linux/mount.cc @@ -48,6 +48,7 @@ #include "absl/time/clock.h" #include "absl/time/time.h" #include "test/util/capability_util.h" +#include "test/util/eventfd_util.h" #include "test/util/file_descriptor.h" #include "test/util/fs_util.h" #include "test/util/linux_capability_util.h" @@ -1513,6 +1514,14 @@ TEST(MountTest, MountNamespacePropagation) { EXPECT_THAT(umount2(child_dir.c_str(), MNT_DETACH), SyscallSucceeds()); } +TEST(MountTest, MountFailsOnPseudoFilesystemMountpoint) { + SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN))); + auto const fd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, 0)); + std::string path = absl::StrCat("/proc/self/fd/", fd.get()); + EXPECT_THAT(mount("test", path.c_str(), "tmpfs", 0, 0), + SyscallFailsWithErrno(EINVAL)); +} + } // namespace } // namespace testing