summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fsimpl/proc
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2020-11-09 16:36:50 +0000
committergVisor bot <gvisor-bot@google.com>2020-11-09 16:36:50 +0000
commit7dd056ef81a67dc95b3d079f20e58e771498220c (patch)
treef8a73367fa610fb309e60c7b8ffdddd13e6a6835 /pkg/sentry/fsimpl/proc
parent9e848922ed33f78bddbb7a772dceba5406c185a2 (diff)
parent0fb5353e45f166460d5846576c20479072207a06 (diff)
Merge release-20201030.0-53-g0fb5353e4 (automated)
Diffstat (limited to 'pkg/sentry/fsimpl/proc')
-rw-r--r--pkg/sentry/fsimpl/proc/fd_dir_inode_refs.go33
-rw-r--r--pkg/sentry/fsimpl/proc/fd_info_dir_inode_refs.go33
-rw-r--r--pkg/sentry/fsimpl/proc/subtasks.go2
-rw-r--r--pkg/sentry/fsimpl/proc/subtasks_inode_refs.go33
-rw-r--r--pkg/sentry/fsimpl/proc/task.go2
-rw-r--r--pkg/sentry/fsimpl/proc/task_fds.go4
-rw-r--r--pkg/sentry/fsimpl/proc/task_inode_refs.go33
-rw-r--r--pkg/sentry/fsimpl/proc/tasks.go2
-rw-r--r--pkg/sentry/fsimpl/proc/tasks_inode_refs.go33
9 files changed, 110 insertions, 65 deletions
diff --git a/pkg/sentry/fsimpl/proc/fd_dir_inode_refs.go b/pkg/sentry/fsimpl/proc/fd_dir_inode_refs.go
index 895298eb9..4644809bd 100644
--- a/pkg/sentry/fsimpl/proc/fd_dir_inode_refs.go
+++ b/pkg/sentry/fsimpl/proc/fd_dir_inode_refs.go
@@ -20,9 +20,6 @@ var fdDirInodeobj *fdDirInode
// Refs implements refs.RefCounter. It keeps a reference count using atomic
// operations and calls the destructor when the count reaches zero.
//
-// Note that the number of references is actually refCount + 1 so that a default
-// zero-value Refs object contains one reference.
-//
// +stateify savable
type fdDirInodeRefs struct {
// refCount is composed of two fields:
@@ -35,6 +32,13 @@ type fdDirInodeRefs struct {
refCount int64
}
+// InitRefs initializes r with one reference and, if enabled, activates leak
+// checking.
+func (r *fdDirInodeRefs) InitRefs() {
+ atomic.StoreInt64(&r.refCount, 1)
+ refsvfs2.Register(r)
+}
+
// RefType implements refsvfs2.CheckedObject.RefType.
func (r *fdDirInodeRefs) RefType() string {
return fmt.Sprintf("%T", fdDirInodeobj)[1:]
@@ -58,8 +62,7 @@ func (r *fdDirInodeRefs) EnableLeakCheck() {
// ReadRefs returns the current number of references. The returned count is
// inherently racy and is unsafe to use without external synchronization.
func (r *fdDirInodeRefs) ReadRefs() int64 {
-
- return atomic.LoadInt64(&r.refCount) + 1
+ return atomic.LoadInt64(&r.refCount)
}
// IncRef implements refs.RefCounter.IncRef.
@@ -67,8 +70,10 @@ func (r *fdDirInodeRefs) ReadRefs() int64 {
//go:nosplit
func (r *fdDirInodeRefs) IncRef() {
v := atomic.AddInt64(&r.refCount, 1)
- refsvfs2.LogIncRef(r, v+1)
- if v <= 0 {
+ if fdDirInodeenableLogging {
+ refsvfs2.LogIncRef(r, v)
+ }
+ if v <= 1 {
panic(fmt.Sprintf("Incrementing non-positive count %p on %s", r, r.RefType()))
}
}
@@ -82,14 +87,16 @@ func (r *fdDirInodeRefs) IncRef() {
//go:nosplit
func (r *fdDirInodeRefs) TryIncRef() bool {
const speculativeRef = 1 << 32
- if v := atomic.AddInt64(&r.refCount, speculativeRef); int32(v) < 0 {
+ if v := atomic.AddInt64(&r.refCount, speculativeRef); int32(v) == 0 {
atomic.AddInt64(&r.refCount, -speculativeRef)
return false
}
v := atomic.AddInt64(&r.refCount, -speculativeRef+1)
- refsvfs2.LogTryIncRef(r, v+1)
+ if fdDirInodeenableLogging {
+ refsvfs2.LogTryIncRef(r, v)
+ }
return true
}
@@ -107,12 +114,14 @@ func (r *fdDirInodeRefs) TryIncRef() bool {
//go:nosplit
func (r *fdDirInodeRefs) DecRef(destroy func()) {
v := atomic.AddInt64(&r.refCount, -1)
- refsvfs2.LogDecRef(r, v+1)
+ if fdDirInodeenableLogging {
+ refsvfs2.LogDecRef(r, v+1)
+ }
switch {
- case v < -1:
+ case v < 0:
panic(fmt.Sprintf("Decrementing non-positive ref count %p, owned by %s", r, r.RefType()))
- case v == -1:
+ case v == 0:
refsvfs2.Unregister(r)
if destroy != nil {
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 8e3458485..dbc7e3f5a 100644
--- a/pkg/sentry/fsimpl/proc/fd_info_dir_inode_refs.go
+++ b/pkg/sentry/fsimpl/proc/fd_info_dir_inode_refs.go
@@ -20,9 +20,6 @@ var fdInfoDirInodeobj *fdInfoDirInode
// Refs implements refs.RefCounter. It keeps a reference count using atomic
// operations and calls the destructor when the count reaches zero.
//
-// Note that the number of references is actually refCount + 1 so that a default
-// zero-value Refs object contains one reference.
-//
// +stateify savable
type fdInfoDirInodeRefs struct {
// refCount is composed of two fields:
@@ -35,6 +32,13 @@ type fdInfoDirInodeRefs struct {
refCount int64
}
+// InitRefs initializes r with one reference and, if enabled, activates leak
+// checking.
+func (r *fdInfoDirInodeRefs) InitRefs() {
+ atomic.StoreInt64(&r.refCount, 1)
+ refsvfs2.Register(r)
+}
+
// RefType implements refsvfs2.CheckedObject.RefType.
func (r *fdInfoDirInodeRefs) RefType() string {
return fmt.Sprintf("%T", fdInfoDirInodeobj)[1:]
@@ -58,8 +62,7 @@ func (r *fdInfoDirInodeRefs) EnableLeakCheck() {
// ReadRefs returns the current number of references. The returned count is
// inherently racy and is unsafe to use without external synchronization.
func (r *fdInfoDirInodeRefs) ReadRefs() int64 {
-
- return atomic.LoadInt64(&r.refCount) + 1
+ return atomic.LoadInt64(&r.refCount)
}
// IncRef implements refs.RefCounter.IncRef.
@@ -67,8 +70,10 @@ func (r *fdInfoDirInodeRefs) ReadRefs() int64 {
//go:nosplit
func (r *fdInfoDirInodeRefs) IncRef() {
v := atomic.AddInt64(&r.refCount, 1)
- refsvfs2.LogIncRef(r, v+1)
- if v <= 0 {
+ if fdInfoDirInodeenableLogging {
+ refsvfs2.LogIncRef(r, v)
+ }
+ if v <= 1 {
panic(fmt.Sprintf("Incrementing non-positive count %p on %s", r, r.RefType()))
}
}
@@ -82,14 +87,16 @@ func (r *fdInfoDirInodeRefs) IncRef() {
//go:nosplit
func (r *fdInfoDirInodeRefs) TryIncRef() bool {
const speculativeRef = 1 << 32
- if v := atomic.AddInt64(&r.refCount, speculativeRef); int32(v) < 0 {
+ if v := atomic.AddInt64(&r.refCount, speculativeRef); int32(v) == 0 {
atomic.AddInt64(&r.refCount, -speculativeRef)
return false
}
v := atomic.AddInt64(&r.refCount, -speculativeRef+1)
- refsvfs2.LogTryIncRef(r, v+1)
+ if fdInfoDirInodeenableLogging {
+ refsvfs2.LogTryIncRef(r, v)
+ }
return true
}
@@ -107,12 +114,14 @@ func (r *fdInfoDirInodeRefs) TryIncRef() bool {
//go:nosplit
func (r *fdInfoDirInodeRefs) DecRef(destroy func()) {
v := atomic.AddInt64(&r.refCount, -1)
- refsvfs2.LogDecRef(r, v+1)
+ if fdInfoDirInodeenableLogging {
+ refsvfs2.LogDecRef(r, v+1)
+ }
switch {
- case v < -1:
+ case v < 0:
panic(fmt.Sprintf("Decrementing non-positive ref count %p, owned by %s", r, r.RefType()))
- case v == -1:
+ case v == 0:
refsvfs2.Unregister(r)
if destroy != nil {
diff --git a/pkg/sentry/fsimpl/proc/subtasks.go b/pkg/sentry/fsimpl/proc/subtasks.go
index cb3c5e0fd..e001d5032 100644
--- a/pkg/sentry/fsimpl/proc/subtasks.go
+++ b/pkg/sentry/fsimpl/proc/subtasks.go
@@ -60,7 +60,7 @@ func (fs *filesystem) newSubtasks(task *kernel.Task, pidns *kernel.PIDNamespace,
// Note: credentials are overridden by taskOwnedInode.
subInode.InodeAttrs.Init(task, task.Credentials(), linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), linux.ModeDirectory|0555)
subInode.OrderedChildren.Init(kernfs.OrderedChildrenOptions{})
- subInode.EnableLeakCheck()
+ subInode.InitRefs()
inode := &taskOwnedInode{Inode: subInode, owner: task}
return inode
diff --git a/pkg/sentry/fsimpl/proc/subtasks_inode_refs.go b/pkg/sentry/fsimpl/proc/subtasks_inode_refs.go
index c609e618a..993251646 100644
--- a/pkg/sentry/fsimpl/proc/subtasks_inode_refs.go
+++ b/pkg/sentry/fsimpl/proc/subtasks_inode_refs.go
@@ -20,9 +20,6 @@ var subtasksInodeobj *subtasksInode
// Refs implements refs.RefCounter. It keeps a reference count using atomic
// operations and calls the destructor when the count reaches zero.
//
-// Note that the number of references is actually refCount + 1 so that a default
-// zero-value Refs object contains one reference.
-//
// +stateify savable
type subtasksInodeRefs struct {
// refCount is composed of two fields:
@@ -35,6 +32,13 @@ type subtasksInodeRefs struct {
refCount int64
}
+// InitRefs initializes r with one reference and, if enabled, activates leak
+// checking.
+func (r *subtasksInodeRefs) InitRefs() {
+ atomic.StoreInt64(&r.refCount, 1)
+ refsvfs2.Register(r)
+}
+
// RefType implements refsvfs2.CheckedObject.RefType.
func (r *subtasksInodeRefs) RefType() string {
return fmt.Sprintf("%T", subtasksInodeobj)[1:]
@@ -58,8 +62,7 @@ func (r *subtasksInodeRefs) EnableLeakCheck() {
// ReadRefs returns the current number of references. The returned count is
// inherently racy and is unsafe to use without external synchronization.
func (r *subtasksInodeRefs) ReadRefs() int64 {
-
- return atomic.LoadInt64(&r.refCount) + 1
+ return atomic.LoadInt64(&r.refCount)
}
// IncRef implements refs.RefCounter.IncRef.
@@ -67,8 +70,10 @@ func (r *subtasksInodeRefs) ReadRefs() int64 {
//go:nosplit
func (r *subtasksInodeRefs) IncRef() {
v := atomic.AddInt64(&r.refCount, 1)
- refsvfs2.LogIncRef(r, v+1)
- if v <= 0 {
+ if subtasksInodeenableLogging {
+ refsvfs2.LogIncRef(r, v)
+ }
+ if v <= 1 {
panic(fmt.Sprintf("Incrementing non-positive count %p on %s", r, r.RefType()))
}
}
@@ -82,14 +87,16 @@ func (r *subtasksInodeRefs) IncRef() {
//go:nosplit
func (r *subtasksInodeRefs) TryIncRef() bool {
const speculativeRef = 1 << 32
- if v := atomic.AddInt64(&r.refCount, speculativeRef); int32(v) < 0 {
+ if v := atomic.AddInt64(&r.refCount, speculativeRef); int32(v) == 0 {
atomic.AddInt64(&r.refCount, -speculativeRef)
return false
}
v := atomic.AddInt64(&r.refCount, -speculativeRef+1)
- refsvfs2.LogTryIncRef(r, v+1)
+ if subtasksInodeenableLogging {
+ refsvfs2.LogTryIncRef(r, v)
+ }
return true
}
@@ -107,12 +114,14 @@ func (r *subtasksInodeRefs) TryIncRef() bool {
//go:nosplit
func (r *subtasksInodeRefs) DecRef(destroy func()) {
v := atomic.AddInt64(&r.refCount, -1)
- refsvfs2.LogDecRef(r, v+1)
+ if subtasksInodeenableLogging {
+ refsvfs2.LogDecRef(r, v+1)
+ }
switch {
- case v < -1:
+ case v < 0:
panic(fmt.Sprintf("Decrementing non-positive ref count %p, owned by %s", r, r.RefType()))
- case v == -1:
+ case v == 0:
refsvfs2.Unregister(r)
if destroy != nil {
diff --git a/pkg/sentry/fsimpl/proc/task.go b/pkg/sentry/fsimpl/proc/task.go
index 19011b010..dc46a09bc 100644
--- a/pkg/sentry/fsimpl/proc/task.go
+++ b/pkg/sentry/fsimpl/proc/task.go
@@ -91,7 +91,7 @@ func (fs *filesystem) newTaskInode(task *kernel.Task, pidns *kernel.PIDNamespace
taskInode := &taskInode{task: task}
// Note: credentials are overridden by taskOwnedInode.
taskInode.InodeAttrs.Init(task, task.Credentials(), linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), linux.ModeDirectory|0555)
- taskInode.EnableLeakCheck()
+ taskInode.InitRefs()
inode := &taskOwnedInode{Inode: taskInode, owner: task}
diff --git a/pkg/sentry/fsimpl/proc/task_fds.go b/pkg/sentry/fsimpl/proc/task_fds.go
index d268b44be..3ec4471f5 100644
--- a/pkg/sentry/fsimpl/proc/task_fds.go
+++ b/pkg/sentry/fsimpl/proc/task_fds.go
@@ -128,7 +128,7 @@ func (fs *filesystem) newFDDirInode(task *kernel.Task) kernfs.Inode {
},
}
inode.InodeAttrs.Init(task, task.Credentials(), linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), linux.ModeDirectory|0555)
- inode.EnableLeakCheck()
+ inode.InitRefs()
inode.OrderedChildren.Init(kernfs.OrderedChildrenOptions{})
return inode
}
@@ -265,7 +265,7 @@ func (fs *filesystem) newFDInfoDirInode(task *kernel.Task) kernfs.Inode {
},
}
inode.InodeAttrs.Init(task, task.Credentials(), linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), linux.ModeDirectory|0555)
- inode.EnableLeakCheck()
+ inode.InitRefs()
inode.OrderedChildren.Init(kernfs.OrderedChildrenOptions{})
return inode
}
diff --git a/pkg/sentry/fsimpl/proc/task_inode_refs.go b/pkg/sentry/fsimpl/proc/task_inode_refs.go
index 2ee58bd62..632251e75 100644
--- a/pkg/sentry/fsimpl/proc/task_inode_refs.go
+++ b/pkg/sentry/fsimpl/proc/task_inode_refs.go
@@ -20,9 +20,6 @@ var taskInodeobj *taskInode
// Refs implements refs.RefCounter. It keeps a reference count using atomic
// operations and calls the destructor when the count reaches zero.
//
-// Note that the number of references is actually refCount + 1 so that a default
-// zero-value Refs object contains one reference.
-//
// +stateify savable
type taskInodeRefs struct {
// refCount is composed of two fields:
@@ -35,6 +32,13 @@ type taskInodeRefs struct {
refCount int64
}
+// InitRefs initializes r with one reference and, if enabled, activates leak
+// checking.
+func (r *taskInodeRefs) InitRefs() {
+ atomic.StoreInt64(&r.refCount, 1)
+ refsvfs2.Register(r)
+}
+
// RefType implements refsvfs2.CheckedObject.RefType.
func (r *taskInodeRefs) RefType() string {
return fmt.Sprintf("%T", taskInodeobj)[1:]
@@ -58,8 +62,7 @@ func (r *taskInodeRefs) EnableLeakCheck() {
// ReadRefs returns the current number of references. The returned count is
// inherently racy and is unsafe to use without external synchronization.
func (r *taskInodeRefs) ReadRefs() int64 {
-
- return atomic.LoadInt64(&r.refCount) + 1
+ return atomic.LoadInt64(&r.refCount)
}
// IncRef implements refs.RefCounter.IncRef.
@@ -67,8 +70,10 @@ func (r *taskInodeRefs) ReadRefs() int64 {
//go:nosplit
func (r *taskInodeRefs) IncRef() {
v := atomic.AddInt64(&r.refCount, 1)
- refsvfs2.LogIncRef(r, v+1)
- if v <= 0 {
+ if taskInodeenableLogging {
+ refsvfs2.LogIncRef(r, v)
+ }
+ if v <= 1 {
panic(fmt.Sprintf("Incrementing non-positive count %p on %s", r, r.RefType()))
}
}
@@ -82,14 +87,16 @@ func (r *taskInodeRefs) IncRef() {
//go:nosplit
func (r *taskInodeRefs) TryIncRef() bool {
const speculativeRef = 1 << 32
- if v := atomic.AddInt64(&r.refCount, speculativeRef); int32(v) < 0 {
+ if v := atomic.AddInt64(&r.refCount, speculativeRef); int32(v) == 0 {
atomic.AddInt64(&r.refCount, -speculativeRef)
return false
}
v := atomic.AddInt64(&r.refCount, -speculativeRef+1)
- refsvfs2.LogTryIncRef(r, v+1)
+ if taskInodeenableLogging {
+ refsvfs2.LogTryIncRef(r, v)
+ }
return true
}
@@ -107,12 +114,14 @@ func (r *taskInodeRefs) TryIncRef() bool {
//go:nosplit
func (r *taskInodeRefs) DecRef(destroy func()) {
v := atomic.AddInt64(&r.refCount, -1)
- refsvfs2.LogDecRef(r, v+1)
+ if taskInodeenableLogging {
+ refsvfs2.LogDecRef(r, v+1)
+ }
switch {
- case v < -1:
+ case v < 0:
panic(fmt.Sprintf("Decrementing non-positive ref count %p, owned by %s", r, r.RefType()))
- case v == -1:
+ case v == 0:
refsvfs2.Unregister(r)
if destroy != nil {
diff --git a/pkg/sentry/fsimpl/proc/tasks.go b/pkg/sentry/fsimpl/proc/tasks.go
index b81ea14bf..151d1f10d 100644
--- a/pkg/sentry/fsimpl/proc/tasks.go
+++ b/pkg/sentry/fsimpl/proc/tasks.go
@@ -83,7 +83,7 @@ func (fs *filesystem) newTasksInode(ctx context.Context, k *kernel.Kernel, pidns
cgroupControllers: cgroupControllers,
}
inode.InodeAttrs.Init(ctx, root, linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), linux.ModeDirectory|0555)
- inode.EnableLeakCheck()
+ inode.InitRefs()
inode.OrderedChildren.Init(kernfs.OrderedChildrenOptions{})
links := inode.OrderedChildren.Populate(contents)
diff --git a/pkg/sentry/fsimpl/proc/tasks_inode_refs.go b/pkg/sentry/fsimpl/proc/tasks_inode_refs.go
index 71dcaed9e..0b2af4269 100644
--- a/pkg/sentry/fsimpl/proc/tasks_inode_refs.go
+++ b/pkg/sentry/fsimpl/proc/tasks_inode_refs.go
@@ -20,9 +20,6 @@ var tasksInodeobj *tasksInode
// Refs implements refs.RefCounter. It keeps a reference count using atomic
// operations and calls the destructor when the count reaches zero.
//
-// Note that the number of references is actually refCount + 1 so that a default
-// zero-value Refs object contains one reference.
-//
// +stateify savable
type tasksInodeRefs struct {
// refCount is composed of two fields:
@@ -35,6 +32,13 @@ type tasksInodeRefs struct {
refCount int64
}
+// InitRefs initializes r with one reference and, if enabled, activates leak
+// checking.
+func (r *tasksInodeRefs) InitRefs() {
+ atomic.StoreInt64(&r.refCount, 1)
+ refsvfs2.Register(r)
+}
+
// RefType implements refsvfs2.CheckedObject.RefType.
func (r *tasksInodeRefs) RefType() string {
return fmt.Sprintf("%T", tasksInodeobj)[1:]
@@ -58,8 +62,7 @@ func (r *tasksInodeRefs) EnableLeakCheck() {
// ReadRefs returns the current number of references. The returned count is
// inherently racy and is unsafe to use without external synchronization.
func (r *tasksInodeRefs) ReadRefs() int64 {
-
- return atomic.LoadInt64(&r.refCount) + 1
+ return atomic.LoadInt64(&r.refCount)
}
// IncRef implements refs.RefCounter.IncRef.
@@ -67,8 +70,10 @@ func (r *tasksInodeRefs) ReadRefs() int64 {
//go:nosplit
func (r *tasksInodeRefs) IncRef() {
v := atomic.AddInt64(&r.refCount, 1)
- refsvfs2.LogIncRef(r, v+1)
- if v <= 0 {
+ if tasksInodeenableLogging {
+ refsvfs2.LogIncRef(r, v)
+ }
+ if v <= 1 {
panic(fmt.Sprintf("Incrementing non-positive count %p on %s", r, r.RefType()))
}
}
@@ -82,14 +87,16 @@ func (r *tasksInodeRefs) IncRef() {
//go:nosplit
func (r *tasksInodeRefs) TryIncRef() bool {
const speculativeRef = 1 << 32
- if v := atomic.AddInt64(&r.refCount, speculativeRef); int32(v) < 0 {
+ if v := atomic.AddInt64(&r.refCount, speculativeRef); int32(v) == 0 {
atomic.AddInt64(&r.refCount, -speculativeRef)
return false
}
v := atomic.AddInt64(&r.refCount, -speculativeRef+1)
- refsvfs2.LogTryIncRef(r, v+1)
+ if tasksInodeenableLogging {
+ refsvfs2.LogTryIncRef(r, v)
+ }
return true
}
@@ -107,12 +114,14 @@ func (r *tasksInodeRefs) TryIncRef() bool {
//go:nosplit
func (r *tasksInodeRefs) DecRef(destroy func()) {
v := atomic.AddInt64(&r.refCount, -1)
- refsvfs2.LogDecRef(r, v+1)
+ if tasksInodeenableLogging {
+ refsvfs2.LogDecRef(r, v+1)
+ }
switch {
- case v < -1:
+ case v < 0:
panic(fmt.Sprintf("Decrementing non-positive ref count %p, owned by %s", r, r.RefType()))
- case v == -1:
+ case v == 0:
refsvfs2.Unregister(r)
if destroy != nil {