Re: [PATCH net] tcp: ignore locked zero CWND route metric
flat view
From: Eric Dumazet <edumazet@kernel.org>
Date: 2026-10-03 17:09:18
Subsystem:
networking [general], networking [ipv4/ipv6], the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, David Ahern, Ido Schimmel, Linus Torvalds
On 10/3/26 18:10, Eric Dumazet wrote:
On 10/3/26 17:32, bestswngs@gmail.com wrote:quoted
From: Weiming Shi <redacted> A locked RTAX_CWND route metric of zero is copied into the TCP metrics cache and then into snd_cwnd_clamp. This sets the initial cwnd to zero. With a cached SSTHRESH metric, a later Reno ACK can reach a divide by zero in tcp_cong_avoid_ai(). A user with CAP_NET_ADMIN in a user-created network namespace can trigger the oops. Ignore a zero cached CWND metric when applying the locked clamp, leaving the socket's initialized nonzero clamp in place. Oops: divide error: 0000 [#1] SMP KASAN NOPTI RIP: 0010:tcp_cong_avoid_ai (net/ipv4/tcp_cong.c:482) Call Trace: tcp_ack (net/ipv4/tcp_input.c:4440) tcp_rcv_established (net/ipv4/tcp_input.c:6678) tcp_v4_do_rcv (net/ipv4/tcp_ipv4.c:1854) tcp_v4_rcv (net/ipv4/tcp_ipv4.c:2248) Kernel panic - not syncing: Fatal exception in interrupt> Fixes: 51c5d0c4b169 ("tcp: Maintain dynamic metrics in local cache.")> Reported-by: [off-list ref]quoted
Assisted-by: LLM Signed-off-by: Weiming Shi <redacted> --- net/ipv4/tcp_metrics.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index dc0c081fc1f3..ff41804ad086 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c@@ -484,8 +484,11 @@ void tcp_init_metrics(struct sock *sk)goto reset; } - if (tcp_metric_locked(tm, TCP_METRIC_CWND)) - tp->snd_cwnd_clamp = tcp_metric_get(tm, TCP_METRIC_CWND); + if (tcp_metric_locked(tm, TCP_METRIC_CWND)) { + val = tcp_metric_get(tm, TCP_METRIC_CWND);Please explain how we can come to this situation? cwnd can never be zero, so how a save metric could contain zero?
That is to say : The right fix is in ip_metrics_convert(), one time instead of at each TCP session init.
diff --git a/net/ipv4/metrics.c b/net/ipv4/metrics.c
index ad40762a8b38379e4ccdc505e3885adb8dfff763..50a08e592b207e85ccc2bb6f917379de61af4579 100644
--- a/net/ipv4/metrics.c
+++ b/net/ipv4/metrics.c@@ -54,6 +54,10 @@ static int ip_metrics_convert(struct nlattr *fc_mx, NL_SET_ERR_MSG(extack, "Unknown flag set in feature mask in metrics attribute"); return -EINVAL; } + if ((type == RTAX_CWND || type == RTAX_INITCWND) && !val) { + NL_SET_ERR_MSG(extack, "CWND metric must be greater than zero"); + return -EINVAL; + } metrics[type - 1] = val; }
pw-bot: cr