diff options
author | gVisor bot <gvisor-bot@google.com> | 2021-07-13 01:36:04 +0000 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-07-13 01:36:04 +0000 |
commit | 06f349011627d6298168ceac919e27cb166675d4 (patch) | |
tree | df2b179bb06b09baee6d2cd47c714d03ae6d75f2 /pkg/sentry/fsimpl | |
parent | 289efe127e1f04f4fbb0c2a46050a6cd9c9f3b9b (diff) | |
parent | 520795aaad701854e9ffe84de1108954cf2b77f8 (diff) |
Merge release-20210705.0-15-g520795aaa (automated)
Diffstat (limited to 'pkg/sentry/fsimpl')
20 files changed, 125 insertions, 68 deletions
diff --git a/pkg/sentry/fsimpl/cgroupfs/dir_refs.go b/pkg/sentry/fsimpl/cgroupfs/dir_refs.go index 3351de386..c29f0c9ae 100644 --- a/pkg/sentry/fsimpl/cgroupfs/dir_refs.go +++ b/pkg/sentry/fsimpl/cgroupfs/dir_refs.go @@ -81,7 +81,7 @@ func (r *dirRefs) IncRef() { } } -// TryIncRef implements refs.RefCounter.TryIncRef. +// TryIncRef implements refs.TryRefCounter.TryIncRef. // // To do this safely without a loop, a speculative reference is first acquired // on the object. This allows multiple concurrent TryIncRef calls to distinguish diff --git a/pkg/sentry/fsimpl/devpts/root_inode_refs.go b/pkg/sentry/fsimpl/devpts/root_inode_refs.go index 4456ef708..e53739a90 100644 --- a/pkg/sentry/fsimpl/devpts/root_inode_refs.go +++ b/pkg/sentry/fsimpl/devpts/root_inode_refs.go @@ -81,7 +81,7 @@ func (r *rootInodeRefs) IncRef() { } } -// TryIncRef implements refs.RefCounter.TryIncRef. +// TryIncRef implements refs.TryRefCounter.TryIncRef. // // To do this safely without a loop, a speculative reference is first acquired // on the object. This allows multiple concurrent TryIncRef calls to distinguish diff --git a/pkg/sentry/fsimpl/fuse/inode_refs.go b/pkg/sentry/fsimpl/fuse/inode_refs.go index ad79c4a56..74489cf5e 100644 --- a/pkg/sentry/fsimpl/fuse/inode_refs.go +++ b/pkg/sentry/fsimpl/fuse/inode_refs.go @@ -81,7 +81,7 @@ func (r *inodeRefs) IncRef() { } } -// TryIncRef implements refs.RefCounter.TryIncRef. +// TryIncRef implements refs.TryRefCounter.TryIncRef. // // To do this safely without a loop, a speculative reference is first acquired // on the object. This allows multiple concurrent TryIncRef calls to distinguish diff --git a/pkg/sentry/fsimpl/host/connected_endpoint_refs.go b/pkg/sentry/fsimpl/host/connected_endpoint_refs.go index 4bc9294bf..c0a87f656 100644 --- a/pkg/sentry/fsimpl/host/connected_endpoint_refs.go +++ b/pkg/sentry/fsimpl/host/connected_endpoint_refs.go @@ -81,7 +81,7 @@ func (r *ConnectedEndpointRefs) IncRef() { } } -// TryIncRef implements refs.RefCounter.TryIncRef. +// TryIncRef implements refs.TryRefCounter.TryIncRef. // // To do this safely without a loop, a speculative reference is first acquired // on the object. This allows multiple concurrent TryIncRef calls to distinguish diff --git a/pkg/sentry/fsimpl/host/inode_refs.go b/pkg/sentry/fsimpl/host/inode_refs.go index 1ca9a7868..112f39850 100644 --- a/pkg/sentry/fsimpl/host/inode_refs.go +++ b/pkg/sentry/fsimpl/host/inode_refs.go @@ -81,7 +81,7 @@ func (r *inodeRefs) IncRef() { } } -// TryIncRef implements refs.RefCounter.TryIncRef. +// TryIncRef implements refs.TryRefCounter.TryIncRef. // // To do this safely without a loop, a speculative reference is first acquired // on the object. This allows multiple concurrent TryIncRef calls to distinguish diff --git a/pkg/sentry/fsimpl/kernfs/kernfs.go b/pkg/sentry/fsimpl/kernfs/kernfs.go index 6f699c9cd..0e2867d49 100644 --- a/pkg/sentry/fsimpl/kernfs/kernfs.go +++ b/pkg/sentry/fsimpl/kernfs/kernfs.go @@ -52,7 +52,7 @@ // vfs.VirtualFilesystem.mountMu // vfs.Dentry.mu // (inode implementation locks, if any) -// kernfs.Filesystem.droppedDentriesMu +// kernfs.Filesystem.deferredDecRefsMu package kernfs import ( @@ -76,12 +76,12 @@ import ( type Filesystem struct { vfsfs vfs.Filesystem - droppedDentriesMu sync.Mutex `state:"nosave"` + deferredDecRefsMu sync.Mutex `state:"nosave"` - // droppedDentries is a list of dentries waiting to be DecRef()ed. This is + // deferredDecRefs is a list of dentries waiting to be DecRef()ed. This is // used to defer dentry destruction until mu can be acquired for - // writing. Protected by droppedDentriesMu. - droppedDentries []*Dentry + // writing. Protected by deferredDecRefsMu. + deferredDecRefs []refsvfs2.RefCounter // mu synchronizes the lifetime of Dentries on this filesystem. Holding it // for reading guarantees continued existence of any resolved dentries, but @@ -131,25 +131,49 @@ type Filesystem struct { // deferDecRef defers dropping a dentry ref until the next call to // processDeferredDecRefs{,Locked}. See comment on Filesystem.mu. // This may be called while Filesystem.mu or Dentry.dirMu is locked. -func (fs *Filesystem) deferDecRef(d *Dentry) { - fs.droppedDentriesMu.Lock() - fs.droppedDentries = append(fs.droppedDentries, d) - fs.droppedDentriesMu.Unlock() +func (fs *Filesystem) deferDecRef(d refsvfs2.RefCounter) { + fs.deferredDecRefsMu.Lock() + fs.deferredDecRefs = append(fs.deferredDecRefs, d) + fs.deferredDecRefsMu.Unlock() +} + +// SafeDecRefFD safely DecRef the FileDescription making sure DecRef is deferred +// in case Filesystem.mu is held. See comment on Filesystem.mu. +func (fs *Filesystem) SafeDecRefFD(ctx context.Context, fd *vfs.FileDescription) { + if d, ok := fd.Dentry().Impl().(*Dentry); ok && d.fs == fs { + // Only defer if dentry belongs to this filesystem, since locks cannot cross + // filesystems. + fs.deferDecRef(fd) + return + } + fd.DecRef(ctx) +} + +// SafeDecRef safely DecRef the virtual dentry making sure DecRef is deferred +// in case Filesystem.mu is held. See comment on Filesystem.mu. +func (fs *Filesystem) SafeDecRef(ctx context.Context, vd vfs.VirtualDentry) { + if d, ok := vd.Dentry().Impl().(*Dentry); ok && d.fs == fs { + // Only defer if dentry belongs to this filesystem, since locks cannot cross + // filesystems. + fs.deferDecRef(&vd) + return + } + vd.DecRef(ctx) } // processDeferredDecRefs calls vfs.Dentry.DecRef on all dentries in the -// droppedDentries list. See comment on Filesystem.mu. +// deferredDecRefs list. See comment on Filesystem.mu. // // Precondition: Filesystem.mu or Dentry.dirMu must NOT be locked. func (fs *Filesystem) processDeferredDecRefs(ctx context.Context) { - fs.droppedDentriesMu.Lock() - for _, d := range fs.droppedDentries { - // Defer the DecRef call so that we are not holding droppedDentriesMu + fs.deferredDecRefsMu.Lock() + for _, d := range fs.deferredDecRefs { + // Defer the DecRef call so that we are not holding deferredDecRefsMu // when DecRef is called. defer d.DecRef(ctx) } - fs.droppedDentries = fs.droppedDentries[:0] // Keep slice memory for reuse. - fs.droppedDentriesMu.Unlock() + fs.deferredDecRefs = fs.deferredDecRefs[:0] // Keep slice memory for reuse. + fs.deferredDecRefsMu.Unlock() } // VFSFilesystem returns the generic vfs filesystem object. diff --git a/pkg/sentry/fsimpl/kernfs/kernfs_state_autogen.go b/pkg/sentry/fsimpl/kernfs/kernfs_state_autogen.go index 5b8d033ec..f8add23f8 100644 --- a/pkg/sentry/fsimpl/kernfs/kernfs_state_autogen.go +++ b/pkg/sentry/fsimpl/kernfs/kernfs_state_autogen.go @@ -602,7 +602,7 @@ func (fs *Filesystem) StateTypeName() string { func (fs *Filesystem) StateFields() []string { return []string{ "vfsfs", - "droppedDentries", + "deferredDecRefs", "nextInoMinusOne", "cachedDentries", "cachedDentriesLen", @@ -617,7 +617,7 @@ func (fs *Filesystem) beforeSave() {} func (fs *Filesystem) StateSave(stateSinkObject state.Sink) { fs.beforeSave() stateSinkObject.Save(0, &fs.vfsfs) - stateSinkObject.Save(1, &fs.droppedDentries) + stateSinkObject.Save(1, &fs.deferredDecRefs) stateSinkObject.Save(2, &fs.nextInoMinusOne) stateSinkObject.Save(3, &fs.cachedDentries) stateSinkObject.Save(4, &fs.cachedDentriesLen) @@ -630,7 +630,7 @@ func (fs *Filesystem) afterLoad() {} // +checklocksignore func (fs *Filesystem) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &fs.vfsfs) - stateSourceObject.Load(1, &fs.droppedDentries) + stateSourceObject.Load(1, &fs.deferredDecRefs) stateSourceObject.Load(2, &fs.nextInoMinusOne) stateSourceObject.Load(3, &fs.cachedDentries) stateSourceObject.Load(4, &fs.cachedDentriesLen) diff --git a/pkg/sentry/fsimpl/kernfs/static_directory_refs.go b/pkg/sentry/fsimpl/kernfs/static_directory_refs.go index d6180daa3..69534a2d2 100644 --- a/pkg/sentry/fsimpl/kernfs/static_directory_refs.go +++ b/pkg/sentry/fsimpl/kernfs/static_directory_refs.go @@ -81,7 +81,7 @@ func (r *StaticDirectoryRefs) IncRef() { } } -// TryIncRef implements refs.RefCounter.TryIncRef. +// TryIncRef implements refs.TryRefCounter.TryIncRef. // // To do this safely without a loop, a speculative reference is first acquired // on the object. This allows multiple concurrent TryIncRef calls to distinguish diff --git a/pkg/sentry/fsimpl/kernfs/synthetic_directory_refs.go b/pkg/sentry/fsimpl/kernfs/synthetic_directory_refs.go index c428cdead..3c5fdf15e 100644 --- a/pkg/sentry/fsimpl/kernfs/synthetic_directory_refs.go +++ b/pkg/sentry/fsimpl/kernfs/synthetic_directory_refs.go @@ -81,7 +81,7 @@ func (r *syntheticDirectoryRefs) IncRef() { } } -// TryIncRef implements refs.RefCounter.TryIncRef. +// TryIncRef implements refs.TryRefCounter.TryIncRef. // // To do this safely without a loop, a speculative reference is first acquired // on the object. This allows multiple concurrent TryIncRef calls to distinguish diff --git a/pkg/sentry/fsimpl/proc/fd_dir_inode_refs.go b/pkg/sentry/fsimpl/proc/fd_dir_inode_refs.go index bda0589f8..61138f055 100644 --- a/pkg/sentry/fsimpl/proc/fd_dir_inode_refs.go +++ b/pkg/sentry/fsimpl/proc/fd_dir_inode_refs.go @@ -81,7 +81,7 @@ func (r *fdDirInodeRefs) IncRef() { } } -// TryIncRef implements refs.RefCounter.TryIncRef. +// TryIncRef implements refs.TryRefCounter.TryIncRef. // // To do this safely without a loop, a speculative reference is first acquired // on the object. This allows multiple concurrent TryIncRef calls to distinguish diff --git a/pkg/sentry/fsimpl/proc/fd_info_dir_inode_refs.go b/pkg/sentry/fsimpl/proc/fd_info_dir_inode_refs.go index f000064ef..53fb0910a 100644 --- a/pkg/sentry/fsimpl/proc/fd_info_dir_inode_refs.go +++ b/pkg/sentry/fsimpl/proc/fd_info_dir_inode_refs.go @@ -81,7 +81,7 @@ func (r *fdInfoDirInodeRefs) IncRef() { } } -// TryIncRef implements refs.RefCounter.TryIncRef. +// TryIncRef implements refs.TryRefCounter.TryIncRef. // // To do this safely without a loop, a speculative reference is first acquired // on the object. This allows multiple concurrent TryIncRef calls to distinguish diff --git a/pkg/sentry/fsimpl/proc/proc_state_autogen.go b/pkg/sentry/fsimpl/proc/proc_state_autogen.go index ebcb21edb..f87739c23 100644 --- a/pkg/sentry/fsimpl/proc/proc_state_autogen.go +++ b/pkg/sentry/fsimpl/proc/proc_state_autogen.go @@ -460,6 +460,7 @@ func (s *fdSymlink) StateFields() []string { "InodeAttrs", "InodeNoopRefCount", "InodeSymlink", + "fs", "task", "fd", } @@ -474,8 +475,9 @@ func (s *fdSymlink) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(1, &s.InodeAttrs) stateSinkObject.Save(2, &s.InodeNoopRefCount) stateSinkObject.Save(3, &s.InodeSymlink) - stateSinkObject.Save(4, &s.task) - stateSinkObject.Save(5, &s.fd) + stateSinkObject.Save(4, &s.fs) + stateSinkObject.Save(5, &s.task) + stateSinkObject.Save(6, &s.fd) } func (s *fdSymlink) afterLoad() {} @@ -486,8 +488,9 @@ func (s *fdSymlink) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(1, &s.InodeAttrs) stateSourceObject.Load(2, &s.InodeNoopRefCount) stateSourceObject.Load(3, &s.InodeSymlink) - stateSourceObject.Load(4, &s.task) - stateSourceObject.Load(5, &s.fd) + stateSourceObject.Load(4, &s.fs) + stateSourceObject.Load(5, &s.task) + stateSourceObject.Load(6, &s.fd) } func (i *fdInfoDirInode) StateTypeName() string { @@ -546,6 +549,7 @@ func (d *fdInfoData) StateTypeName() string { func (d *fdInfoData) StateFields() []string { return []string{ "DynamicBytesFile", + "fs", "task", "fd", } @@ -557,8 +561,9 @@ func (d *fdInfoData) beforeSave() {} func (d *fdInfoData) StateSave(stateSinkObject state.Sink) { d.beforeSave() stateSinkObject.Save(0, &d.DynamicBytesFile) - stateSinkObject.Save(1, &d.task) - stateSinkObject.Save(2, &d.fd) + stateSinkObject.Save(1, &d.fs) + stateSinkObject.Save(2, &d.task) + stateSinkObject.Save(3, &d.fd) } func (d *fdInfoData) afterLoad() {} @@ -566,8 +571,9 @@ func (d *fdInfoData) afterLoad() {} // +checklocksignore func (d *fdInfoData) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &d.DynamicBytesFile) - stateSourceObject.Load(1, &d.task) - stateSourceObject.Load(2, &d.fd) + stateSourceObject.Load(1, &d.fs) + stateSourceObject.Load(2, &d.task) + stateSourceObject.Load(3, &d.fd) } func (d *auxvData) StateTypeName() string { @@ -1011,6 +1017,7 @@ func (s *exeSymlink) StateFields() []string { "InodeAttrs", "InodeNoopRefCount", "InodeSymlink", + "fs", "task", } } @@ -1024,7 +1031,8 @@ func (s *exeSymlink) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(1, &s.InodeAttrs) stateSinkObject.Save(2, &s.InodeNoopRefCount) stateSinkObject.Save(3, &s.InodeSymlink) - stateSinkObject.Save(4, &s.task) + stateSinkObject.Save(4, &s.fs) + stateSinkObject.Save(5, &s.task) } func (s *exeSymlink) afterLoad() {} @@ -1035,7 +1043,8 @@ func (s *exeSymlink) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(1, &s.InodeAttrs) stateSourceObject.Load(2, &s.InodeNoopRefCount) stateSourceObject.Load(3, &s.InodeSymlink) - stateSourceObject.Load(4, &s.task) + stateSourceObject.Load(4, &s.fs) + stateSourceObject.Load(5, &s.task) } func (s *cwdSymlink) StateTypeName() string { @@ -1048,6 +1057,7 @@ func (s *cwdSymlink) StateFields() []string { "InodeAttrs", "InodeNoopRefCount", "InodeSymlink", + "fs", "task", } } @@ -1061,7 +1071,8 @@ func (s *cwdSymlink) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(1, &s.InodeAttrs) stateSinkObject.Save(2, &s.InodeNoopRefCount) stateSinkObject.Save(3, &s.InodeSymlink) - stateSinkObject.Save(4, &s.task) + stateSinkObject.Save(4, &s.fs) + stateSinkObject.Save(5, &s.task) } func (s *cwdSymlink) afterLoad() {} @@ -1072,7 +1083,8 @@ func (s *cwdSymlink) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(1, &s.InodeAttrs) stateSourceObject.Load(2, &s.InodeNoopRefCount) stateSourceObject.Load(3, &s.InodeSymlink) - stateSourceObject.Load(4, &s.task) + stateSourceObject.Load(4, &s.fs) + stateSourceObject.Load(5, &s.task) } func (i *mountInfoData) StateTypeName() string { @@ -1082,6 +1094,7 @@ func (i *mountInfoData) StateTypeName() string { func (i *mountInfoData) StateFields() []string { return []string{ "DynamicBytesFile", + "fs", "task", } } @@ -1092,7 +1105,8 @@ func (i *mountInfoData) beforeSave() {} func (i *mountInfoData) StateSave(stateSinkObject state.Sink) { i.beforeSave() stateSinkObject.Save(0, &i.DynamicBytesFile) - stateSinkObject.Save(1, &i.task) + stateSinkObject.Save(1, &i.fs) + stateSinkObject.Save(2, &i.task) } func (i *mountInfoData) afterLoad() {} @@ -1100,7 +1114,8 @@ func (i *mountInfoData) afterLoad() {} // +checklocksignore func (i *mountInfoData) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &i.DynamicBytesFile) - stateSourceObject.Load(1, &i.task) + stateSourceObject.Load(1, &i.fs) + stateSourceObject.Load(2, &i.task) } func (i *mountsData) StateTypeName() string { @@ -1110,6 +1125,7 @@ func (i *mountsData) StateTypeName() string { func (i *mountsData) StateFields() []string { return []string{ "DynamicBytesFile", + "fs", "task", } } @@ -1120,7 +1136,8 @@ func (i *mountsData) beforeSave() {} func (i *mountsData) StateSave(stateSinkObject state.Sink) { i.beforeSave() stateSinkObject.Save(0, &i.DynamicBytesFile) - stateSinkObject.Save(1, &i.task) + stateSinkObject.Save(1, &i.fs) + stateSinkObject.Save(2, &i.task) } func (i *mountsData) afterLoad() {} @@ -1128,7 +1145,8 @@ func (i *mountsData) afterLoad() {} // +checklocksignore func (i *mountsData) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &i.DynamicBytesFile) - stateSourceObject.Load(1, &i.task) + stateSourceObject.Load(1, &i.fs) + stateSourceObject.Load(2, &i.task) } func (s *namespaceSymlink) StateTypeName() string { diff --git a/pkg/sentry/fsimpl/proc/subtasks_inode_refs.go b/pkg/sentry/fsimpl/proc/subtasks_inode_refs.go index fb3517437..bd4998cbc 100644 --- a/pkg/sentry/fsimpl/proc/subtasks_inode_refs.go +++ b/pkg/sentry/fsimpl/proc/subtasks_inode_refs.go @@ -81,7 +81,7 @@ func (r *subtasksInodeRefs) IncRef() { } } -// TryIncRef implements refs.RefCounter.TryIncRef. +// TryIncRef implements refs.TryRefCounter.TryIncRef. // // To do this safely without a loop, a speculative reference is first acquired // on the object. This allows multiple concurrent TryIncRef calls to distinguish diff --git a/pkg/sentry/fsimpl/proc/task.go b/pkg/sentry/fsimpl/proc/task.go index 2717e1359..cbbc0935a 100644 --- a/pkg/sentry/fsimpl/proc/task.go +++ b/pkg/sentry/fsimpl/proc/task.go @@ -65,8 +65,8 @@ func (fs *filesystem) newTaskInode(ctx context.Context, task *kernel.Task, pidns "io": fs.newTaskOwnedInode(ctx, task, fs.NextIno(), 0400, newIO(task, isThreadGroup)), "maps": fs.newTaskOwnedInode(ctx, task, fs.NextIno(), 0444, &mapsData{task: task}), "mem": fs.newMemInode(ctx, task, fs.NextIno(), 0400), - "mountinfo": fs.newTaskOwnedInode(ctx, task, fs.NextIno(), 0444, &mountInfoData{task: task}), - "mounts": fs.newTaskOwnedInode(ctx, task, fs.NextIno(), 0444, &mountsData{task: task}), + "mountinfo": fs.newTaskOwnedInode(ctx, task, fs.NextIno(), 0444, &mountInfoData{fs: fs, task: task}), + "mounts": fs.newTaskOwnedInode(ctx, task, fs.NextIno(), 0444, &mountsData{fs: fs, task: task}), "net": fs.newTaskNetDir(ctx, task), "ns": fs.newTaskOwnedDir(ctx, task, fs.NextIno(), 0511, map[string]kernfs.Inode{ "net": fs.newNamespaceSymlink(ctx, task, fs.NextIno(), "net"), diff --git a/pkg/sentry/fsimpl/proc/task_fds.go b/pkg/sentry/fsimpl/proc/task_fds.go index 4718fac7a..dfc0a924e 100644 --- a/pkg/sentry/fsimpl/proc/task_fds.go +++ b/pkg/sentry/fsimpl/proc/task_fds.go @@ -42,12 +42,12 @@ func getTaskFD(t *kernel.Task, fd int32) (*vfs.FileDescription, kernel.FDFlags) return file, flags } -func taskFDExists(ctx context.Context, t *kernel.Task, fd int32) bool { +func taskFDExists(ctx context.Context, fs *filesystem, t *kernel.Task, fd int32) bool { file, _ := getTaskFD(t, fd) if file == nil { return false } - file.DecRef(ctx) + fs.SafeDecRefFD(ctx, file) return true } @@ -145,7 +145,7 @@ func (i *fdDirInode) Lookup(ctx context.Context, name string) (kernfs.Inode, err return nil, syserror.ENOENT } fd := int32(fdInt) - if !taskFDExists(ctx, i.task, fd) { + if !taskFDExists(ctx, i.fs, i.task, fd) { return nil, syserror.ENOENT } return i.fs.newFDSymlink(ctx, i.task, fd, i.fs.NextIno()), nil @@ -198,6 +198,7 @@ type fdSymlink struct { kernfs.InodeNoopRefCount kernfs.InodeSymlink + fs *filesystem task *kernel.Task fd int32 } @@ -206,6 +207,7 @@ var _ kernfs.Inode = (*fdSymlink)(nil) func (fs *filesystem) newFDSymlink(ctx context.Context, task *kernel.Task, fd int32, ino uint64) kernfs.Inode { inode := &fdSymlink{ + fs: fs, task: task, fd: fd, } @@ -218,9 +220,9 @@ func (s *fdSymlink) Readlink(ctx context.Context, _ *vfs.Mount) (string, error) if file == nil { return "", syserror.ENOENT } - defer file.DecRef(ctx) + defer s.fs.SafeDecRefFD(ctx, file) root := vfs.RootFromContext(ctx) - defer root.DecRef(ctx) + defer s.fs.SafeDecRef(ctx, root) // Note: it's safe to reenter kernfs from Readlink if needed to resolve path. return s.task.Kernel().VFS().PathnameWithDeleted(ctx, root, file.VirtualDentry()) @@ -231,7 +233,7 @@ func (s *fdSymlink) Getlink(ctx context.Context, mnt *vfs.Mount) (vfs.VirtualDen if file == nil { return vfs.VirtualDentry{}, "", syserror.ENOENT } - defer file.DecRef(ctx) + defer s.fs.SafeDecRefFD(ctx, file) vd := file.VirtualDentry() vd.IncRef() return vd, "", nil @@ -239,7 +241,7 @@ func (s *fdSymlink) Getlink(ctx context.Context, mnt *vfs.Mount) (vfs.VirtualDen // Valid implements kernfs.Inode.Valid. func (s *fdSymlink) Valid(ctx context.Context) bool { - return taskFDExists(ctx, s.task, s.fd) + return taskFDExists(ctx, s.fs, s.task, s.fd) } // fdInfoDirInode represents the inode for /proc/[pid]/fdinfo directory. @@ -279,10 +281,11 @@ func (i *fdInfoDirInode) Lookup(ctx context.Context, name string) (kernfs.Inode, return nil, syserror.ENOENT } fd := int32(fdInt) - if !taskFDExists(ctx, i.task, fd) { + if !taskFDExists(ctx, i.fs, i.task, fd) { return nil, syserror.ENOENT } data := &fdInfoData{ + fs: i.fs, task: i.task, fd: fd, } @@ -316,6 +319,7 @@ func (i *fdInfoDirInode) DecRef(ctx context.Context) { type fdInfoData struct { kernfs.DynamicBytesFile + fs *filesystem task *kernel.Task fd int32 } @@ -328,7 +332,7 @@ func (d *fdInfoData) Generate(ctx context.Context, buf *bytes.Buffer) error { if file == nil { return syserror.ENOENT } - defer file.DecRef(ctx) + defer d.fs.SafeDecRefFD(ctx, file) // TODO(b/121266871): Include pos, locks, and other data. For now we only // have flags. // See https://www.kernel.org/doc/Documentation/filesystems/proc.txt @@ -339,5 +343,5 @@ func (d *fdInfoData) Generate(ctx context.Context, buf *bytes.Buffer) error { // Valid implements kernfs.Inode.Valid. func (d *fdInfoData) Valid(ctx context.Context) bool { - return taskFDExists(ctx, d.task, d.fd) + return taskFDExists(ctx, d.fs, d.task, d.fd) } diff --git a/pkg/sentry/fsimpl/proc/task_files.go b/pkg/sentry/fsimpl/proc/task_files.go index 5526cac1e..5bb6bc372 100644 --- a/pkg/sentry/fsimpl/proc/task_files.go +++ b/pkg/sentry/fsimpl/proc/task_files.go @@ -803,13 +803,17 @@ type exeSymlink struct { kernfs.InodeNoopRefCount kernfs.InodeSymlink + fs *filesystem task *kernel.Task } var _ kernfs.Inode = (*exeSymlink)(nil) func (fs *filesystem) newExeSymlink(ctx context.Context, task *kernel.Task, ino uint64) kernfs.Inode { - inode := &exeSymlink{task: task} + inode := &exeSymlink{ + fs: fs, + task: task, + } inode.Init(ctx, task.Credentials(), linux.UNNAMED_MAJOR, fs.devMinor, ino, linux.ModeSymlink|0777) return inode } @@ -820,14 +824,14 @@ func (s *exeSymlink) Readlink(ctx context.Context, _ *vfs.Mount) (string, error) if err != nil { return "", err } - defer exec.DecRef(ctx) + defer s.fs.SafeDecRef(ctx, exec) root := vfs.RootFromContext(ctx) if !root.Ok() { // It could have raced with process deletion. return "", linuxerr.ESRCH } - defer root.DecRef(ctx) + defer s.fs.SafeDecRef(ctx, root) vfsObj := exec.Mount().Filesystem().VirtualFilesystem() name, _ := vfsObj.PathnameWithDeleted(ctx, root, exec) @@ -879,13 +883,17 @@ type cwdSymlink struct { kernfs.InodeNoopRefCount kernfs.InodeSymlink + fs *filesystem task *kernel.Task } var _ kernfs.Inode = (*cwdSymlink)(nil) func (fs *filesystem) newCwdSymlink(ctx context.Context, task *kernel.Task, ino uint64) kernfs.Inode { - inode := &cwdSymlink{task: task} + inode := &cwdSymlink{ + fs: fs, + task: task, + } inode.Init(ctx, task.Credentials(), linux.UNNAMED_MAJOR, fs.devMinor, ino, linux.ModeSymlink|0777) return inode } @@ -896,14 +904,14 @@ func (s *cwdSymlink) Readlink(ctx context.Context, _ *vfs.Mount) (string, error) if err != nil { return "", err } - defer cwd.DecRef(ctx) + defer s.fs.SafeDecRef(ctx, cwd) root := vfs.RootFromContext(ctx) if !root.Ok() { // It could have raced with process deletion. return "", linuxerr.ESRCH } - defer root.DecRef(ctx) + defer s.fs.SafeDecRef(ctx, root) vfsObj := cwd.Mount().Filesystem().VirtualFilesystem() name, _ := vfsObj.PathnameWithDeleted(ctx, root, cwd) @@ -923,6 +931,7 @@ func (s *cwdSymlink) Getlink(ctx context.Context, _ *vfs.Mount) (vfs.VirtualDent // It could have raced with process deletion. return vfs.VirtualDentry{}, "", linuxerr.ESRCH } + // The reference is transferred to the caller. return cwd, "", nil } @@ -932,6 +941,7 @@ func (s *cwdSymlink) Getlink(ctx context.Context, _ *vfs.Mount) (vfs.VirtualDent type mountInfoData struct { kernfs.DynamicBytesFile + fs *filesystem task *kernel.Task } @@ -952,7 +962,7 @@ func (i *mountInfoData) Generate(ctx context.Context, buf *bytes.Buffer) error { // Root has been destroyed. Don't try to read mounts. return nil } - defer rootDir.DecRef(ctx) + defer i.fs.SafeDecRef(ctx, rootDir) i.task.Kernel().VFS().GenerateProcMountInfo(ctx, rootDir, buf) return nil } @@ -963,6 +973,7 @@ func (i *mountInfoData) Generate(ctx context.Context, buf *bytes.Buffer) error { type mountsData struct { kernfs.DynamicBytesFile + fs *filesystem task *kernel.Task } @@ -983,7 +994,7 @@ func (i *mountsData) Generate(ctx context.Context, buf *bytes.Buffer) error { // Root has been destroyed. Don't try to read mounts. return nil } - defer rootDir.DecRef(ctx) + defer i.fs.SafeDecRef(ctx, rootDir) i.task.Kernel().VFS().GenerateProcMounts(ctx, rootDir, buf) return nil } diff --git a/pkg/sentry/fsimpl/proc/task_inode_refs.go b/pkg/sentry/fsimpl/proc/task_inode_refs.go index 5d08a2992..82c63213a 100644 --- a/pkg/sentry/fsimpl/proc/task_inode_refs.go +++ b/pkg/sentry/fsimpl/proc/task_inode_refs.go @@ -81,7 +81,7 @@ func (r *taskInodeRefs) IncRef() { } } -// TryIncRef implements refs.RefCounter.TryIncRef. +// TryIncRef implements refs.TryRefCounter.TryIncRef. // // To do this safely without a loop, a speculative reference is first acquired // on the object. This allows multiple concurrent TryIncRef calls to distinguish diff --git a/pkg/sentry/fsimpl/proc/tasks_inode_refs.go b/pkg/sentry/fsimpl/proc/tasks_inode_refs.go index 2bfadc272..73adc5278 100644 --- a/pkg/sentry/fsimpl/proc/tasks_inode_refs.go +++ b/pkg/sentry/fsimpl/proc/tasks_inode_refs.go @@ -81,7 +81,7 @@ func (r *tasksInodeRefs) IncRef() { } } -// TryIncRef implements refs.RefCounter.TryIncRef. +// TryIncRef implements refs.TryRefCounter.TryIncRef. // // To do this safely without a loop, a speculative reference is first acquired // on the object. This allows multiple concurrent TryIncRef calls to distinguish diff --git a/pkg/sentry/fsimpl/sys/dir_refs.go b/pkg/sentry/fsimpl/sys/dir_refs.go index 3b5335671..17bc43d2e 100644 --- a/pkg/sentry/fsimpl/sys/dir_refs.go +++ b/pkg/sentry/fsimpl/sys/dir_refs.go @@ -81,7 +81,7 @@ func (r *dirRefs) IncRef() { } } -// TryIncRef implements refs.RefCounter.TryIncRef. +// TryIncRef implements refs.TryRefCounter.TryIncRef. // // To do this safely without a loop, a speculative reference is first acquired // on the object. This allows multiple concurrent TryIncRef calls to distinguish diff --git a/pkg/sentry/fsimpl/tmpfs/inode_refs.go b/pkg/sentry/fsimpl/tmpfs/inode_refs.go index d333bb742..f0f032e0c 100644 --- a/pkg/sentry/fsimpl/tmpfs/inode_refs.go +++ b/pkg/sentry/fsimpl/tmpfs/inode_refs.go @@ -81,7 +81,7 @@ func (r *inodeRefs) IncRef() { } } -// TryIncRef implements refs.RefCounter.TryIncRef. +// TryIncRef implements refs.TryRefCounter.TryIncRef. // // To do this safely without a loop, a speculative reference is first acquired // on the object. This allows multiple concurrent TryIncRef calls to distinguish |