On Wed, Aug 26, 2026 at 4:11 PM Jiayuan Chen <[email protected]> wrote: > > On the normal xmit path, while in urgent mode we refuse to build a > multi-segment TSO packet, so every segment gets its own urg_ptr: > > /* tcp_write_xmit() */ > limit = mss_now; > if (tso_segs > 1 && !tcp_urg_mode(tp)) > limit = tcp_mss_split_point(...); > > The retransmit path has no such guard. __tcp_retransmit_skb() builds a > segs > 1 skb and hands it to the GSO layer, which only advances th->seq > per segment and copies urg_ptr verbatim: > > /* __tcp_retransmit_skb() */ > len = cur_mss * segs; /* segs > 1, no urg_mode check */ > ... > /* tcp_gso_segment(): bumps seq only, urg_ptr is copied */ > > urg_ptr is an offset from the segment's own seq, so a copied value points > at a different place on each segment. The receiver rebuilds the absolute > urgent seq as seg.seq + urg_ptr, so it walks a moving urgent point instead > of the one OOB byte: > > seg1 seq 1 urg_ptr 5001 -> urgent @ 5001 (ok) > seg2 seq 1001 urg_ptr 5001 -> urgent @ 6001 (wrong, +MSS) > seg3 seq 2001 urg_ptr 5001 -> urgent @ 7001 (wrong, +2*MSS) > > The real OOB byte is never pointed at, so the receiver stops splicing it > out and delivers it as normal in-band data, corrupting the stream. > > Guard the retransmit length like the xmit path: keep segs = 1 while in > urgent mode. > > Fixes: 10d3be569243 ("tcp-tso: do not split TSO packets at retransmit time") > Signed-off-by: Jiayuan Chen <[email protected]> > ---
Nice! So we had a bug for 10 years. This is a testament to the fact that urgent mode is no longer used as advised by RFC 6093. Reviewed-by: Eric Dumazet <[email protected]> Thanks.

