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

dccp: fix undefined behavior with 'cwnd' shift in ccid2_cwnd_restart()

The shift of 'cwnd' with '(now - hc->tx_lsndtime) / hc->tx_rto' value
can lead to undefined behavior [1].

In order to fix this use a gradual shift of the window with a 'while'
loop, similar to what tcp_cwnd_restart() is doing.

When comparing delta and RTO there is a minor difference between TCP
and DCCP, the last one also invokes dccp_cwnd_restart() and reduces
'cwnd' if delta equals RTO. That case is preserved in this change.

[1]:
[40850.963623] UBSAN: Undefined behaviour in net/dccp/ccids/ccid2.c:237:7
[40851.043858] shift exponent 67 is too large for 32-bit type 'unsigned int'
[40851.127163] CPU: 3 PID: 15940 Comm: netstress Tainted: G W E 4.18.0-rc7.x86_64 #1
...
[40851.377176] Call Trace:
[40851.408503] dump_stack+0xf1/0x17b
[40851.451331] ? show_regs_print_info+0x5/0x5
[40851.503555] ubsan_epilogue+0x9/0x7c
[40851.548363] __ubsan_handle_shift_out_of_bounds+0x25b/0x2b4
[40851.617109] ? __ubsan_handle_load_invalid_value+0x18f/0x18f
[40851.686796] ? xfrm4_output_finish+0x80/0x80
[40851.739827] ? lock_downgrade+0x6d0/0x6d0
[40851.789744] ? xfrm4_prepare_output+0x160/0x160
[40851.845912] ? ip_queue_xmit+0x810/0x1db0
[40851.895845] ? ccid2_hc_tx_packet_sent+0xd36/0x10a0 [dccp]
[40851.963530] ccid2_hc_tx_packet_sent+0xd36/0x10a0 [dccp]
[40852.029063] dccp_xmit_packet+0x1d3/0x720 [dccp]
[40852.086254] dccp_write_xmit+0x116/0x1d0 [dccp]
[40852.142412] dccp_sendmsg+0x428/0xb20 [dccp]
[40852.195454] ? inet_dccp_listen+0x200/0x200 [dccp]
[40852.254833] ? sched_clock+0x5/0x10
[40852.298508] ? sched_clock+0x5/0x10
[40852.342194] ? inet_create+0xdf0/0xdf0
[40852.388988] sock_sendmsg+0xd9/0x160
...

Fixes: 113ced1f52e5 ("dccp ccid-2: Perform congestion-window validation")
Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Alexey Kodanev and committed by
David S. Miller
61ef4b07 37436d9c

+4 -2
+4 -2
net/dccp/ccids/ccid2.c
··· 229 229 struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); 230 230 u32 cwnd = hc->tx_cwnd, restart_cwnd, 231 231 iwnd = rfc3390_bytes_to_packets(dccp_sk(sk)->dccps_mss_cache); 232 + s32 delta = now - hc->tx_lsndtime; 232 233 233 234 hc->tx_ssthresh = max(hc->tx_ssthresh, (cwnd >> 1) + (cwnd >> 2)); 234 235 235 236 /* don't reduce cwnd below the initial window (IW) */ 236 237 restart_cwnd = min(cwnd, iwnd); 237 - cwnd >>= (now - hc->tx_lsndtime) / hc->tx_rto; 238 - hc->tx_cwnd = max(cwnd, restart_cwnd); 239 238 239 + while ((delta -= hc->tx_rto) >= 0 && cwnd > restart_cwnd) 240 + cwnd >>= 1; 241 + hc->tx_cwnd = max(cwnd, restart_cwnd); 240 242 hc->tx_cwnd_stamp = now; 241 243 hc->tx_cwnd_used = 0; 242 244