Skip to content

Commit 1727a24

Browse files
committed
tcp: skip RST in resetConnectionLocked when snd/rcv are nil
1 parent f87a10e commit 1727a24

File tree

3 files changed

+71
-5
lines changed

3 files changed

+71
-5
lines changed

pkg/tcpip/transport/tcp/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ go_test(
215215
name = "tcp_test",
216216
size = "small",
217217
srcs = [
218+
"connect_test.go",
218219
"cubic_test.go",
219220
"main_test.go",
220221
"segment_test.go",

pkg/tcpip/transport/tcp/connect.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,12 +1081,26 @@ func (e *Endpoint) resetConnectionLocked(err tcpip.Error) {
10811081
//
10821082
// See: https://www.snellman.net/blog/archive/2016-02-01-tcp-rst/ for more
10831083
// information.
1084-
sndWndEnd := e.snd.SndUna.Add(e.snd.SndWnd)
1085-
resetSeqNum := sndWndEnd
1086-
if !sndWndEnd.LessThan(e.snd.SndNxt) || e.snd.SndNxt.Size(sndWndEnd) < (1<<e.snd.SndWndScale) {
1087-
resetSeqNum = e.snd.SndNxt
1084+
//
1085+
// e.snd and e.rcv may be nil if the endpoint is in a handshake
1086+
// state (e.g. SynSent) where the sender and receiver have not
1087+
// yet been initialized. Per Linux behavior, use a sequence
1088+
// number of zero when no ACK has been received (snd is nil),
1089+
// and a receive window of zero when rcv is nil since the
1090+
// connection will be immediately terminated.
1091+
var resetSeqNum seqnum.Value
1092+
var ackNum seqnum.Value
1093+
if e.snd != nil {
1094+
sndWndEnd := e.snd.SndUna.Add(e.snd.SndWnd)
1095+
resetSeqNum = sndWndEnd
1096+
if !sndWndEnd.LessThan(e.snd.SndNxt) || e.snd.SndNxt.Size(sndWndEnd) < (1<<e.snd.SndWndScale) {
1097+
resetSeqNum = e.snd.SndNxt
1098+
}
1099+
}
1100+
if e.rcv != nil {
1101+
ackNum = e.rcv.RcvNxt
10881102
}
1089-
e.sendEmptyRaw(header.TCPFlagAck|header.TCPFlagRst, resetSeqNum, e.rcv.RcvNxt, 0)
1103+
e.sendEmptyRaw(header.TCPFlagAck|header.TCPFlagRst, resetSeqNum, ackNum, 0)
10901104
}
10911105
// Don't purge read queues here. If there's buffered data, it's still allowed
10921106
// to be read.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2024 The gVisor Authors.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package tcp
16+
17+
import (
18+
"testing"
19+
20+
"gvisor.dev/gvisor/pkg/tcpip"
21+
"gvisor.dev/gvisor/pkg/tcpip/faketime"
22+
"gvisor.dev/gvisor/pkg/tcpip/stack"
23+
)
24+
25+
// TestResetConnectionLockedNilSndRcv verifies that resetConnectionLocked does
26+
// not panic when e.snd and e.rcv are nil, which occurs for endpoints in
27+
// handshake states (e.g. SynSent) that have not yet initialized their sender
28+
// and receiver. In this case, per Linux behavior, the RST is sent with a
29+
// sequence number of zero and a receive window of zero.
30+
func TestResetConnectionLockedNilSndRcv(t *testing.T) {
31+
fClock := faketime.NewManualClock()
32+
s := stack.New(stack.Options{
33+
TransportProtocols: []stack.TransportProtocolFactory{NewProtocol},
34+
Clock: fClock,
35+
})
36+
37+
ep := &Endpoint{
38+
stack: s,
39+
snd: nil,
40+
rcv: nil,
41+
}
42+
ep.setEndpointState(StateSynSent)
43+
44+
ep.mu.Lock()
45+
ep.resetConnectionLocked(&tcpip.ErrConnectionAborted{})
46+
ep.mu.Unlock()
47+
48+
if got, want := ep.EndpointState(), StateError; got != want {
49+
t.Errorf("endpoint state after resetConnectionLocked = %v, want %v", got, want)
50+
}
51+
}

0 commit comments

Comments
 (0)