diff options
author | Bhasker Hariharan <bhaskerh@google.com> | 2019-06-04 16:16:24 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2019-06-04 16:17:24 -0700 |
commit | e0fb921205b79f401375544652e4de8077162292 (patch) | |
tree | 10e51ffa7d84894cf360076e4fa839c0f60bdcb7 /pkg | |
parent | 7398f013f043cfe43b5fc615bd24b641df17e6bc (diff) |
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
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/tcpip/transport/tcp/connect.go | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/pkg/tcpip/transport/tcp/connect.go b/pkg/tcpip/transport/tcp/connect.go index 2aed6f286..371d2ed29 100644 --- a/pkg/tcpip/transport/tcp/connect.go +++ b/pkg/tcpip/transport/tcp/connect.go @@ -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 |