diff options
author | Kevin Krakauer <krakauer@google.com> | 2019-04-26 11:08:37 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2019-04-26 11:09:55 -0700 |
commit | 5f13338d30fb59241cf7f1aa6374c54c69677314 (patch) | |
tree | f56328cb60ebe16a337a555c381d87db8c287442 | |
parent | f4d34b420bd30b9c3725f9247c9145808aab0ffb (diff) |
Fix reference counting bug in /proc/PID/fdinfo/.
PiperOrigin-RevId: 245452217
Change-Id: I7164d8f57fe34c17e601079eb9410a6d95af1869
-rw-r--r-- | pkg/sentry/fs/proc/fds.go | 19 | ||||
-rw-r--r-- | test/syscalls/linux/pipe.cc | 36 |
2 files changed, 20 insertions, 35 deletions
diff --git a/pkg/sentry/fs/proc/fds.go b/pkg/sentry/fs/proc/fds.go index 939ebaba1..25da06f5d 100644 --- a/pkg/sentry/fs/proc/fds.go +++ b/pkg/sentry/fs/proc/fds.go @@ -236,24 +236,6 @@ func (f *fdDirFile) Readdir(ctx context.Context, file *fs.File, ser fs.DentrySer }) } -// fdInfoInode is a single file in /proc/TID/fdinfo/. -// -// +stateify savable -type fdInfoInode struct { - staticFileInodeOps - - file *fs.File - flags fs.FileFlags - fdFlags kernel.FDFlags -} - -var _ fs.InodeOperations = (*fdInfoInode)(nil) - -// Release implements fs.InodeOperations.Release. -func (f *fdInfoInode) Release(ctx context.Context) { - f.file.DecRef() -} - // fdInfoDir implements /proc/TID/fdinfo. It embeds an fdDir, but overrides // Lookup and Readdir. // @@ -283,6 +265,7 @@ func (fdid *fdInfoDir) Lookup(ctx context.Context, dir *fs.Inode, p string) (*fs // locks, and other data. For now we only have flags. // See https://www.kernel.org/doc/Documentation/filesystems/proc.txt flags := file.Flags().ToLinux() | fdFlags.ToLinuxFileFlags() + file.DecRef() contents := []byte(fmt.Sprintf("flags:\t0%o\n", flags)) return newStaticProcInode(ctx, dir.MountSource, contents) }) diff --git a/test/syscalls/linux/pipe.cc b/test/syscalls/linux/pipe.cc index 4731157e8..c49ec9f09 100644 --- a/test/syscalls/linux/pipe.cc +++ b/test/syscalls/linux/pipe.cc @@ -455,24 +455,26 @@ TEST_F(PipeTest, LargeFile) { EXPECT_EQ(rflags, 0); } -// Test that accessing /proc/<PID>/fd/<FD> correctly decrements the refcount of -// that file descriptor. +// Test that accesses of /proc/<PID>/fd/<FD> and /proc/<PID>/fdinfo/<FD> +// correctly decrement the refcount of that file descriptor. TEST_F(PipeTest, ProcFDReleasesFile) { - int fds[2]; - ASSERT_THAT(pipe(fds), SyscallSucceeds()); - FileDescriptor rfd(fds[0]); - FileDescriptor wfd(fds[1]); - - // Stat the pipe FD, which shouldn't alter the refcount of the write end of - // the pipe. - struct stat wst; - ASSERT_THAT(lstat(absl::StrCat("/proc/self/fd/", wfd.get()).c_str(), &wst), - SyscallSucceeds()); - - // Close the write end of the pipe and ensure that read indicates EOF. - wfd.reset(); - char buf; - ASSERT_THAT(read(rfd.get(), &buf, 1), SyscallSucceedsWithValue(0)); + std::vector<std::string> paths = {"/proc/self/fd/", "/proc/self/fdinfo/"}; + for (const std::string& path : paths) { + int fds[2]; + ASSERT_THAT(pipe(fds), SyscallSucceeds()); + FileDescriptor rfd(fds[0]); + FileDescriptor wfd(fds[1]); + + // Stat the pipe FD, which shouldn't alter the refcount of the write end of + // the pipe. + struct stat wst; + ASSERT_THAT(lstat(absl::StrCat(path.c_str(), wfd.get()).c_str(), &wst), + SyscallSucceeds()); + // Close the write end of the pipe and ensure that read indicates EOF. + wfd.reset(); + char buf; + ASSERT_THAT(read(rfd.get(), &buf, 1), SyscallSucceedsWithValue(0)); + } } } // namespace |