Fix data race in synRcvdState.

When checking the length of the acceptedChan we should hold the
endpoint mutex otherwise a syn received while the listening socket
is being closed can result in a data race where the cleanupLocked
routine sets acceptedChan to nil while a handshake goroutine
in progress could try and check it at the same time.

PiperOrigin-RevId: 251537697
This commit is contained in:
Bhasker Hariharan 2019-06-04 16:16:24 -07:00 committed by Shentubot
parent 7398f013f0
commit e0fb921205
1 changed files with 13 additions and 8 deletions

View File

@ -284,14 +284,19 @@ func (h *handshake) synRcvdState(s *segment) *tcpip.Error {
// listenContext is also used by a tcp.Forwarder and in that
// context we do not have a listening endpoint to check the
// backlog. So skip this check if listenEP is nil.
if h.listenEP != nil && len(h.listenEP.acceptedChan) == cap(h.listenEP.acceptedChan) {
// If there is no space in the accept queue to accept
// this endpoint then silently drop this ACK. The peer
// will anyway resend the ack and we can complete the
// connection the next time it's retransmitted.
h.ep.stack.Stats().TCP.ListenOverflowAckDrop.Increment()
h.ep.stack.Stats().DroppedPackets.Increment()
return nil
if h.listenEP != nil {
h.listenEP.mu.Lock()
if len(h.listenEP.acceptedChan) == cap(h.listenEP.acceptedChan) {
h.listenEP.mu.Unlock()
// If there is no space in the accept queue to accept
// this endpoint then silently drop this ACK. The peer
// will anyway resend the ack and we can complete the
// connection the next time it's retransmitted.
h.ep.stack.Stats().TCP.ListenOverflowAckDrop.Increment()
h.ep.stack.Stats().DroppedPackets.Increment()
return nil
}
h.listenEP.mu.Unlock()
}
// If the timestamp option is negotiated and the segment does
// not carry a timestamp option then the segment must be dropped