diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-23 02:44:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-23 02:44:31 -0400 |
commit | 107df03203bb66de56e2caec3bde6d22b55480c5 (patch) | |
tree | cff42c091a4a9f43203bbb85c9cf526857470a8f /net/ipv4/tcp_input.c | |
parent | 88083e9845612826dfd44a5215647b4f6567317c (diff) | |
parent | f8e7718cc0445587fe8530fc2d240d9aac2c9072 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller:
1) Fix memory leak in nftables, from Liping Zhang.
2) Need to check result of vlan_insert_tag() in batman-adv otherwise we
risk NULL skb derefs, from Sven Eckelmann.
3) Check for dev_alloc_skb() failures in cfg80211, from Gregory
Greenman.
4) Handle properly when we have ppp_unregister_channel() happening in
parallel with ppp_connect_channel(), from WANG Cong.
5) Fix DCCP deadlock, from Eric Dumazet.
6) Bail out properly in UDP if sk_filter() truncates the packet to be
smaller than even the space that the protocol headers need. From
Michal Kubecek.
7) Similarly for rose, dccp, and sctp, from Willem de Bruijn.
8) Make TCP challenge ACKs less predictable, from Eric Dumazet.
9) Fix infinite loop in bgmac_dma_tx_add() from Florian Fainelli.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (65 commits)
packet: propagate sock_cmsg_send() error
net/mlx5e: Fix del vxlan port command buffer memset
packet: fix second argument of sock_tx_timestamp()
net: switchdev: change ageing_time type to clock_t
Update maintainer for EHEA driver.
net/mlx4_en: Add resilience in low memory systems
net/mlx4_en: Move filters cleanup to a proper location
sctp: load transport header after sk_filter
net/sched/sch_htb: clamp xstats tokens to fit into 32-bit int
net: cavium: liquidio: Avoid dma_unmap_single on uninitialized ndata
net: nb8800: Fix SKB leak in nb8800_receive()
et131x: Fix logical vs bitwise check in et131x_tx_timeout()
vlan: use a valid default mtu value for vlan over macsec
net: bgmac: Fix infinite loop in bgmac_dma_tx_add()
mlxsw: spectrum: Prevent invalid ingress buffer mapping
mlxsw: spectrum: Prevent overwrite of DCB capability fields
mlxsw: spectrum: Don't emit errors when PFC is disabled
mlxsw: spectrum: Indicate support for autonegotiation
mlxsw: spectrum: Force link training according to admin state
r8152: add MODULE_VERSION
...
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 54 |
1 files changed, 32 insertions, 22 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index d6c8f4cd0800..42bf89aaf6a5 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -87,7 +87,7 @@ int sysctl_tcp_adv_win_scale __read_mostly = 1; | |||
87 | EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); | 87 | EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); |
88 | 88 | ||
89 | /* rfc5961 challenge ack rate limiting */ | 89 | /* rfc5961 challenge ack rate limiting */ |
90 | int sysctl_tcp_challenge_ack_limit = 100; | 90 | int sysctl_tcp_challenge_ack_limit = 1000; |
91 | 91 | ||
92 | int sysctl_tcp_stdurg __read_mostly; | 92 | int sysctl_tcp_stdurg __read_mostly; |
93 | int sysctl_tcp_rfc1337 __read_mostly; | 93 | int sysctl_tcp_rfc1337 __read_mostly; |
@@ -3421,6 +3421,23 @@ static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32 | |||
3421 | return flag; | 3421 | return flag; |
3422 | } | 3422 | } |
3423 | 3423 | ||
3424 | static bool __tcp_oow_rate_limited(struct net *net, int mib_idx, | ||
3425 | u32 *last_oow_ack_time) | ||
3426 | { | ||
3427 | if (*last_oow_ack_time) { | ||
3428 | s32 elapsed = (s32)(tcp_time_stamp - *last_oow_ack_time); | ||
3429 | |||
3430 | if (0 <= elapsed && elapsed < sysctl_tcp_invalid_ratelimit) { | ||
3431 | NET_INC_STATS(net, mib_idx); | ||
3432 | return true; /* rate-limited: don't send yet! */ | ||
3433 | } | ||
3434 | } | ||
3435 | |||
3436 | *last_oow_ack_time = tcp_time_stamp; | ||
3437 | |||
3438 | return false; /* not rate-limited: go ahead, send dupack now! */ | ||
3439 | } | ||
3440 | |||
3424 | /* Return true if we're currently rate-limiting out-of-window ACKs and | 3441 | /* Return true if we're currently rate-limiting out-of-window ACKs and |
3425 | * thus shouldn't send a dupack right now. We rate-limit dupacks in | 3442 | * thus shouldn't send a dupack right now. We rate-limit dupacks in |
3426 | * response to out-of-window SYNs or ACKs to mitigate ACK loops or DoS | 3443 | * response to out-of-window SYNs or ACKs to mitigate ACK loops or DoS |
@@ -3434,21 +3451,9 @@ bool tcp_oow_rate_limited(struct net *net, const struct sk_buff *skb, | |||
3434 | /* Data packets without SYNs are not likely part of an ACK loop. */ | 3451 | /* Data packets without SYNs are not likely part of an ACK loop. */ |
3435 | if ((TCP_SKB_CB(skb)->seq != TCP_SKB_CB(skb)->end_seq) && | 3452 | if ((TCP_SKB_CB(skb)->seq != TCP_SKB_CB(skb)->end_seq) && |
3436 | !tcp_hdr(skb)->syn) | 3453 | !tcp_hdr(skb)->syn) |
3437 | goto not_rate_limited; | 3454 | return false; |
3438 | |||
3439 | if (*last_oow_ack_time) { | ||
3440 | s32 elapsed = (s32)(tcp_time_stamp - *last_oow_ack_time); | ||
3441 | |||
3442 | if (0 <= elapsed && elapsed < sysctl_tcp_invalid_ratelimit) { | ||
3443 | NET_INC_STATS(net, mib_idx); | ||
3444 | return true; /* rate-limited: don't send yet! */ | ||
3445 | } | ||
3446 | } | ||
3447 | |||
3448 | *last_oow_ack_time = tcp_time_stamp; | ||
3449 | 3455 | ||
3450 | not_rate_limited: | 3456 | return __tcp_oow_rate_limited(net, mib_idx, last_oow_ack_time); |
3451 | return false; /* not rate-limited: go ahead, send dupack now! */ | ||
3452 | } | 3457 | } |
3453 | 3458 | ||
3454 | /* RFC 5961 7 [ACK Throttling] */ | 3459 | /* RFC 5961 7 [ACK Throttling] */ |
@@ -3458,21 +3463,26 @@ static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb) | |||
3458 | static u32 challenge_timestamp; | 3463 | static u32 challenge_timestamp; |
3459 | static unsigned int challenge_count; | 3464 | static unsigned int challenge_count; |
3460 | struct tcp_sock *tp = tcp_sk(sk); | 3465 | struct tcp_sock *tp = tcp_sk(sk); |
3461 | u32 now; | 3466 | u32 count, now; |
3462 | 3467 | ||
3463 | /* First check our per-socket dupack rate limit. */ | 3468 | /* First check our per-socket dupack rate limit. */ |
3464 | if (tcp_oow_rate_limited(sock_net(sk), skb, | 3469 | if (__tcp_oow_rate_limited(sock_net(sk), |
3465 | LINUX_MIB_TCPACKSKIPPEDCHALLENGE, | 3470 | LINUX_MIB_TCPACKSKIPPEDCHALLENGE, |
3466 | &tp->last_oow_ack_time)) | 3471 | &tp->last_oow_ack_time)) |
3467 | return; | 3472 | return; |
3468 | 3473 | ||
3469 | /* Then check the check host-wide RFC 5961 rate limit. */ | 3474 | /* Then check host-wide RFC 5961 rate limit. */ |
3470 | now = jiffies / HZ; | 3475 | now = jiffies / HZ; |
3471 | if (now != challenge_timestamp) { | 3476 | if (now != challenge_timestamp) { |
3477 | u32 half = (sysctl_tcp_challenge_ack_limit + 1) >> 1; | ||
3478 | |||
3472 | challenge_timestamp = now; | 3479 | challenge_timestamp = now; |
3473 | challenge_count = 0; | 3480 | WRITE_ONCE(challenge_count, half + |
3481 | prandom_u32_max(sysctl_tcp_challenge_ack_limit)); | ||
3474 | } | 3482 | } |
3475 | if (++challenge_count <= sysctl_tcp_challenge_ack_limit) { | 3483 | count = READ_ONCE(challenge_count); |
3484 | if (count > 0) { | ||
3485 | WRITE_ONCE(challenge_count, count - 1); | ||
3476 | NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); | 3486 | NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); |
3477 | tcp_send_ack(sk); | 3487 | tcp_send_ack(sk); |
3478 | } | 3488 | } |