summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/socket/unix
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/sentry/socket/unix')
-rw-r--r--pkg/sentry/socket/unix/socket_refs.go42
-rw-r--r--pkg/sentry/socket/unix/socket_vfs2_refs.go42
-rw-r--r--pkg/sentry/socket/unix/transport/queue_refs.go42
-rw-r--r--pkg/sentry/socket/unix/transport/transport_state_autogen.go3
-rw-r--r--pkg/sentry/socket/unix/unix.go1
-rw-r--r--pkg/sentry/socket/unix/unix_state_autogen.go6
-rw-r--r--pkg/sentry/socket/unix/unix_vfs2.go1
7 files changed, 58 insertions, 79 deletions
diff --git a/pkg/sentry/socket/unix/socket_refs.go b/pkg/sentry/socket/unix/socket_refs.go
index ea63dc659..45b7c77d5 100644
--- a/pkg/sentry/socket/unix/socket_refs.go
+++ b/pkg/sentry/socket/unix/socket_refs.go
@@ -2,11 +2,9 @@ package unix
import (
"fmt"
- "runtime"
"sync/atomic"
- "gvisor.dev/gvisor/pkg/log"
- refs_vfs1 "gvisor.dev/gvisor/pkg/refs"
+ "gvisor.dev/gvisor/pkg/refsvfs2"
)
// ownerType is used to customize logging. Note that we use a pointer to T so
@@ -19,11 +17,6 @@ var socketOperationsownerType *SocketOperations
// Note that the number of references is actually refCount + 1 so that a default
// zero-value Refs object contains one reference.
//
-// TODO(gvisor.dev/issue/1486): Store stack traces when leak check is enabled in
-// a map with 16-bit hashes, and store the hash in the top 16 bits of refCount.
-// This will allow us to add stack trace information to the leak messages
-// without growing the size of Refs.
-//
// +stateify savable
type socketOperationsRefs struct {
// refCount is composed of two fields:
@@ -36,24 +29,16 @@ type socketOperationsRefs struct {
refCount int64
}
-func (r *socketOperationsRefs) finalize() {
- var note string
- switch refs_vfs1.GetLeakMode() {
- case refs_vfs1.NoLeakChecking:
- return
- case refs_vfs1.UninitializedLeakChecking:
- note = "(Leak checker uninitialized): "
- }
- if n := r.ReadRefs(); n != 0 {
- log.Warningf("%sRefs %p owned by %T garbage collected with ref count of %d (want 0)", note, r, socketOperationsownerType, n)
+// EnableLeakCheck enables reference leak checking on r.
+func (r *socketOperationsRefs) EnableLeakCheck() {
+ if refsvfs2.LeakCheckEnabled() {
+ refsvfs2.Register(r, fmt.Sprintf("%T", socketOperationsownerType))
}
}
-// EnableLeakCheck checks for reference leaks when Refs gets garbage collected.
-func (r *socketOperationsRefs) EnableLeakCheck() {
- if refs_vfs1.GetLeakMode() != refs_vfs1.NoLeakChecking {
- runtime.SetFinalizer(r, (*socketOperationsRefs).finalize)
- }
+// LeakMessage implements refsvfs2.CheckedObject.LeakMessage.
+func (r *socketOperationsRefs) LeakMessage() string {
+ return fmt.Sprintf("%T %p: reference count of %d instead of 0", socketOperationsownerType, r, r.ReadRefs())
}
// ReadRefs returns the current number of references. The returned count is
@@ -68,7 +53,7 @@ func (r *socketOperationsRefs) ReadRefs() int64 {
//go:nosplit
func (r *socketOperationsRefs) IncRef() {
if v := atomic.AddInt64(&r.refCount, 1); v <= 0 {
- panic(fmt.Sprintf("Incrementing non-positive ref count %p owned by %T", r, socketOperationsownerType))
+ panic(fmt.Sprintf("Incrementing non-positive count %p on %T", r, socketOperationsownerType))
}
}
@@ -110,9 +95,18 @@ func (r *socketOperationsRefs) DecRef(destroy func()) {
panic(fmt.Sprintf("Decrementing non-positive ref count %p, owned by %T", r, socketOperationsownerType))
case v == -1:
+ if refsvfs2.LeakCheckEnabled() {
+ refsvfs2.Unregister(r, fmt.Sprintf("%T", socketOperationsownerType))
+ }
if destroy != nil {
destroy()
}
}
}
+
+func (r *socketOperationsRefs) afterLoad() {
+ if refsvfs2.LeakCheckEnabled() && r.ReadRefs() > 0 {
+ r.EnableLeakCheck()
+ }
+}
diff --git a/pkg/sentry/socket/unix/socket_vfs2_refs.go b/pkg/sentry/socket/unix/socket_vfs2_refs.go
index dc55f2947..479dd5ef0 100644
--- a/pkg/sentry/socket/unix/socket_vfs2_refs.go
+++ b/pkg/sentry/socket/unix/socket_vfs2_refs.go
@@ -2,11 +2,9 @@ package unix
import (
"fmt"
- "runtime"
"sync/atomic"
- "gvisor.dev/gvisor/pkg/log"
- refs_vfs1 "gvisor.dev/gvisor/pkg/refs"
+ "gvisor.dev/gvisor/pkg/refsvfs2"
)
// ownerType is used to customize logging. Note that we use a pointer to T so
@@ -19,11 +17,6 @@ var socketVFS2ownerType *SocketVFS2
// Note that the number of references is actually refCount + 1 so that a default
// zero-value Refs object contains one reference.
//
-// TODO(gvisor.dev/issue/1486): Store stack traces when leak check is enabled in
-// a map with 16-bit hashes, and store the hash in the top 16 bits of refCount.
-// This will allow us to add stack trace information to the leak messages
-// without growing the size of Refs.
-//
// +stateify savable
type socketVFS2Refs struct {
// refCount is composed of two fields:
@@ -36,24 +29,16 @@ type socketVFS2Refs struct {
refCount int64
}
-func (r *socketVFS2Refs) finalize() {
- var note string
- switch refs_vfs1.GetLeakMode() {
- case refs_vfs1.NoLeakChecking:
- return
- case refs_vfs1.UninitializedLeakChecking:
- note = "(Leak checker uninitialized): "
- }
- if n := r.ReadRefs(); n != 0 {
- log.Warningf("%sRefs %p owned by %T garbage collected with ref count of %d (want 0)", note, r, socketVFS2ownerType, n)
+// EnableLeakCheck enables reference leak checking on r.
+func (r *socketVFS2Refs) EnableLeakCheck() {
+ if refsvfs2.LeakCheckEnabled() {
+ refsvfs2.Register(r, fmt.Sprintf("%T", socketVFS2ownerType))
}
}
-// EnableLeakCheck checks for reference leaks when Refs gets garbage collected.
-func (r *socketVFS2Refs) EnableLeakCheck() {
- if refs_vfs1.GetLeakMode() != refs_vfs1.NoLeakChecking {
- runtime.SetFinalizer(r, (*socketVFS2Refs).finalize)
- }
+// LeakMessage implements refsvfs2.CheckedObject.LeakMessage.
+func (r *socketVFS2Refs) LeakMessage() string {
+ return fmt.Sprintf("%T %p: reference count of %d instead of 0", socketVFS2ownerType, r, r.ReadRefs())
}
// ReadRefs returns the current number of references. The returned count is
@@ -68,7 +53,7 @@ func (r *socketVFS2Refs) ReadRefs() int64 {
//go:nosplit
func (r *socketVFS2Refs) IncRef() {
if v := atomic.AddInt64(&r.refCount, 1); v <= 0 {
- panic(fmt.Sprintf("Incrementing non-positive ref count %p owned by %T", r, socketVFS2ownerType))
+ panic(fmt.Sprintf("Incrementing non-positive count %p on %T", r, socketVFS2ownerType))
}
}
@@ -110,9 +95,18 @@ func (r *socketVFS2Refs) DecRef(destroy func()) {
panic(fmt.Sprintf("Decrementing non-positive ref count %p, owned by %T", r, socketVFS2ownerType))
case v == -1:
+ if refsvfs2.LeakCheckEnabled() {
+ refsvfs2.Unregister(r, fmt.Sprintf("%T", socketVFS2ownerType))
+ }
if destroy != nil {
destroy()
}
}
}
+
+func (r *socketVFS2Refs) afterLoad() {
+ if refsvfs2.LeakCheckEnabled() && r.ReadRefs() > 0 {
+ r.EnableLeakCheck()
+ }
+}
diff --git a/pkg/sentry/socket/unix/transport/queue_refs.go b/pkg/sentry/socket/unix/transport/queue_refs.go
index 0d4e34988..de3bb9270 100644
--- a/pkg/sentry/socket/unix/transport/queue_refs.go
+++ b/pkg/sentry/socket/unix/transport/queue_refs.go
@@ -2,11 +2,9 @@ package transport
import (
"fmt"
- "runtime"
"sync/atomic"
- "gvisor.dev/gvisor/pkg/log"
- refs_vfs1 "gvisor.dev/gvisor/pkg/refs"
+ "gvisor.dev/gvisor/pkg/refsvfs2"
)
// ownerType is used to customize logging. Note that we use a pointer to T so
@@ -19,11 +17,6 @@ var queueownerType *queue
// Note that the number of references is actually refCount + 1 so that a default
// zero-value Refs object contains one reference.
//
-// TODO(gvisor.dev/issue/1486): Store stack traces when leak check is enabled in
-// a map with 16-bit hashes, and store the hash in the top 16 bits of refCount.
-// This will allow us to add stack trace information to the leak messages
-// without growing the size of Refs.
-//
// +stateify savable
type queueRefs struct {
// refCount is composed of two fields:
@@ -36,24 +29,16 @@ type queueRefs struct {
refCount int64
}
-func (r *queueRefs) finalize() {
- var note string
- switch refs_vfs1.GetLeakMode() {
- case refs_vfs1.NoLeakChecking:
- return
- case refs_vfs1.UninitializedLeakChecking:
- note = "(Leak checker uninitialized): "
- }
- if n := r.ReadRefs(); n != 0 {
- log.Warningf("%sRefs %p owned by %T garbage collected with ref count of %d (want 0)", note, r, queueownerType, n)
+// EnableLeakCheck enables reference leak checking on r.
+func (r *queueRefs) EnableLeakCheck() {
+ if refsvfs2.LeakCheckEnabled() {
+ refsvfs2.Register(r, fmt.Sprintf("%T", queueownerType))
}
}
-// EnableLeakCheck checks for reference leaks when Refs gets garbage collected.
-func (r *queueRefs) EnableLeakCheck() {
- if refs_vfs1.GetLeakMode() != refs_vfs1.NoLeakChecking {
- runtime.SetFinalizer(r, (*queueRefs).finalize)
- }
+// LeakMessage implements refsvfs2.CheckedObject.LeakMessage.
+func (r *queueRefs) LeakMessage() string {
+ return fmt.Sprintf("%T %p: reference count of %d instead of 0", queueownerType, r, r.ReadRefs())
}
// ReadRefs returns the current number of references. The returned count is
@@ -68,7 +53,7 @@ func (r *queueRefs) ReadRefs() int64 {
//go:nosplit
func (r *queueRefs) IncRef() {
if v := atomic.AddInt64(&r.refCount, 1); v <= 0 {
- panic(fmt.Sprintf("Incrementing non-positive ref count %p owned by %T", r, queueownerType))
+ panic(fmt.Sprintf("Incrementing non-positive count %p on %T", r, queueownerType))
}
}
@@ -110,9 +95,18 @@ func (r *queueRefs) DecRef(destroy func()) {
panic(fmt.Sprintf("Decrementing non-positive ref count %p, owned by %T", r, queueownerType))
case v == -1:
+ if refsvfs2.LeakCheckEnabled() {
+ refsvfs2.Unregister(r, fmt.Sprintf("%T", queueownerType))
+ }
if destroy != nil {
destroy()
}
}
}
+
+func (r *queueRefs) afterLoad() {
+ if refsvfs2.LeakCheckEnabled() && r.ReadRefs() > 0 {
+ r.EnableLeakCheck()
+ }
+}
diff --git a/pkg/sentry/socket/unix/transport/transport_state_autogen.go b/pkg/sentry/socket/unix/transport/transport_state_autogen.go
index 015fbc90a..4ec849a7f 100644
--- a/pkg/sentry/socket/unix/transport/transport_state_autogen.go
+++ b/pkg/sentry/socket/unix/transport/transport_state_autogen.go
@@ -126,10 +126,9 @@ func (r *queueRefs) StateSave(stateSinkObject state.Sink) {
stateSinkObject.Save(0, &r.refCount)
}
-func (r *queueRefs) afterLoad() {}
-
func (r *queueRefs) StateLoad(stateSourceObject state.Source) {
stateSourceObject.Load(0, &r.refCount)
+ stateSourceObject.AfterLoad(r.afterLoad)
}
func (l *messageList) StateTypeName() string {
diff --git a/pkg/sentry/socket/unix/unix.go b/pkg/sentry/socket/unix/unix.go
index a4a76d0a3..adad485a9 100644
--- a/pkg/sentry/socket/unix/unix.go
+++ b/pkg/sentry/socket/unix/unix.go
@@ -81,7 +81,6 @@ func NewWithDirent(ctx context.Context, d *fs.Dirent, ep transport.Endpoint, sty
},
}
s.EnableLeakCheck()
-
return fs.NewFile(ctx, d, flags, &s)
}
diff --git a/pkg/sentry/socket/unix/unix_state_autogen.go b/pkg/sentry/socket/unix/unix_state_autogen.go
index 6b2886e4f..fba990d9a 100644
--- a/pkg/sentry/socket/unix/unix_state_autogen.go
+++ b/pkg/sentry/socket/unix/unix_state_autogen.go
@@ -23,10 +23,9 @@ func (r *socketOperationsRefs) StateSave(stateSinkObject state.Sink) {
stateSinkObject.Save(0, &r.refCount)
}
-func (r *socketOperationsRefs) afterLoad() {}
-
func (r *socketOperationsRefs) StateLoad(stateSourceObject state.Source) {
stateSourceObject.Load(0, &r.refCount)
+ stateSourceObject.AfterLoad(r.afterLoad)
}
func (r *socketVFS2Refs) StateTypeName() string {
@@ -46,10 +45,9 @@ func (r *socketVFS2Refs) StateSave(stateSinkObject state.Sink) {
stateSinkObject.Save(0, &r.refCount)
}
-func (r *socketVFS2Refs) afterLoad() {}
-
func (r *socketVFS2Refs) StateLoad(stateSourceObject state.Source) {
stateSourceObject.Load(0, &r.refCount)
+ stateSourceObject.AfterLoad(r.afterLoad)
}
func (s *SocketOperations) StateTypeName() string {
diff --git a/pkg/sentry/socket/unix/unix_vfs2.go b/pkg/sentry/socket/unix/unix_vfs2.go
index 678355fb9..21514c7bb 100644
--- a/pkg/sentry/socket/unix/unix_vfs2.go
+++ b/pkg/sentry/socket/unix/unix_vfs2.go
@@ -80,6 +80,7 @@ func NewFileDescription(ep transport.Endpoint, stype linux.SockType, flags uint3
stype: stype,
},
}
+ sock.EnableLeakCheck()
sock.LockFD.Init(locks)
vfsfd := &sock.vfsfd
if err := vfsfd.Init(sock, flags, mnt, d, &vfs.FileDescriptionOptions{