summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fsimpl
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2021-07-13 01:36:04 +0000
committergVisor bot <gvisor-bot@google.com>2021-07-13 01:36:04 +0000
commit06f349011627d6298168ceac919e27cb166675d4 (patch)
treedf2b179bb06b09baee6d2cd47c714d03ae6d75f2 /pkg/sentry/fsimpl
parent289efe127e1f04f4fbb0c2a46050a6cd9c9f3b9b (diff)
parent520795aaad701854e9ffe84de1108954cf2b77f8 (diff)
Merge release-20210705.0-15-g520795aaa (automated)
Diffstat (limited to 'pkg/sentry/fsimpl')
-rw-r--r--pkg/sentry/fsimpl/cgroupfs/dir_refs.go2
-rw-r--r--pkg/sentry/fsimpl/devpts/root_inode_refs.go2
-rw-r--r--pkg/sentry/fsimpl/fuse/inode_refs.go2
-rw-r--r--pkg/sentry/fsimpl/host/connected_endpoint_refs.go2
-rw-r--r--pkg/sentry/fsimpl/host/inode_refs.go2
-rw-r--r--pkg/sentry/fsimpl/kernfs/kernfs.go54
-rw-r--r--pkg/sentry/fsimpl/kernfs/kernfs_state_autogen.go6
-rw-r--r--pkg/sentry/fsimpl/kernfs/static_directory_refs.go2
-rw-r--r--pkg/sentry/fsimpl/kernfs/synthetic_directory_refs.go2
-rw-r--r--pkg/sentry/fsimpl/proc/fd_dir_inode_refs.go2
-rw-r--r--pkg/sentry/fsimpl/proc/fd_info_dir_inode_refs.go2
-rw-r--r--pkg/sentry/fsimpl/proc/proc_state_autogen.go50
-rw-r--r--pkg/sentry/fsimpl/proc/subtasks_inode_refs.go2
-rw-r--r--pkg/sentry/fsimpl/proc/task.go4
-rw-r--r--pkg/sentry/fsimpl/proc/task_fds.go24
-rw-r--r--pkg/sentry/fsimpl/proc/task_files.go27
-rw-r--r--pkg/sentry/fsimpl/proc/task_inode_refs.go2
-rw-r--r--pkg/sentry/fsimpl/proc/tasks_inode_refs.go2
-rw-r--r--pkg/sentry/fsimpl/sys/dir_refs.go2
-rw-r--r--pkg/sentry/fsimpl/tmpfs/inode_refs.go2
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