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
This commit is contained in:
Ian Gudger
2018-08-08 19:23:48 -07:00
committed by Shentubot
parent 9144ddda09
commit 2a44362c0b
2 changed files with 12 additions and 2 deletions
+7 -1
View File
@@ -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
}
+5 -1
View File
@@ -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.