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
This commit is contained in:
Andrei Vagin
2021-09-02 15:15:45 -07:00
committed by gVisor bot
parent bd75e52ad8
commit 9149b2cefd
@@ -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
}