diff --git a/pkg/sentry/fsimpl/kernfs/filesystem.go b/pkg/sentry/fsimpl/kernfs/filesystem.go index 9572fea59..5dc4499b2 100644 --- a/pkg/sentry/fsimpl/kernfs/filesystem.go +++ b/pkg/sentry/fsimpl/kernfs/filesystem.go @@ -618,6 +618,19 @@ afterTrailingSymlink: if err := child.inode.CheckPermissions(ctx, rp.Credentials(), ats); err != nil { return nil, err } + if child.isDir() { + // Can't open directories with O_CREAT. + if opts.Flags&linux.O_CREAT != 0 { + return nil, linuxerr.EISDIR + } + // Can't open directories writably. + if ats&vfs.MayWrite != 0 { + return nil, linuxerr.EISDIR + } + if opts.Flags&linux.O_DIRECT != 0 { + return nil, linuxerr.EINVAL + } + } // Open may block so we need to unlock fs.mu. IncRef child to prevent // its destruction while fs.mu is unlocked. child.IncRef() diff --git a/pkg/sentry/fsimpl/tmpfs/filesystem.go b/pkg/sentry/fsimpl/tmpfs/filesystem.go index f2a98bc2b..1dd8589f0 100644 --- a/pkg/sentry/fsimpl/tmpfs/filesystem.go +++ b/pkg/sentry/fsimpl/tmpfs/filesystem.go @@ -483,10 +483,17 @@ func (d *dentry) open(ctx context.Context, rp *vfs.ResolvingPath, opts *vfs.Open } return &fd.vfsfd, nil case *directory: + // Can't open directories with O_CREAT. + if opts.Flags&linux.O_CREAT != 0 { + return nil, linuxerr.EISDIR + } // Can't open directories writably. if ats&vfs.MayWrite != 0 { return nil, linuxerr.EISDIR } + if opts.Flags&linux.O_DIRECT != 0 { + return nil, linuxerr.EINVAL + } var fd directoryFD fd.LockFD.Init(&d.inode.locks) if err := fd.vfsfd.Init(&fd, opts.Flags, rp.Mount(), &d.vfsd, &vfs.FileDescriptionOptions{AllowDirectIO: true}); err != nil { diff --git a/test/syscalls/linux/open.cc b/test/syscalls/linux/open.cc index 5ba14af86..cc74ef850 100644 --- a/test/syscalls/linux/open.cc +++ b/test/syscalls/linux/open.cc @@ -99,17 +99,17 @@ TEST_F(OpenTest, OCreateDirectory) { auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); // Normal case: existing directory. - ASSERT_THAT(open(dir.path().c_str(), O_RDWR | O_CREAT, 0666), + ASSERT_THAT(open(dir.path().c_str(), O_RDONLY | O_CREAT, 0666), SyscallFailsWithErrno(EISDIR)); // Trailing separator on existing directory. - ASSERT_THAT(open(dir.path().append("/").c_str(), O_RDWR | O_CREAT, 0666), + ASSERT_THAT(open(dir.path().append("/").c_str(), O_RDONLY | O_CREAT, 0666), SyscallFailsWithErrno(EISDIR)); // Trailing separator on non-existing directory. ASSERT_THAT(open(JoinPath(dir.path(), "non-existent").append("/").c_str(), - O_RDWR | O_CREAT, 0666), + O_RDONLY | O_CREAT, 0666), SyscallFailsWithErrno(EISDIR)); // "." special case. - ASSERT_THAT(open(JoinPath(dir.path(), ".").c_str(), O_RDWR | O_CREAT, 0666), + ASSERT_THAT(open(JoinPath(dir.path(), ".").c_str(), O_RDONLY | O_CREAT, 0666), SyscallFailsWithErrno(EISDIR)); } @@ -399,6 +399,11 @@ TEST_F(OpenTest, DirectoryWritableFails) { SyscallFailsWithErrno(EISDIR)); } +TEST_F(OpenTest, DirectoryDirectFails) { + ASSERT_THAT(open(GetAbsoluteTestTmpdir().c_str(), O_RDONLY | O_DIRECT), + SyscallFailsWithErrno(EINVAL)); +} + TEST_F(OpenTest, FileNotDirectory) { // Create a file and try to open it with O_DIRECTORY. auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());