diff options
author | Bhasker Hariharan <bhaskerh@google.com> | 2021-02-26 20:14:34 -0800 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-02-26 20:16:48 -0800 |
commit | 037bb2f45abada02fb50b563f3d37381f88de7f5 (patch) | |
tree | b005d16f3275e7c0253a4bbf9269072db6656d71 /pkg | |
parent | af6e6d5e7fc8266016eefa309d3857c92102db9a (diff) |
Fix panic due to zero length writes in TCP.
There is a short race where in Write an endpoint can transition from writable
to non-writable state due to say an incoming RST during the time we release
the endpoint lock and reacquire after copying the payload. In such a case
if the write happens to be a zero sized write we end up trying to call
sendData() even though nothing was queued.
This can panic when trying to enable/disable TCP timers if the endpoint had
already transitioned to a CLOSED/ERROR state due to the incoming RST as we
cleanup timers when the protocol goroutine terminates.
Sadly the race window is small enough that my attempts at reproducing the panic
in a syscall test has not been successful.
PiperOrigin-RevId: 359887905
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/tcpip/transport/tcp/endpoint.go | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/pkg/tcpip/transport/tcp/endpoint.go b/pkg/tcpip/transport/tcp/endpoint.go index 8c5be0586..83ec99fa9 100644 --- a/pkg/tcpip/transport/tcp/endpoint.go +++ b/pkg/tcpip/transport/tcp/endpoint.go @@ -1586,7 +1586,9 @@ func (e *endpoint) Write(p tcpip.Payloader, opts tcpip.WriteOptions) (int64, tcp return e.drainSendQueueLocked(), len(v), nil }() - if err != nil { + // Return if either we didn't queue anything or if an error occurred while + // attempting to queue data. + if n == 0 || err != nil { return 0, err } e.sendData(nextSeg) |