linux/net/ipv4
Yuchung Cheng 8b8a321ff7 tcp: fix zero cwnd in tcp_cwnd_reduction
Patch 3759824da8 ("tcp: PRR uses CRB mode by default and SS mode
conditionally") introduced a bug that cwnd may become 0 when both
inflight and sndcnt are 0 (cwnd = inflight + sndcnt). This may lead
to a div-by-zero if the connection starts another cwnd reduction
phase by setting tp->prior_cwnd to the current cwnd (0) in
tcp_init_cwnd_reduction().

To prevent this we skip PRR operation when nothing is acked or
sacked. Then cwnd must be positive in all cases as long as ssthresh
is positive:

1) The proportional reduction mode
   inflight > ssthresh > 0

2) The reduction bound mode
  a) inflight == ssthresh > 0

  b) inflight < ssthresh
     sndcnt > 0 since newly_acked_sacked > 0 and inflight < ssthresh

Therefore in all cases inflight and sndcnt can not both be 0.
We check invalid tp->prior_cwnd to avoid potential div0 bugs.

In reality this bug is triggered only with a sequence of less common
events.  For example, the connection is terminating an ECN-triggered
cwnd reduction with an inflight 0, then it receives reordered/old
ACKs or DSACKs from prior transmission (which acks nothing). Or the
connection is in fast recovery stage that marks everything lost,
but fails to retransmit due to local issues, then receives data
packets from other end which acks nothing.

