Send a TCP RST in response to a TCP SYN-ACK on a listening endpoint

This change better follows what is outlined in RFC 793 section 3.4 figure 12
where a listening socket should not accept a SYN-ACK segment in response to a
(potentially) old SYN segment.

Tests: Test that checks the TCP RST segment sent in response to a TCP SYN-ACK
segment received on a listening TCP endpoint.
PiperOrigin-RevId: 278893114
This commit is contained in:
Ghanan Gowripalan
2019-11-06 10:44:20 -08:00
committed by gVisor bot
parent a824b48cea
commit d0d89ceedd
3 changed files with 73 additions and 2 deletions
+9
View File
@@ -25,6 +25,7 @@ import (
"gvisor.dev/gvisor/pkg/rand"
"gvisor.dev/gvisor/pkg/sleep"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/seqnum"
"gvisor.dev/gvisor/pkg/tcpip/stack"
@@ -400,6 +401,14 @@ func (e *endpoint) acceptQueueIsFull() bool {
// handleListenSegment is called when a listening endpoint receives a segment
// and needs to handle it.
func (e *endpoint) handleListenSegment(ctx *listenContext, s *segment) {
if s.flagsAreSet(header.TCPFlagSyn | header.TCPFlagAck) {
// RFC 793 section 3.4 page 35 (figure 12) outlines that a RST
// must be sent in response to a SYN-ACK while in the listen
// state to prevent completing a handshake from an old SYN.
e.sendTCP(&s.route, s.id, buffer.VectorisedView{}, e.ttl, e.sendTOS, header.TCPFlagRst, s.ackNumber, 0, 0, nil, nil)
return
}
// TODO(b/143300739): Use the userMSS of the listening socket
// for accepted sockets.
+8 -2
View File
@@ -99,8 +99,14 @@ func (s *segment) clone() *segment {
return t
}
func (s *segment) flagIsSet(flag uint8) bool {
return (s.flags & flag) != 0
// flagIsSet checks if at least one flag in flags is set in s.flags.
func (s *segment) flagIsSet(flags uint8) bool {
return s.flags&flags != 0
}
// flagsAreSet checks if all flags in flags are set in s.flags.
func (s *segment) flagsAreSet(flags uint8) bool {
return s.flags&flags == flags
}
func (s *segment) decRef() {
+56
View File
@@ -598,6 +598,62 @@ func TestUserSuppliedMSSOnConnectV6(t *testing.T) {
}
}
func TestSendRstOnListenerRxSynAckV4(t *testing.T) {
c := context.New(t, defaultMTU)
defer c.Cleanup()
c.Create(-1)
if err := c.EP.Bind(tcpip.FullAddress{Port: context.StackPort}); err != nil {
t.Fatal("Bind failed:", err)
}
if err := c.EP.Listen(10); err != nil {
t.Fatal("Listen failed:", err)
}
c.SendPacket(nil, &context.Headers{
SrcPort: context.TestPort,
DstPort: context.StackPort,
Flags: header.TCPFlagSyn | header.TCPFlagAck,
SeqNum: 100,
AckNum: 200,
})
checker.IPv4(t, c.GetPacket(), checker.TCP(
checker.DstPort(context.TestPort),
checker.TCPFlags(header.TCPFlagRst),
checker.SeqNum(200)))
}
func TestSendRstOnListenerRxSynAckV6(t *testing.T) {
c := context.New(t, defaultMTU)
defer c.Cleanup()
c.CreateV6Endpoint(true)
if err := c.EP.Bind(tcpip.FullAddress{Port: context.StackPort}); err != nil {
t.Fatal("Bind failed:", err)
}
if err := c.EP.Listen(10); err != nil {
t.Fatal("Listen failed:", err)
}
c.SendV6Packet(nil, &context.Headers{
SrcPort: context.TestPort,
DstPort: context.StackPort,
Flags: header.TCPFlagSyn | header.TCPFlagAck,
SeqNum: 100,
AckNum: 200,
})
checker.IPv6(t, c.GetV6Packet(), checker.TCP(
checker.DstPort(context.TestPort),
checker.TCPFlags(header.TCPFlagRst),
checker.SeqNum(200)))
}
func TestTOSV4(t *testing.T) {
c := context.New(t, defaultMTU)
defer c.Cleanup()