From 12a4912aedc834fc8f404dc1ffeaa37088dd2d6b Mon Sep 17 00:00:00 2001 From: Kevin Krakauer Date: Tue, 14 Aug 2018 15:48:52 -0700 Subject: [PATCH] Fix `ls -laR | wc -l` hanging. stat()-ing /proc/PID/fd/FD incremented but didn't decrement the refcount for FD. This behavior wasn't usually noticeable, but in the above case: - ls would never decrement the refcount of the write end of the pipe to 0. - This caused the write end of the pipe never to close. - wc would then hang read()-ing from the pipe. PiperOrigin-RevId: 208728817 Change-Id: I4fca1ba5ca24e4108915a1d30b41dc63da40604d --- pkg/sentry/fs/proc/fds.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/pkg/sentry/fs/proc/fds.go b/pkg/sentry/fs/proc/fds.go index cca8f874c..dada8f982 100644 --- a/pkg/sentry/fs/proc/fds.go +++ b/pkg/sentry/fs/proc/fds.go @@ -94,7 +94,7 @@ type fd struct { *fs.File } -// newFD returns a new fd based on an existing file. +// newFd returns a new fd based on an existing file. // // This inherits one reference to the file. func newFd(t *kernel.Task, f *fs.File, msrc *fs.MountSource) *fs.Inode { @@ -131,6 +131,11 @@ func (f *fd) Truncate(context.Context, *fs.Inode, int64) error { return nil } +func (f *fd) Release(ctx context.Context) { + f.Symlink.Release(ctx) + f.File.DecRef() +} + // Close releases the reference on the file. func (f *fd) Close() error { f.DecRef() @@ -204,13 +209,14 @@ func (f *fdDir) DeprecatedReaddir(ctx context.Context, dirCtx *fs.DirCtx, offset type fdInfo struct { ramfs.File + file *fs.File flags fs.FileFlags fdFlags kernel.FDFlags } // newFdInfo returns a new fdInfo based on an existing file. func newFdInfo(t *kernel.Task, file *fs.File, fdFlags kernel.FDFlags, msrc *fs.MountSource) *fs.Inode { - fdi := &fdInfo{flags: file.Flags(), fdFlags: fdFlags} + fdi := &fdInfo{file: file, flags: file.Flags(), fdFlags: fdFlags} fdi.InitFile(t, fs.RootOwner, fs.FilePermissions{User: fs.PermMask{Read: true}}) // TODO: Get pos, locks, and other data. For now we only // have flags. @@ -231,6 +237,11 @@ func (*fdInfo) Truncate(ctx context.Context, inode *fs.Inode, size int64) error return ramfs.ErrInvalidOp } +func (f *fdInfo) Release(ctx context.Context) { + f.File.Release(ctx) + f.file.DecRef() +} + // fdInfoDir implements /proc/TID/fdinfo. It embeds an fdDir, but overrides // Lookup and Readdir. //