From d154c6a25f9d2b88b8ce22cff575467b159f06bc Mon Sep 17 00:00:00 2001 From: Christopher Koch Date: Wed, 16 May 2018 13:28:29 -0700 Subject: [PATCH] Refcount socket Dirents correctly. This should fix the socket Dirent memory leak. fs.NewFile takes a new reference. It should hold the *only* reference. DecRef that socket Dirent. Before the globalDirentMap was introduced, a mis-refcounted Dirent would be garbage collected when all references to it were gone. For socket Dirents, this meant that they would be garbage collected when the associated fs.Files disappeared. After the globalDirentMap, Dirents *must* be reference-counted correctly to be garbage collected, as Dirents remove themselves from the global map when their refcount goes to -1 (see Dirent.destroy). That removes the last pointer to that Dirent. PiperOrigin-RevId: 196878973 Change-Id: Ic7afcd1de97c7101ccb13be5fc31de0fb50963f0 --- pkg/sentry/socket/epsocket/epsocket.go | 1 + pkg/sentry/socket/hostinet/socket.go | 1 + pkg/sentry/socket/netlink/provider.go | 1 + pkg/sentry/socket/unix/unix.go | 1 + 4 files changed, 4 insertions(+) diff --git a/pkg/sentry/socket/epsocket/epsocket.go b/pkg/sentry/socket/epsocket/epsocket.go index 3e4887e16..18cb70c96 100644 --- a/pkg/sentry/socket/epsocket/epsocket.go +++ b/pkg/sentry/socket/epsocket/epsocket.go @@ -116,6 +116,7 @@ type SocketOperations struct { // New creates a new endpoint socket. func New(t *kernel.Task, family int, skType unix.SockType, queue *waiter.Queue, endpoint tcpip.Endpoint) *fs.File { dirent := socket.NewDirent(t, epsocketDevice) + defer dirent.DecRef() return fs.NewFile(t, dirent, fs.FileFlags{Read: true, Write: true}, &SocketOperations{ Queue: queue, family: family, diff --git a/pkg/sentry/socket/hostinet/socket.go b/pkg/sentry/socket/hostinet/socket.go index 02fad1c60..8f901df6c 100644 --- a/pkg/sentry/socket/hostinet/socket.go +++ b/pkg/sentry/socket/hostinet/socket.go @@ -65,6 +65,7 @@ func newSocketFile(ctx context.Context, fd int, nonblock bool) (*fs.File, *syser return nil, syserr.FromError(err) } dirent := socket.NewDirent(ctx, socketDevice) + defer dirent.DecRef() return fs.NewFile(ctx, dirent, fs.FileFlags{NonBlocking: nonblock, Read: true, Write: true}, s), nil } diff --git a/pkg/sentry/socket/netlink/provider.go b/pkg/sentry/socket/netlink/provider.go index 36800da4d..e874216f4 100644 --- a/pkg/sentry/socket/netlink/provider.go +++ b/pkg/sentry/socket/netlink/provider.go @@ -89,6 +89,7 @@ func (*socketProvider) Socket(t *kernel.Task, stype unix.SockType, protocol int) } d := socket.NewDirent(t, netlinkSocketDevice) + defer d.DecRef() return fs.NewFile(t, d, fs.FileFlags{Read: true, Write: true}, s), nil } diff --git a/pkg/sentry/socket/unix/unix.go b/pkg/sentry/socket/unix/unix.go index f83156c8e..27bacbbc3 100644 --- a/pkg/sentry/socket/unix/unix.go +++ b/pkg/sentry/socket/unix/unix.go @@ -56,6 +56,7 @@ type SocketOperations struct { // New creates a new unix socket. func New(ctx context.Context, endpoint unix.Endpoint) *fs.File { dirent := socket.NewDirent(ctx, unixSocketDevice) + defer dirent.DecRef() return NewWithDirent(ctx, dirent, endpoint, fs.FileFlags{Read: true, Write: true}) }