summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKevin Krakauer <krakauer@google.com>2019-04-26 11:08:37 -0700
committerShentubot <shentubot@google.com>2019-04-26 11:09:55 -0700
commit5f13338d30fb59241cf7f1aa6374c54c69677314 (patch)
treef56328cb60ebe16a337a555c381d87db8c287442
parentf4d34b420bd30b9c3725f9247c9145808aab0ffb (diff)
Fix reference counting bug in /proc/PID/fdinfo/.
PiperOrigin-RevId: 245452217 Change-Id: I7164d8f57fe34c17e601079eb9410a6d95af1869
-rw-r--r--pkg/sentry/fs/proc/fds.go19
-rw-r--r--test/syscalls/linux/pipe.cc36
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