Fixes: 3759824da8 ("tcp: PRR uses CRB mode by default and SS mode conditionally")
Reported-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Signed-off-by: Yuchung Cheng <ycheng@google.com>
Signed-off-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-01-06 16:39:56 -05:00
..
netfilter netfilter: nf_dup: add missing dependencies with NF_CONNTRACK 2015-12-10 18:17:06 +01:00
Kconfig geneve: Consolidate Geneve functionality in single module. 2015-08-27 15:42:48 -07:00
Makefile tcp: track the packet timings in RACK 2015-10-21 07:00:48 -07:00
af_inet.c net: add validation for the socket syscall protocol argument 2015-12-14 16:09:30 -05:00
ah4.c ah4: Fix error return in ah_input(). 2015-08-25 13:38:50 -07:00
arp.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2015-10-20 06:08:27 -07:00
cipso_ipv4.c ipv4: coding style: comparison for inequality with NULL 2015-04-03 12:11:15 -04:00
datagram.c net: Set sk_txhash from a random number 2015-07-29 22:44:04 -07:00
devinet.c netlink: Rightsize IFLA_AF_SPEC size calculation 2015-10-21 19:15:20 -07:00
esp4.c esp4: Switch to new AEAD interface 2015-05-28 11:23:20 +08:00
fib_frontend.c net: Flush local routes when device changes vrf association 2015-12-13 23:58:44 -05:00
fib_lookup.h ipv4: consider TOS in fib_select_default 2015-07-24 22:46:11 -07:00
fib_rules.c net: ipv6: use common fib_default_rule_pref 2015-09-09 14:19:50 -07:00
fib_semantics.c net: Fix prefsrc lookups 2015-11-04 21:34:37 -05:00
fib_trie.c fib_trie: leaf_walk_rcu should not compute key if key is less than pn->key 2015-10-27 18:14:51 -07:00
fou.c fou: clean up socket with kfree_rcu 2015-12-16 19:03:02 -05:00
gre_demux.c gre: Remove support for sharing GRE protocol hook. 2015-08-10 14:03:54 -07:00
gre_offload.c ipv6: gre: support SIT encapsulation 2015-10-26 22:01:18 -07:00
icmp.c Revert "ipv4/icmp: redirect messages can use the ingress daddr as source" 2015-10-14 06:01:07 -07:00
igmp.c ipv4: igmp: Allow removing groups from a removed interface 2015-12-03 12:07:05 -05:00
inet_connection_sock.c tcp: ensure proper barriers in lockless contexts 2015-11-15 18:36:38 -05:00
inet_diag.c tcp/dccp: install syn_recv requests into ehash table 2015-10-03 04:32:41 -07:00
inet_fragment.c net: fix percpu memory leaks 2015-11-02 22:47:14 -05:00
inet_hashtables.c tcp/dccp: fix hashdance race for passive sessions 2015-10-23 05:42:21 -07:00
inet_lro.c lro: remove dead code 2013-12-29 16:34:25 -05:00
inet_timewait_sock.c tcp/dccp: fix timewait races in timer handling 2015-09-21 16:32:29 -07:00
inetpeer.c net: Add helper function to compare inetpeer addresses 2015-08-28 13:32:36 -07:00
ip_forward.c net: Pass net into dst_output and remove dst_output_okfn 2015-10-08 04:26:54 -07:00
ip_fragment.c net: fix percpu memory leaks 2015-11-02 22:47:14 -05:00
ip_gre.c openvswitch: Fix egress tunnel info. 2015-10-22 19:39:25 -07:00
ip_input.c ipv4: Pass struct net into ip_defrag and ip_check_defrag 2015-10-12 19:44:16 -07:00
ip_options.c ipv4: coding style: comparison for inequality with NULL 2015-04-03 12:11:15 -04:00
ip_output.c ipv4: add defensive check for CHECKSUM_PARTIAL skbs in ip_fragment 2015-11-01 12:01:27 -05:00
ip_sockglue.c ipv4: fix a potential deadlock in mcast getsockopt() path 2015-11-04 21:29:59 -05:00
ip_tunnel.c ip_gre: Add support to collect tunnel metadata. 2015-08-10 14:03:54 -07:00
ip_tunnel_core.c ipv4, ipv6: Pass net into ip_local_out and ip6_local_out 2015-10-08 04:27:02 -07:00
ip_vti.c net: Pass net into dst_output and remove dst_output_okfn 2015-10-08 04:26:54 -07:00
ipcomp.c ipv4: coding style: comparison for equality with NULL 2015-04-03 12:11:15 -04:00
ipconfig.c ipconfig: send Client-identifier in DHCP requests 2015-10-18 19:23:52 -07:00
ipip.c ipip: ioctl: Remove superfluous IP-TTL handling. 2015-12-18 16:07:59 -05:00
ipmr.c net: ipmr, ip6mr: fix vif/tunnel failure race condition 2015-11-24 17:15:56 -05:00
netfilter.c ipv4: Pass struct net into ip_route_me_harder 2015-09-29 20:21:32 +02:00
ping.c ipv6: Nonlocal bind 2015-07-09 21:09:10 -07:00
proc.c net: track success and failure of TCP PMTU probing 2015-07-21 22:36:33 -07:00
protocol.c net: Export inet_offloads and inet6_offloads 2014-09-19 17:15:31 -04:00
raw.c net: Propagate lookup failure in l3mdev_get_saddr to caller 2016-01-04 22:58:30 -05:00
route.c net: Do not drop to make_route if oif is l3mdev 2015-10-08 05:18:47 -07:00
syncookies.c tcp/dccp: fix hashdance race for passive sessions 2015-10-23 05:42:21 -07:00
sysctl_net_ipv4.c ipv4: disable BH when changing ip local port range 2015-11-04 21:29:06 -05:00
tcp.c net: rename SOCK_ASYNC_NOSPACE and SOCK_ASYNC_WAITDATA 2015-12-01 15:45:05 -05:00
tcp_bic.c tcp: add tcp_in_slow_start helper 2015-07-09 14:22:52 -07:00
tcp_cdg.c tcp: do not slow start when cwnd equals ssthresh 2015-07-09 14:22:52 -07:00
tcp_cong.c tcp: remove tcp_ecn_make_synack() socket argument 2015-09-25 13:00:38 -07:00
tcp_cubic.c tcp_cubic: do not set epoch_start in the future 2015-09-17 22:35:07 -07:00
tcp_dctcp.c tcp: allow dctcp alpha to drop to zero 2015-10-23 02:46:52 -07:00
tcp_diag.c tcp: ensure proper barriers in lockless contexts 2015-11-15 18:36:38 -05:00
tcp_fastopen.c tcp/dccp: fix hashdance race for passive sessions 2015-10-23 05:42:21 -07:00
tcp_highspeed.c tcp: add tcp_in_slow_start helper 2015-07-09 14:22:52 -07:00
tcp_htcp.c tcp: add tcp_in_slow_start helper 2015-07-09 14:22:52 -07:00
tcp_hybla.c tcp: do not slow start when cwnd equals ssthresh 2015-07-09 14:22:52 -07:00
tcp_illinois.c tcp: add tcp_in_slow_start helper 2015-07-09 14:22:52 -07:00
tcp_input.c tcp: fix zero cwnd in tcp_cwnd_reduction 2016-01-06 16:39:56 -05:00
tcp_ipv4.c net: fix IP early demux races 2015-12-14 23:52:00 -05:00
tcp_lp.c tcp: remove in_flight parameter from cong_avoid() methods 2014-05-03 19:23:07 -04:00
tcp_memcontrol.c memcg: cleanup static keys decrement 2015-02-12 18:54:10 -08:00
tcp_metrics.c net: Add helper function to compare inetpeer addresses 2015-08-28 13:32:36 -07:00
tcp_minisocks.c tcp: fix req->saved_syn race 2015-11-05 14:36:09 -05:00
tcp_offload.c tcp: reserve tcp_skb_mss() to tcp stack 2015-06-11 16:33:10 -07:00
tcp_output.c tcp: restore fastopen with no data in SYN packet 2015-12-17 15:37:39 -05:00
tcp_probe.c tcp: whitespace fixes 2014-09-01 18:12:45 -07:00
tcp_recovery.c tcp: use RACK to detect losses 2015-10-21 07:00:53 -07:00
tcp_scalable.c tcp: add tcp_in_slow_start helper 2015-07-09 14:22:52 -07:00
tcp_timer.c tcp: fix Fast Open snmp over-counting bug 2015-11-20 10:51:12 -05:00
tcp_vegas.c tcp: add tcp_in_slow_start helper 2015-07-09 14:22:52 -07:00
tcp_vegas.h tcp: prepare CC get_info() access from getsockopt() 2015-04-29 17:10:38 -04:00
tcp_veno.c tcp: add tcp_in_slow_start helper 2015-07-09 14:22:52 -07:00
tcp_westwood.c tcp_westwood: fix tcp_westwood_info() 2015-05-05 19:50:09 -04:00
tcp_yeah.c tcp: stretch ACK fixes prep 2015-01-28 22:18:37 -08:00
tunnel4.c
udp.c net: Propagate lookup failure in l3mdev_get_saddr to caller 2016-01-04 22:58:30 -05:00
udp_diag.c sock_diag: specify info_size per inet protocol 2015-06-15 19:49:22 -07:00
udp_impl.h net: Remove iocb argument from sendmsg and recvmsg 2015-03-02 13:06:31 -05:00
udp_offload.c ipv4: coding style: comparison for inequality with NULL 2015-04-03 12:11:15 -04:00
udp_tunnel.c tunnel: introduce udp_tun_rx_dst() 2015-08-27 15:42:47 -07:00
udplite.c net: Eliminate no_check from protosw 2014-05-23 16:28:53 -04:00
xfrm4_input.c netfilter: Pass net into okfn 2015-09-17 17:18:37 -07:00
xfrm4_mode_beet.c ipv4: ERROR: code indent should use tabs where possible 2013-12-26 13:43:21 -05:00
xfrm4_mode_transport.c
xfrm4_mode_tunnel.c ipv4: hash net ptr into fragmentation bucket selection 2015-03-25 14:07:04 -04:00
xfrm4_output.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2015-10-24 06:54:12 -07:00
xfrm4_policy.c Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec 2015-12-22 16:26:31 -05:00
xfrm4_protocol.c xfrm4: Remove duplicate semicolon 2014-06-30 07:49:47 +02:00
xfrm4_state.c inet: make no_pmtu_disc per namespace and kill ipv4_config 2013-12-18 16:58:20 -05:00
xfrm4_tunnel.c