From 9149b2cefdb5883e41416aecea16fba4c5cd3ac1 Mon Sep 17 00:00:00 2001
From: Andrei Vagin <avagin@google.com>
Date: Thu, 2 Sep 2021 15:13:45 -0700
Subject: unix: avoid taking two endpoint locks

If we want to take two endpoint locks, we need to be sure that we always
take them in the same order.

Accept() locks the listening endpoint to work with acceptedChan and then
it calls GetLocalAddress that locks an accepted endpoint. Actually, we
can release the listening endpoint lock before calling GetLocalAddress.

Reported-by: syzbot+f52bd603f51a4ae91054@syzkaller.appspotmail.com
PiperOrigin-RevId: 394553823
---
 pkg/sentry/socket/unix/transport/connectioned.go | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

(limited to 'pkg/sentry/socket/unix')

diff --git a/pkg/sentry/socket/unix/transport/connectioned.go b/pkg/sentry/socket/unix/transport/connectioned.go
index 9a398c3b5..b3f0cf563 100644
--- a/pkg/sentry/socket/unix/transport/connectioned.go
+++ b/pkg/sentry/socket/unix/transport/connectioned.go
@@ -406,14 +406,15 @@ func (e *connectionedEndpoint) Listen(backlog int) *syserr.Error {
 // Accept accepts a new connection.
 func (e *connectionedEndpoint) Accept(peerAddr *tcpip.FullAddress) (Endpoint, *syserr.Error) {
 	e.Lock()
-	defer e.Unlock()
 
 	if !e.Listening() {
+		e.Unlock()
 		return nil, syserr.ErrInvalidEndpointState
 	}
 
 	select {
 	case ne := <-e.acceptedChan:
+		e.Unlock()
 		if peerAddr != nil {
 			ne.Lock()
 			c := ne.connected
@@ -429,6 +430,7 @@ func (e *connectionedEndpoint) Accept(peerAddr *tcpip.FullAddress) (Endpoint, *s
 		return ne, nil
 
 	default:
+		e.Unlock()
 		// Nothing left.
 		return nil, syserr.ErrWouldBlock
 	}
-- 
cgit v1.2.3