From 52bee5297caf67ddb7bb6d23035255e09cb10861 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Tue, 4 Jan 2022 16:23:33 -0800 Subject: [PATCH] unix: call Listening under the endpoint lock PiperOrigin-RevId: 419703575 --- pkg/sentry/fs/gofer/socket.go | 2 +- pkg/sentry/fs/proc/net.go | 4 ++- pkg/sentry/fsimpl/gofer/socket.go | 2 +- pkg/sentry/fsimpl/proc/task_net.go | 4 ++- .../socket/unix/transport/connectioned.go | 29 ++++++++++++------- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/pkg/sentry/fs/gofer/socket.go b/pkg/sentry/fs/gofer/socket.go index 3080128b1..396de7f9d 100644 --- a/pkg/sentry/fs/gofer/socket.go +++ b/pkg/sentry/fs/gofer/socket.go @@ -93,7 +93,7 @@ func (e *endpoint) BidirectionalConnect(ctx context.Context, ce transport.Connec ce.Unlock() return syserr.ErrAlreadyConnected } - if ce.Listening() { + if ce.ListeningLocked() { ce.Unlock() return syserr.ErrInvalidEndpointState } diff --git a/pkg/sentry/fs/proc/net.go b/pkg/sentry/fs/proc/net.go index 187e9a921..57dacf9a3 100644 --- a/pkg/sentry/fs/proc/net.go +++ b/pkg/sentry/fs/proc/net.go @@ -442,11 +442,13 @@ func (n *netUnix) ReadSeqFileData(ctx context.Context, h seqfile.SeqHandle) ([]s sockFlags := 0 if ce, ok := sops.Endpoint().(transport.ConnectingEndpoint); ok { - if ce.Listening() { + ce.Lock() + if ce.ListeningLocked() { // For unix domain sockets, linux reports a single flag // value if the socket is listening, of __SO_ACCEPTCON. sockFlags = linux.SO_ACCEPTCON } + ce.Unlock() } // In the socket entry below, the value for the 'Num' field requires diff --git a/pkg/sentry/fsimpl/gofer/socket.go b/pkg/sentry/fsimpl/gofer/socket.go index 628ab3262..bf36c2323 100644 --- a/pkg/sentry/fsimpl/gofer/socket.go +++ b/pkg/sentry/fsimpl/gofer/socket.go @@ -66,7 +66,7 @@ func (e *endpoint) BidirectionalConnect(ctx context.Context, ce transport.Connec ce.Unlock() return syserr.ErrAlreadyConnected } - if ce.Listening() { + if ce.ListeningLocked() { ce.Unlock() return syserr.ErrInvalidEndpointState } diff --git a/pkg/sentry/fsimpl/proc/task_net.go b/pkg/sentry/fsimpl/proc/task_net.go index ab47ea5a7..a99efdc67 100644 --- a/pkg/sentry/fsimpl/proc/task_net.go +++ b/pkg/sentry/fsimpl/proc/task_net.go @@ -226,11 +226,13 @@ func (n *netUnixData) Generate(ctx context.Context, buf *bytes.Buffer) error { sockFlags := 0 if ce, ok := sops.Endpoint().(transport.ConnectingEndpoint); ok { - if ce.Listening() { + ce.Lock() + if ce.ListeningLocked() { // For unix domain sockets, linux reports a single flag // value if the socket is listening, of __SO_ACCEPTCON. sockFlags = linux.SO_ACCEPTCON } + ce.Unlock() } // Get inode number. diff --git a/pkg/sentry/socket/unix/transport/connectioned.go b/pkg/sentry/socket/unix/transport/connectioned.go index 14a17ef2e..8824aa08c 100644 --- a/pkg/sentry/socket/unix/transport/connectioned.go +++ b/pkg/sentry/socket/unix/transport/connectioned.go @@ -53,10 +53,11 @@ type ConnectingEndpoint interface { // so the connection attempt must be aborted if this returns true. Connected() bool - // Listening returns true iff the ConnectingEndpoint is in the listening - // state. ConnectingEndpoints cannot make connections while listening, so - // the connection attempt must be aborted if this returns true. - Listening() bool + // ListeningLocked returns true iff the ConnectingEndpoint is in the + // listening state. ConnectingEndpoints cannot make connections while + // listening, so the connection attempt must be aborted if this returns + // true. + ListeningLocked() bool // WaiterQueue returns a pointer to the endpoint's waiter queue. WaiterQueue() *waiter.Queue @@ -199,6 +200,12 @@ func (e *connectionedEndpoint) isBound() bool { // Listening implements ConnectingEndpoint.Listening. func (e *connectionedEndpoint) Listening() bool { + e.Lock() + defer e.Unlock() + return e.ListeningLocked() +} + +func (e *connectionedEndpoint) ListeningLocked() bool { return e.acceptedChan != nil } @@ -228,7 +235,7 @@ func (e *connectionedEndpoint) Close(ctx context.Context) { e.receiver = nil case e.isBound(): e.path = "" - case e.Listening(): + case e.ListeningLocked(): close(e.acceptedChan) acceptedChan = e.acceptedChan e.acceptedChan = nil @@ -276,14 +283,14 @@ func (e *connectionedEndpoint) BidirectionalConnect(ctx context.Context, ce Conn ce.Unlock() return syserr.ErrAlreadyConnected } - if ce.Listening() { + if ce.ListeningLocked() { e.Unlock() ce.Unlock() return syserr.ErrInvalidEndpointState } // Check bound state. - if !e.Listening() { + if !e.ListeningLocked() { e.Unlock() ce.Unlock() return syserr.ErrConnectionRefused @@ -378,7 +385,7 @@ func (e *connectionedEndpoint) Connect(ctx context.Context, server BoundEndpoint func (e *connectionedEndpoint) Listen(backlog int) *syserr.Error { e.Lock() defer e.Unlock() - if e.Listening() { + if e.ListeningLocked() { // Adjust the size of the channel iff we can fix existing // pending connections into the new one. if len(e.acceptedChan) > backlog { @@ -405,7 +412,7 @@ func (e *connectionedEndpoint) Listen(backlog int) *syserr.Error { func (e *connectionedEndpoint) Accept(peerAddr *tcpip.FullAddress) (Endpoint, *syserr.Error) { e.Lock() - if !e.Listening() { + if !e.ListeningLocked() { e.Unlock() return nil, syserr.ErrInvalidEndpointState } @@ -445,7 +452,7 @@ func (e *connectionedEndpoint) Accept(peerAddr *tcpip.FullAddress) (Endpoint, *s func (e *connectionedEndpoint) Bind(addr tcpip.FullAddress, commit func() *syserr.Error) *syserr.Error { e.Lock() defer e.Unlock() - if e.isBound() || e.Listening() { + if e.isBound() || e.ListeningLocked() { return syserr.ErrAlreadyBound } if addr.Addr == "" { @@ -490,7 +497,7 @@ func (e *connectionedEndpoint) Readiness(mask waiter.EventMask) waiter.EventMask if mask&waiter.WritableEvents != 0 && e.connected.Writable() { ready |= waiter.WritableEvents } - case e.Listening(): + case e.ListeningLocked(): if mask&waiter.ReadableEvents != 0 && len(e.acceptedChan) > 0 { ready |= waiter.ReadableEvents }