From: Jiayuan Chen <jiayuan.chen@linux.dev>
To: netdev@vger.kernel.org
Cc: Jiayuan Chen <jiayuan.chen@linux.dev>,
stable@vger.kernel.org, "David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@kernel.org>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Simon Horman <horms@kernel.org>, Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
Randy Dunlap <rdunlap@infradead.org>,
Neal Cardwell <ncardwell@google.com>,
Kuniyuki Iwashima <kuniyu@google.com>,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH net v2 2/2] tcp: fix shift-out-of-bounds in inet_csk_rto_backoff()
Date: Mon, 26 Oct 2026 20:32:39 +0800 [thread overview]
Message-ID: <20261026123244.239766-2-jiayuan.chen@linux.dev> (raw)
In-Reply-To: <20261026123244.239766-1-jiayuan.chen@linux.dev>
icsk_backoff is incremented by tcp_retransmit_timer() on every backed-off
RTO with no cap of its own, and by tcp_send_probe0() up to tcp_retries2.
It is used as a shift amount in inet_csk_rto_backoff():
u64 when = (u64)icsk->icsk_rto << icsk->icsk_backoff;
Once it climbs past 63 the shift is UB. Seen with tcp_retries2=255 and a
silent peer, when an ICMP host unreachable goes through
tcp_ld_RTO_revert():
UBSAN: shift-out-of-bounds in ./include/net/inet_connection_sock.h:258:40
shift exponent 73 is too large for 64-bit type 'long long unsigned int'
Call Trace:
<IRQ>
dump_stack_lvl+0xc1/0xf0
dump_stack+0x10/0x20
__ubsan_handle_shift_out_of_bounds+0x1d1/0x390
tcp_ld_RTO_revert.cold+0x16/0x92
tcp_v4_err+0xdb3/0x13e0
icmp_socket_deliver+0x1a7/0x390
icmp_unreach+0x2dd/0xe50
icmp_rcv+0x93e/0xe30
ip_protocol_deliver_rcu+0x36b/0x3e0
ip_local_deliver_finish+0x37d/0x620
ip_local_deliver+0x165/0x1d0
ip_rcv+0x284/0x320
__netif_receive_skb_one_core+0x16b/0x1c0
__netif_receive_skb+0x21/0x150
process_backlog+0x37e/0x1200
__napi_poll.constprop.0+0xa5/0x5e0
net_rx_action+0x4c0/0xf70
handle_softirqs+0x204/0x9b0
__irq_exit_rcu+0x13c/0x220
irq_exit_rcu+0xe/0x20
sysvec_apic_timer_interrupt+0x92/0xd0
</IRQ>
The orphan check in tcp_probe_timer() calls the same helper. On x86-64
the oversized shift count is taken modulo 64, so an orphan that should
be dead can be seen as alive, and tcp_ld_RTO_revert() can end up with a
smaller RTO than intended.
Cap the shift at 32: any non-zero icsk_rto << 32 exceeds TCP_RTO_MAX, so
the min_t() result is what the unbounded math would give. The
ilog2(TCP_RTO_MAX / TCP_RTO_MIN) + 1 bound of tcp_probe0_when() does not
fit here, as icsk_rto has no TCP_RTO_MIN floor the way tcp_probe0_base()
has.
Fixes: fcdd1cf4dd63 ("tcp: avoid possible arithmetic overflows")
Cc: stable@vger.kernel.org
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
include/net/inet_connection_sock.h | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 903499581db7..562e12033a5d 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -255,9 +255,10 @@ static inline unsigned long
inet_csk_rto_backoff(const struct inet_connection_sock *icsk,
unsigned long max_when)
{
- u64 when = (u64)icsk->icsk_rto << icsk->icsk_backoff;
+ u8 backoff = min_t(u8, 32U, icsk->icsk_backoff);
+ u64 when = (u64)icsk->icsk_rto << backoff;
- return (unsigned long)min_t(u64, when, max_when);
+ return (unsigned long)min_t(u64, when, max_when);
}
struct sock *inet_csk_accept(struct sock *sk, struct proto_accept_arg *arg);
--
2.43.0
next prev parent reply other threads:[~2026-10-26 12:33 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-26 12:32 [PATCH net v2 1/2] tcp: fix shift-out-of-bounds in SYN-ACK retransmit timers Jiayuan Chen
2026-10-26 12:32 ` Jiayuan Chen [this message]
2026-10-26 13:36 ` [PATCH net v2 2/2] tcp: fix shift-out-of-bounds in inet_csk_rto_backoff() Neal Cardwell
2026-10-26 13:27 ` [PATCH net v2 1/2] tcp: fix shift-out-of-bounds in SYN-ACK retransmit timers Neal Cardwell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261026123244.239766-2-jiayuan.chen@linux.dev \
--to=jiayuan.chen@linux.dev \
--cc=corbet@lwn.net \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ncardwell@google.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=rdunlap@infradead.org \
--cc=skhan@linuxfoundation.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®