Page MenuHomeFreeBSD

Address rescue retransmission and FIN overlap
ClosedPublic

Authored by rscheff on Wed, Mar 17, 3:23 PM.

Details

Summary

The FIN bit is using Sequence Number Space.
Thus a rescue retransmission at the tail end
of a session which is being closed could be
off-by-one, and lead to a invalid memory free.

Also, if the partial ACK only Acks the data,
but not the FIN bit, that could also lead to
the creation of a SACK hole with start==end.

PR254309
PR254244

Test Plan

packetdrill script to recreate the issue and
also validate the proper operation:
'''

A simple test to verify behavior when SACK retransmission is lost

--tolerance_usecs=200000

0.0 sysctl net.inet.tcp.cc.algorithm=newreno
+0.0 sysctl net.inet.tcp.initcwnd_segments=10
+0.0 sysctl net.inet.tcp.rexmit_slop=1000
+0.0 sysctl net.inet.tcp.do_prr=0
+0.0 sysctl net.inet.tcp.do_prr_conservative=0
+0.0 sysctl net.inet.tcp.rfc6675_pipe=1
+0.0 sysctl net.inet.tcp.hostcache.purgenow=1

// Create a listening TCP socket.

+0.50 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0.01 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0.01 setsockopt(3, SOL_SOCKET, SO_SNDBUF, [1048576], 4) = 0
+0.01 setsockopt(3, SOL_SOCKET, SO_DEBUG, [1], 4) = 0
+0.01 bind(3, ..., ...) = 0
+0.01 listen(3, 1) = 0

// Establish a TCP connection.
+0.05 < S 0:0(0) win 65535 <mss 1000, sackOK, wscale 9, nop, nop, nop >
+0.00 > S. 0:0(0) ack 1 win 65535 <...>
+0.00 < . 1:1(0) ack 1 win 65535
+0.00 accept(3, ..., ...) = 4

Write some data to be sent to the simulated packetdrill receiver.
// Note: More than 33kB appears to get stuck on BSD
+0.20 write(4, ..., 20000) = 20000
+0.00 close(4) = 0

+0.00 > . 1:1001(1000) ack 1
+0.00 > . 1001:2001(1000) ack 1
+0.00 > . 2001:3001(1000) ack 1
+0.00 > . 3001:4001(1000) ack 1
+0.00 > . 4001:5001(1000) ack 1
+0.00 > . 5001:6001(1000) ack 1
+0.00 > . 6001:7001(1000) ack 1
+0.00 > . 7001:8001(1000) ack 1
+0.00 > . 8001:9001(1000) ack 1
+0.00 > . 9001:10001(1000) ack 1
+0.01 < . 1:1(0) ack 1001 win 65535 ACKing every packet
+0.00 > . 10001:11001(1000) ack 1
+0.00 > . 11001:12001(1000) ack 1
+0.01 < . 1:1(0) ack 2001 win 65535
to built up cwnd fast
+0.00 > . 12001:13001(1000) ack 1
+0.00 > . 13001:14001(1000) ack 1
+0.01 < . 1:1(0) ack 3001 win 65535
+0.00 > . 14001:15001(1000) ack 1
+0.00 > . 15001:16001(1000) ack 1
+0.01 < . 1:1(0) ack 4001 win 65535
+0.00 > . 16001:17001(1000) ack 1
+0.00 > . 17001:18001(1000) ack 1
+0.01 < . 1:1(0) ack 5001 win 65535
+0.00 > . 18001:19001(1000) ack 1
+0.00 > FP. 19001:20001(1000) ack 1
+0.01 < . 1:1(0) ack 6001 win 65535
+0.01 < . 1:1(0) ack 7001 win 65535
+0.01 < . 1:1(0) ack 8001 win 65535
+0.01 < . 1:1(0) ack 9001 win 65535
+0.01 < . 1:1(0) ack 10001 win 65535
+0.01 < . 1:1(0) ack 10001 win 65535 <sack 11001:12001,nop,nop>
+0.01 < . 1:1(0) ack 10001 win 65535 <sack 11001:13001,nop,nop>
+0.01 < . 1:1(0) ack 10001 win 65535 <sack 11001:14001,nop,nop>
+0.00 > . 10001:11001(1000) ack 1
+0.01 < . 1:1(0) ack 14001 win 65535
+0.00 > FP. 19001:20001(1000) ack 1 // Rescue Retransmission with FIN
+0.01 < . 1:1(0) ack 14001 win 65535 <sack 19001:20001,nop,nop>
+0.00 > . 14001:15001(1000) ack 1
+0.00 > . 15001:16001(1000) ack 1
+0.01 < . 1:1(0) ack 15001 win 65535 <sack 19001:20001,nop,nop>
+0.00 > . 16001:17001(1000) ack 1
+0.01 < . 1:1(0) ack 16001 win 65535 <sack 19001:20001,nop,nop>
+0.00 > . 17001:18001(1000) ack 1
+0.01 < . 1:1(0) ack 17001 win 65535 <sack 19001:20001,nop,nop>
+0.00 > . 18001:19001(1000) ack 1
+0.01 < . 1:1(0) ack 18001 win 65535 <sack 19001:20001,nop,nop>
+0.00 > F. 20001:20001(0) ack 1
+0.01 < . 1:1(0) ack 20001 win 65535
+0.00 > F. 20001:20001(0) ack 1
+0.1 < F. 1:1(0) ack 72002 win 65535
'''

Diff Detail

Repository
R10 FreeBSD src repository
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

This revision is now accepted and ready to land.Wed, Mar 17, 4:00 PM