Make anonfs return ENOTDIR for open(O_DIRECTORY) calls.

All anonfs dentries are non-directories. So all FilesystemImpl
methods that would require an anonDentry to be a directory should
return ENOTDIR.

PiperOrigin-RevId: 455271653
This commit is contained in:
Ayush Ranjan
2022-06-15 19:07:24 -07:00
committed by gVisor bot
parent 34d2ad28d0
commit 8011b8d6d2
4 changed files with 47 additions and 37 deletions
+11 -11
View File
@@ -100,7 +100,7 @@ func (fs *anonFilesystem) Sync(ctx context.Context) error {
// AccessAt implements vfs.Filesystem.Impl.AccessAt.
func (fs *anonFilesystem) AccessAt(ctx context.Context, rp *ResolvingPath, creds *auth.Credentials, ats AccessTypes) error {
if !rp.Done() {
if !rp.Done() || rp.MustBeDir() {
return linuxerr.ENOTDIR
}
return GenericCheckPermissions(creds, ats, anonFileMode, anonFileUID, anonFileGID)
@@ -108,7 +108,7 @@ func (fs *anonFilesystem) AccessAt(ctx context.Context, rp *ResolvingPath, creds
// GetDentryAt implements FilesystemImpl.GetDentryAt.
func (fs *anonFilesystem) GetDentryAt(ctx context.Context, rp *ResolvingPath, opts GetDentryOptions) (*Dentry, error) {
if !rp.Done() {
if !rp.Done() || rp.MustBeDir() {
return nil, linuxerr.ENOTDIR
}
if opts.CheckSearchable {
@@ -153,7 +153,7 @@ func (fs *anonFilesystem) MknodAt(ctx context.Context, rp *ResolvingPath, opts M
// OpenAt implements FilesystemImpl.OpenAt.
func (fs *anonFilesystem) OpenAt(ctx context.Context, rp *ResolvingPath, opts OpenOptions) (*FileDescription, error) {
if !rp.Done() {
if !rp.Done() || rp.MustBeDir() {
return nil, linuxerr.ENOTDIR
}
return nil, linuxerr.ENODEV
@@ -161,7 +161,7 @@ func (fs *anonFilesystem) OpenAt(ctx context.Context, rp *ResolvingPath, opts Op
// ReadlinkAt implements FilesystemImpl.ReadlinkAt.
func (fs *anonFilesystem) ReadlinkAt(ctx context.Context, rp *ResolvingPath) (string, error) {
if !rp.Done() {
if !rp.Done() || rp.MustBeDir() {
return "", linuxerr.ENOTDIR
}
return "", linuxerr.EINVAL
@@ -185,7 +185,7 @@ func (fs *anonFilesystem) RmdirAt(ctx context.Context, rp *ResolvingPath) error
// SetStatAt implements FilesystemImpl.SetStatAt.
func (fs *anonFilesystem) SetStatAt(ctx context.Context, rp *ResolvingPath, opts SetStatOptions) error {
if !rp.Done() {
if !rp.Done() || rp.MustBeDir() {
return linuxerr.ENOTDIR
}
// Linux actually permits anon_inode_inode's metadata to be set, which is
@@ -196,7 +196,7 @@ func (fs *anonFilesystem) SetStatAt(ctx context.Context, rp *ResolvingPath, opts
// StatAt implements FilesystemImpl.StatAt.
func (fs *anonFilesystem) StatAt(ctx context.Context, rp *ResolvingPath, opts StatOptions) (linux.Statx, error) {
if !rp.Done() {
if !rp.Done() || rp.MustBeDir() {
return linux.Statx{}, linuxerr.ENOTDIR
}
// See fs/anon_inodes.c:anon_inode_init() => fs/libfs.c:alloc_anon_inode().
@@ -217,7 +217,7 @@ func (fs *anonFilesystem) StatAt(ctx context.Context, rp *ResolvingPath, opts St
// StatFSAt implements FilesystemImpl.StatFSAt.
func (fs *anonFilesystem) StatFSAt(ctx context.Context, rp *ResolvingPath) (linux.Statfs, error) {
if !rp.Done() {
if !rp.Done() || rp.MustBeDir() {
return linux.Statfs{}, linuxerr.ENOTDIR
}
return linux.Statfs{
@@ -255,7 +255,7 @@ func (fs *anonFilesystem) BoundEndpointAt(ctx context.Context, rp *ResolvingPath
// ListXattrAt implements FilesystemImpl.ListXattrAt.
func (fs *anonFilesystem) ListXattrAt(ctx context.Context, rp *ResolvingPath, size uint64) ([]string, error) {
if !rp.Done() {
if !rp.Done() || rp.MustBeDir() {
return nil, linuxerr.ENOTDIR
}
return nil, nil
@@ -263,7 +263,7 @@ func (fs *anonFilesystem) ListXattrAt(ctx context.Context, rp *ResolvingPath, si
// GetXattrAt implements FilesystemImpl.GetXattrAt.
func (fs *anonFilesystem) GetXattrAt(ctx context.Context, rp *ResolvingPath, opts GetXattrOptions) (string, error) {
if !rp.Done() {
if !rp.Done() || rp.MustBeDir() {
return "", linuxerr.ENOTDIR
}
return "", linuxerr.ENOTSUP
@@ -271,7 +271,7 @@ func (fs *anonFilesystem) GetXattrAt(ctx context.Context, rp *ResolvingPath, opt
// SetXattrAt implements FilesystemImpl.SetXattrAt.
func (fs *anonFilesystem) SetXattrAt(ctx context.Context, rp *ResolvingPath, opts SetXattrOptions) error {
if !rp.Done() {
if !rp.Done() || rp.MustBeDir() {
return linuxerr.ENOTDIR
}
return linuxerr.EPERM
@@ -279,7 +279,7 @@ func (fs *anonFilesystem) SetXattrAt(ctx context.Context, rp *ResolvingPath, opt
// RemoveXattrAt implements FilesystemImpl.RemoveXattrAt.
func (fs *anonFilesystem) RemoveXattrAt(ctx context.Context, rp *ResolvingPath, name string) error {
if !rp.Done() {
if !rp.Done() || rp.MustBeDir() {
return linuxerr.ENOTDIR
}
return linuxerr.EPERM
+1 -1
View File
@@ -377,7 +377,7 @@ func (rp *ResolvingPath) relpathPrepend(path fspath.Path) {
// HandleJump is called when the current path component is a "magic" link to
// the given VirtualDentry, like /proc/[pid]/fd/[fd]. If the calling Filesystem
// method should continue path traversal, HandleMagicSymlink updates the path
// method should continue path traversal, HandleJump updates the path
// component stream to reflect the magic link target and returns nil. Otherwise
// it returns a non-nil error.
//
+1
View File
@@ -1777,6 +1777,7 @@ cc_binary(
"@com_google_absl//absl/synchronization",
"@com_google_absl//absl/time",
gtest,
"//test/util:eventfd_util",
"//test/util:memory_util",
"//test/util:multiprocess_util",
"//test/util:posix_error",
+34 -25
View File
@@ -63,6 +63,7 @@
#include "absl/time/time.h"
#include "test/util/capability_util.h"
#include "test/util/cleanup.h"
#include "test/util/eventfd_util.h"
#include "test/util/file_descriptor.h"
#include "test/util/fs_util.h"
#include "test/util/memory_util.h"
@@ -1662,32 +1663,30 @@ TEST(ProcPidStatusTest, HasBasicFields) {
Pair("PPid", absl::StrCat(getppid())),
}));
uid_t ruid, euid, suid;
ASSERT_THAT(getresuid(&ruid, &euid, &suid), SyscallSucceeds());
gid_t rgid, egid, sgid;
ASSERT_THAT(getresgid(&rgid, &egid, &sgid), SyscallSucceeds());
std::vector<gid_t> supplementary_gids;
int ngids = getgroups(0, nullptr);
supplementary_gids.resize(ngids);
ASSERT_THAT(getgroups(ngids, supplementary_gids.data()),
SyscallSucceeds());
uid_t ruid, euid, suid;
ASSERT_THAT(getresuid(&ruid, &euid, &suid), SyscallSucceeds());
gid_t rgid, egid, sgid;
ASSERT_THAT(getresgid(&rgid, &egid, &sgid), SyscallSucceeds());
std::vector<gid_t> supplementary_gids;
int ngids = getgroups(0, nullptr);
supplementary_gids.resize(ngids);
ASSERT_THAT(getgroups(ngids, supplementary_gids.data()), SyscallSucceeds());
EXPECT_THAT(
status,
IsSupersetOf(std::vector<
::testing::Matcher<std::pair<std::string, std::string>>>{
// gVisor doesn't support fsuid/gid, and even if it did there is
// no getfsuid/getfsgid().
Pair("Uid", StartsWith(absl::StrFormat("%d\t%d\t%d\t", ruid, euid,
suid))),
Pair("Gid", StartsWith(absl::StrFormat("%d\t%d\t%d\t", rgid, egid,
sgid))),
// ParseProcStatus strips leading whitespace for each value,
// so if the Groups line is empty then the trailing space is
// stripped.
Pair("Groups",
StartsWith(absl::StrJoin(supplementary_gids, " "))),
}));
EXPECT_THAT(
status,
IsSupersetOf(std::vector<
::testing::Matcher<std::pair<std::string, std::string>>>{
// gVisor doesn't support fsuid/gid, and even if it did there is
// no getfsuid/getfsgid().
Pair("Uid",
StartsWith(absl::StrFormat("%d\t%d\t%d\t", ruid, euid, suid))),
Pair("Gid",
StartsWith(absl::StrFormat("%d\t%d\t%d\t", rgid, egid, sgid))),
// ParseProcStatus strips leading whitespace for each value,
// so if the Groups line is empty then the trailing space is
// stripped.
Pair("Groups", StartsWith(absl::StrJoin(supplementary_gids, " "))),
}));
});
}
@@ -2734,6 +2733,16 @@ TEST(Proc, ResolveSymlinkToProc) {
EXPECT_EQ(target, JoinPath("/proc/", absl::StrCat(getpid()), "/cmdline"));
}
// NOTE(b/236035339): Tests that opening /proc/[pid]/fd/[eventFDNum] with
// O_DIRECTORY leads to ENOTDIR.
TEST(Proc, RegressionTestB236035339) {
FileDescriptor efd =
ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_NONBLOCK | EFD_CLOEXEC));
const auto path = JoinPath("/proc/self/fd/", absl::StrCat(efd.get()));
EXPECT_THAT(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_DIRECTORY),
SyscallFailsWithErrno(ENOTDIR));
}
} // namespace
} // namespace testing
} // namespace gvisor