From 2a44362c0b99c6ab800e1b0d26e4f368a5e7f9f1 Mon Sep 17 00:00:00 2001 From: Ian Gudger Date: Wed, 8 Aug 2018 19:23:02 -0700 Subject: Fix data race in unix.BoundEndpoint.UnidirectionalConnect. Data race is: Read: (*connectionlessEndpoint).UnidirectionalConnect: writeQueue: e.receiver.(*queueReceiver).readQueue, Write: (*connectionlessEndpoint).Close: e.receiver = nil The problem is that (*connectionlessEndpoint).UnidirectionalConnect assumed that baseEndpoint.receiver is immutable which is explicitly not the case. Fixing this required two changes: 1. Add synchronization around access of baseEndpoint.receiver in (*connectionlessEndpoint).UnidirectionalConnect. 2. Check for baseEndpoint.receiver being nil in (*connectionlessEndpoint).UnidirectionalConnect. PiperOrigin-RevId: 207984402 Change-Id: Icddeeb43805e777fa3ef874329fa704891d14181 --- pkg/tcpip/transport/unix/connectionless.go | 8 +++++++- pkg/tcpip/transport/unix/unix.go | 6 +++++- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'pkg') diff --git a/pkg/tcpip/transport/unix/connectionless.go b/pkg/tcpip/transport/unix/connectionless.go index 2a6ec8b4b..ebd4802b0 100644 --- a/pkg/tcpip/transport/unix/connectionless.go +++ b/pkg/tcpip/transport/unix/connectionless.go @@ -77,9 +77,15 @@ func (e *connectionlessEndpoint) BidirectionalConnect(ce ConnectingEndpoint, ret // UnidirectionalConnect implements BoundEndpoint.UnidirectionalConnect. func (e *connectionlessEndpoint) UnidirectionalConnect() (ConnectedEndpoint, *tcpip.Error) { + e.Lock() + r := e.receiver + e.Unlock() + if r == nil { + return nil, tcpip.ErrConnectionRefused + } return &connectedEndpoint{ endpoint: e, - writeQueue: e.receiver.(*queueReceiver).readQueue, + writeQueue: r.(*queueReceiver).readQueue, }, nil } diff --git a/pkg/tcpip/transport/unix/unix.go b/pkg/tcpip/transport/unix/unix.go index 8e4af3139..0bb00df42 100644 --- a/pkg/tcpip/transport/unix/unix.go +++ b/pkg/tcpip/transport/unix/unix.go @@ -224,7 +224,11 @@ type BoundEndpoint interface { // type that isn't SockStream or SockSeqpacket. BidirectionalConnect(ep ConnectingEndpoint, returnConnect func(Receiver, ConnectedEndpoint)) *tcpip.Error - // UnidirectionalConnect establishes a write-only connection to a unix endpoint. + // UnidirectionalConnect establishes a write-only connection to a unix + // endpoint. + // + // An endpoint which calls UnidirectionalConnect and supports it itself must + // not hold its own lock when calling UnidirectionalConnect. // // This method will return tcpip.ErrConnectionRefused on a non-SockDgram // endpoint. -- cgit v1.2.3