mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
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:
committed by
gVisor bot
parent
a824b48cea
commit
d0d89ceedd
@@ -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.
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user