Skip to content

Commit 75ff39c

Browse files
edumazetdavem330
authored andcommitted
tcp: make challenge acks less predictable
Yue Cao claims that current host rate limiting of challenge ACKS (RFC 5961) could leak enough information to allow a patient attacker to hijack TCP sessions. He will soon provide details in an academic paper. This patch increases the default limit from 100 to 1000, and adds some randomization so that the attacker can no longer hijack sessions without spending a considerable amount of probes. Based on initial analysis and patch from Linus. Note that we also have per socket rate limiting, so it is tempting to remove the host limit in the future. v2: randomize the count of challenge acks per second, not the period. Fixes: 282f23c ("tcp: implement RFC 5961 3.2") Reported-by: Yue Cao <[email protected]> Signed-off-by: Eric Dumazet <[email protected]> Suggested-by: Linus Torvalds <[email protected]> Cc: Yuchung Cheng <[email protected]> Cc: Neal Cardwell <[email protected]> Acked-by: Neal Cardwell <[email protected]> Acked-by: Yuchung Cheng <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a612769 commit 75ff39c

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

net/ipv4/tcp_input.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ int sysctl_tcp_adv_win_scale __read_mostly = 1;
8787
EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
8888

8989
/* rfc5961 challenge ack rate limiting */
90-
int sysctl_tcp_challenge_ack_limit = 100;
90+
int sysctl_tcp_challenge_ack_limit = 1000;
9191

9292
int sysctl_tcp_stdurg __read_mostly;
9393
int sysctl_tcp_rfc1337 __read_mostly;
@@ -3458,21 +3458,26 @@ static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb)
34583458
static u32 challenge_timestamp;
34593459
static unsigned int challenge_count;
34603460
struct tcp_sock *tp = tcp_sk(sk);
3461-
u32 now;
3461+
u32 count, now;
34623462

34633463
/* First check our per-socket dupack rate limit. */
34643464
if (tcp_oow_rate_limited(sock_net(sk), skb,
34653465
LINUX_MIB_TCPACKSKIPPEDCHALLENGE,
34663466
&tp->last_oow_ack_time))
34673467
return;
34683468

3469-
/* Then check the check host-wide RFC 5961 rate limit. */
3469+
/* Then check host-wide RFC 5961 rate limit. */
34703470
now = jiffies / HZ;
34713471
if (now != challenge_timestamp) {
3472+
u32 half = (sysctl_tcp_challenge_ack_limit + 1) >> 1;
3473+
34723474
challenge_timestamp = now;
3473-
challenge_count = 0;
3475+
WRITE_ONCE(challenge_count, half +
3476+
prandom_u32_max(sysctl_tcp_challenge_ack_limit));
34743477
}
3475-
if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
3478+
count = READ_ONCE(challenge_count);
3479+
if (count > 0) {
3480+
WRITE_ONCE(challenge_count, count - 1);
34763481
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
34773482
tcp_send_ack(sk);
34783483
}

0 commit comments

Comments
 (0)