Re: [PATCH] tcp: fastopen: check rsk_drop_req() in tcp_fastopen_create_child()
From: Yilin Zhang <hidden>
Date: 2026-09-03 07:07:19
Also in:
mptcp
Here is a packetdrill reproducer for the MPTCP subflow/TFO issue. It first obtains a TFO cookie and the server key during an MP_CAPABLE handshake, then sends an MP_JOIN SYN from a new source port with the corresponding token and cookie. The final ACK is intentionally omitted. With the fix, the request remains in the SYN queue: the MPTCP reset is followed by a normal SYN/ACK that echoes the cookie, and the second accept() returns EAGAIN. Without the fix, tcp_fastopen_create_child() ignores drop_req=true after subflow_syn_recv_sock() destroys the cloned child. The TFO path queues that child instead; the SYN/ACK omits the cookie, and closing the listener reports a refcount/use-after-free warning. -- >8 -- gtests/net/mptcp/fastopen/server-tfo-mpjoin-syn_v4.pkt -- >8 -- // Regression test: an MP_JOIN SYN with a valid TFO cookie must not queue // a destroyed child. --tolerance_usecs=100000 `../common/defaults.sh` // MPTCP listener with server-side Fast Open enabled. +0.0 socket(..., SOCK_STREAM, IPPROTO_MPTCP) = 3 +0.0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 +0.0 setsockopt(3, SOL_TCP, TCP_FASTOPEN, [2], 4) = 0 +0.0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) +0.0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 +0.0 bind(3, ..., ...) = 0 +0.0 listen(3, 1) = 0 // Obtain a TFO cookie and learn the server key. +0.1 < S 0:0(0) win 65535 <mss 1460, sackOK, TS val 100 ecr 0, nop, wscale 8, FO, nop, nop, mpcapable v1 flags[flag_h] nokey> +0.0 > S. 0:0(0) ack 1 <mss 1460, nop, nop, sackOK, nop, wscale 8, FO TFO_COOKIE, nop, nop, mpcapable v1 flags[flag_h] key[skey]> +0.2 < . 1:1(0) ack 1 win 450 < mpcapable v1 flags[flag_h] key[ckey=2, skey]> +0.0 accept(3, ..., ...) = 4 // Use a new source port with the same address; the cookie remains valid. +0.1 < 192.0.2.1:15000 > 192.168.0.1:8080 S 0:0(0) win 65535 <mss 1460, sackOK, nop, wscale 8, FO TFO_COOKIE, nop, nop, mp_join_syn address_id=1 token=sha256_32(skey), nop, nop> // The fatal MPTCP fallback destroys the cloned child and resets the flow. +0.0 > 192.168.0.1:8080 > 192.0.2.1:15000 R. 0:0(0) ack 1 <mp_reset 1> // Normal SYN processing sends a SYN/ACK and echoes the TFO cookie. +0.0 > 192.168.0.1:8080 > 192.0.2.1:15000 S. 0:0(0) ack 1 <mss 1460, nop, nop, sackOK, nop, wscale 8, FO TFO_COOKIE, nop, nop, mp_join_syn_ack address_id=0 sender_hmac=auto> // Without the final ACK, the request must remain in the SYN queue. +0.2 accept(3, ..., ...) = -1 EAGAIN (Resource temporarily unavailable) -- >8 -- For the MPTCP packetdrill fork, save this as `gtests/net/mptcp/fastopen/server-tfo-mpjoin-syn_v4.pkt` and run it with that fork's packetdrill binary. Tested on Linux 7.3.0-rc1 (defconfig + MPTCP + KASAN, QEMU guest): the unpatched kernel sends a SYN/ACK without the TFO cookie and reports `refcount_t: underflow; use-after-free` when the listener closes; the fixed kernel passes, with the second `accept()` returning EAGAIN.