Skip to content

Commit 8092160

Browse files
edumazetopsiff
authored andcommitted
tcp: reduce accepted window in NEW_SYN_RECV state
mainline inclusion from mainline-v6.10-rc2 category: bugfix Jason commit made checks against ACK sequence less strict and can be exploited by attackers to establish spoofed flows with less probes. Innocent users might use tcp_rmem[1] == 1,000,000,000, or something more reasonable. An attacker can use a regular TCP connection to learn the server initial tp->rcv_wnd, and use it to optimize the attack. If we make sure that only the announced window (smaller than 65535) is used for ACK validation, we force an attacker to use 65537 packets to complete the 3WHS (assuming server ISN is unknown) Fixes: 378979e ("tcp: remove 64 KByte limit for initial tp->rcv_wnd value") Link: https://datatracker.ietf.org/meeting/119/materials/slides-119-tcpm-ghost-acks-00 Signed-off-by: Eric Dumazet <edumazet@google.com> Acked-by: Neal Cardwell <ncardwell@google.com> Reviewed-by: Jason Xing <kerneljasonxing@gmail.com> Link: https://lore.kernel.org/r/20240523130528.60376-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Conflicts: net/ipv4/tcp_ipv4.c net/ipv6/tcp_ipv6.c (cherry picked from commit f4dca95) Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
1 parent f7ee893 commit 8092160

4 files changed

Lines changed: 19 additions & 14 deletions

File tree

include/net/request_sock.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,4 +238,16 @@ static inline int reqsk_queue_len_young(const struct request_sock_queue *queue)
238238
return atomic_read(&queue->young);
239239
}
240240

241+
/* RFC 7323 2.3 Using the Window Scale Option
242+
* The window field (SEG.WND) of every outgoing segment, with the
243+
* exception of <SYN> segments, MUST be right-shifted by
244+
* Rcv.Wind.Shift bits.
245+
*
246+
* This means the SEG.WND carried in SYNACK can not exceed 65535.
247+
* We use this property to harden TCP stack while in NEW_SYN_RECV state.
248+
*/
249+
static inline u32 tcp_synack_window(const struct request_sock *req)
250+
{
251+
return min(req->rsk_rcv_wnd, 65535U);
252+
}
241253
#endif /* _REQUEST_SOCK_H */

net/ipv4/tcp_ipv4.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -985,16 +985,11 @@ static void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
985985
u32 seq = (sk->sk_state == TCP_LISTEN) ? tcp_rsk(req)->snt_isn + 1 :
986986
tcp_sk(sk)->snd_nxt;
987987

988-
/* RFC 7323 2.3
989-
* The window field (SEG.WND) of every outgoing segment, with the
990-
* exception of <SYN> segments, MUST be right-shifted by
991-
* Rcv.Wind.Shift bits:
992-
*/
993988
addr = (union tcp_md5_addr *)&ip_hdr(skb)->saddr;
994989
l3index = tcp_v4_sdif(skb) ? inet_iif(skb) : 0;
995990
tcp_v4_send_ack(sk, skb, seq,
996991
tcp_rsk(req)->rcv_nxt,
997-
req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
992+
tcp_synack_window(req) >> inet_rsk(req)->rcv_wscale,
998993
tcp_time_stamp_raw() + tcp_rsk(req)->ts_off,
999994
READ_ONCE(req->ts_recent),
1000995
0,

net/ipv4/tcp_minisocks.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -739,8 +739,11 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
739739

740740
/* RFC793: "first check sequence number". */
741741

742-
if (paws_reject || !tcp_in_window(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq,
743-
tcp_rsk(req)->rcv_nxt, tcp_rsk(req)->rcv_nxt + req->rsk_rcv_wnd)) {
742+
if (paws_reject || !tcp_in_window(TCP_SKB_CB(skb)->seq,
743+
TCP_SKB_CB(skb)->end_seq,
744+
tcp_rsk(req)->rcv_nxt,
745+
tcp_rsk(req)->rcv_nxt +
746+
tcp_synack_window(req))) {
744747
/* Out of window: send ACK and drop. */
745748
if (!(flg & TCP_FLAG_RST) &&
746749
!tcp_oow_rate_limited(sock_net(sk), skb,

net/ipv6/tcp_ipv6.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,15 +1111,10 @@ static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
11111111
/* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV
11121112
* sk->sk_state == TCP_SYN_RECV -> for Fast Open.
11131113
*/
1114-
/* RFC 7323 2.3
1115-
* The window field (SEG.WND) of every outgoing segment, with the
1116-
* exception of <SYN> segments, MUST be right-shifted by
1117-
* Rcv.Wind.Shift bits:
1118-
*/
11191114
tcp_v6_send_ack(sk, skb, (sk->sk_state == TCP_LISTEN) ?
11201115
tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt,
11211116
tcp_rsk(req)->rcv_nxt,
1122-
req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
1117+
tcp_synack_window(req) >> inet_rsk(req)->rcv_wscale,
11231118
tcp_time_stamp_raw() + tcp_rsk(req)->ts_off,
11241119
READ_ONCE(req->ts_recent), sk->sk_bound_dev_if,
11251120
tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr, l3index),

0 commit comments

Comments
 (0)