Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

tcp: do not accept packets beyond window

Currently, TCP accepts incoming packets which might go beyond the
offered RWIN.

Add to tcp_sequence() the validation of packet end sequence.

Add the corresponding check in the fast path.

We relax this new constraint if the receive queue is empty,
to not freeze flows from buggy peers.

Add a new drop reason : SKB_DROP_REASON_TCP_INVALID_END_SEQUENCE.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20250711114006.480026-2-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Eric Dumazet and committed by
Jakub Kicinski
9ca48d61 a86eb2a6

+24 -6
+7 -1
include/net/dropreason-core.h
··· 45 45 FN(TCP_LISTEN_OVERFLOW) \ 46 46 FN(TCP_OLD_SEQUENCE) \ 47 47 FN(TCP_INVALID_SEQUENCE) \ 48 + FN(TCP_INVALID_END_SEQUENCE) \ 48 49 FN(TCP_INVALID_ACK_SEQUENCE) \ 49 50 FN(TCP_RESET) \ 50 51 FN(TCP_INVALID_SYN) \ ··· 304 303 SKB_DROP_REASON_TCP_LISTEN_OVERFLOW, 305 304 /** @SKB_DROP_REASON_TCP_OLD_SEQUENCE: Old SEQ field (duplicate packet) */ 306 305 SKB_DROP_REASON_TCP_OLD_SEQUENCE, 307 - /** @SKB_DROP_REASON_TCP_INVALID_SEQUENCE: Not acceptable SEQ field */ 306 + /** @SKB_DROP_REASON_TCP_INVALID_SEQUENCE: Not acceptable SEQ field. */ 308 307 SKB_DROP_REASON_TCP_INVALID_SEQUENCE, 308 + /** 309 + * @SKB_DROP_REASON_TCP_INVALID_END_SEQUENCE: 310 + * Not acceptable END_SEQ field. 311 + */ 312 + SKB_DROP_REASON_TCP_INVALID_END_SEQUENCE, 309 313 /** 310 314 * @SKB_DROP_REASON_TCP_INVALID_ACK_SEQUENCE: Not acceptable ACK SEQ 311 315 * field because ack sequence is not in the window between snd_una
+17 -5
net/ipv4/tcp_input.c
··· 4391 4391 * (borrowed from freebsd) 4392 4392 */ 4393 4393 4394 - static enum skb_drop_reason tcp_sequence(const struct tcp_sock *tp, 4394 + static enum skb_drop_reason tcp_sequence(const struct sock *sk, 4395 4395 u32 seq, u32 end_seq) 4396 4396 { 4397 + const struct tcp_sock *tp = tcp_sk(sk); 4398 + 4397 4399 if (before(end_seq, tp->rcv_wup)) 4398 4400 return SKB_DROP_REASON_TCP_OLD_SEQUENCE; 4399 4401 4400 - if (after(seq, tp->rcv_nxt + tcp_receive_window(tp))) 4401 - return SKB_DROP_REASON_TCP_INVALID_SEQUENCE; 4402 + if (after(end_seq, tp->rcv_nxt + tcp_receive_window(tp))) { 4403 + if (after(seq, tp->rcv_nxt + tcp_receive_window(tp))) 4404 + return SKB_DROP_REASON_TCP_INVALID_SEQUENCE; 4405 + 4406 + /* Only accept this packet if receive queue is empty. */ 4407 + if (skb_queue_len(&sk->sk_receive_queue)) 4408 + return SKB_DROP_REASON_TCP_INVALID_END_SEQUENCE; 4409 + } 4402 4410 4403 4411 return SKB_NOT_DROPPED_YET; 4404 4412 } ··· 5889 5881 5890 5882 step1: 5891 5883 /* Step 1: check sequence number */ 5892 - reason = tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq); 5884 + reason = tcp_sequence(sk, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq); 5893 5885 if (reason) { 5894 5886 /* RFC793, page 37: "In all states except SYN-SENT, all reset 5895 5887 * (RST) segments are validated by checking their SEQ-fields." ··· 6118 6110 if (tcp_checksum_complete(skb)) 6119 6111 goto csum_error; 6120 6112 6113 + if (after(TCP_SKB_CB(skb)->end_seq, 6114 + tp->rcv_nxt + tcp_receive_window(tp))) 6115 + goto validate; 6116 + 6121 6117 if ((int)skb->truesize > sk->sk_forward_alloc) 6122 6118 goto step5; 6123 6119 ··· 6177 6165 /* 6178 6166 * Standard slow path. 6179 6167 */ 6180 - 6168 + validate: 6181 6169 if (!tcp_validate_incoming(sk, skb, th, 1)) 6182 6170 return; 6183 6171