* [PATCH net v3 1/1] tcp: bound SYN-ACK timers to reqsk timeout range
@ 2026-07-02 9:52 Ren Wei
2026-07-09 10:13 ` Paolo Abeni
0 siblings, 1 reply; 2+ messages in thread
From: Ren Wei @ 2026-07-02 9:52 UTC (permalink / raw)
To: netdev
Cc: edumazet, ncardwell, kuniyu, davem, pabeni, horms, chia-yu.chang,
ij, idosch, fmancera, bronzed_45_vested, yuuchihsu, yuantan098,
yifanwucs, tomapufckgml, bird, roxy520tt, n05ec
From: Zhiling Zou <roxy520tt@gmail.com>
tcp_synack_retries supplies the SYN-ACK retry limit used by request
socket timers. The same effective limit can also come from TCP_SYNCNT
through icsk_syn_retries, while TCP_DEFER_ACCEPT can keep an ACKed
request alive until rskq_defer_accept is reached.
The request socket timeout counter is incremented before it is used to
compute the next timeout. tcp_reqsk_timeout() and the Fast Open SYN-ACK
timer shift req->timeout by req->num_timeout. Excessive retry or
defer-accept limits can therefore drive these timer paths into invalid
shift counts before the request expires.
Limit tcp_synack_retries to the request socket timer range, clamp the
effective retry and defer-accept limits in the regular request socket
timer path, clamp the Fast Open retry limit, and make the request
socket timeout helper saturate before shifting.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:gpt-5.4
Signed-off-by: Zhiling Zou <roxy520tt@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
---
Changes in v3:
- Order local variables in tcp_reqsk_timeout_sk() by reverse Christmas tree.
- v2 Link: https://lore.kernel.org/all/20260630035009.55201-1-n05ec@lzu.edu.cn/
Changes in v2:
- Keep the existing max_retries calculation in tcp_fastopen_synack_timer()
and only add the clamp, avoiding code churn.
- v1 Link: https://lore.kernel.org/all/02e24eb83639e9d7ecc623f000c60254bb5c40a5.1782643946.git.roxy520tt@gmail.com/
include/net/tcp.h | 19 +++++++++++++++----
net/ipv4/inet_connection_sock.c | 6 +++++-
net/ipv4/sysctl_net_ipv4.c | 2 ++
net/ipv4/tcp_timer.c | 3 ++-
4 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 6d376ea4d1c0..ee78436b8964 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -183,6 +183,7 @@ static_assert((1 << ATO_BITS) > TCP_DELACK_MAX);
#define MAX_TCP_KEEPINTVL 32767
#define MAX_TCP_KEEPCNT 127
#define MAX_TCP_SYNCNT 127
+#define MAX_TCP_SYNACK_RETRIES 63
/* Ensure that TCP PAWS checks are relaxed after ~2147 seconds
* to avoid overflows. This assumes a clock smaller than 1 Mhz.
@@ -882,12 +883,22 @@ static inline u32 __tcp_set_rto(const struct tcp_sock *tp)
return usecs_to_jiffies((tp->srtt_us >> 3) + tp->rttvar_us);
}
-static inline unsigned long tcp_reqsk_timeout(struct request_sock *req)
+static inline unsigned long tcp_reqsk_timeout_sk(const struct sock *sk,
+ struct request_sock *req)
{
- u64 timeout = (u64)req->timeout << req->num_timeout;
+ u32 rto_max = tcp_rto_max(sk);
+ u64 timeout = req->timeout;
+
+ if (req->num_timeout >= BITS_PER_TYPE(u64) ||
+ timeout > U64_MAX >> req->num_timeout)
+ return rto_max;
+
+ return (unsigned long)min_t(u64, timeout << req->num_timeout, rto_max);
+}
- return (unsigned long)min_t(u64, timeout,
- tcp_rto_max(req->rsk_listener));
+static inline unsigned long tcp_reqsk_timeout(struct request_sock *req)
+{
+ return tcp_reqsk_timeout_sk(req->rsk_listener, req);
}
u32 tcp_delack_max(const struct sock *sk);
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 56902bba5483..b74212bae3dd 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -1056,6 +1056,8 @@ static void reqsk_timer_handler(struct timer_list *t)
net = sock_net(sk_listener);
max_syn_ack_retries = READ_ONCE(icsk->icsk_syn_retries) ? :
READ_ONCE(net->ipv4.sysctl_tcp_synack_retries);
+ max_syn_ack_retries = min_t(int, max_syn_ack_retries,
+ MAX_TCP_SYNACK_RETRIES);
/* Normally all the openreqs are young and become mature
* (i.e. converted to established socket) for first timeout.
* If synack was not acknowledged for 1 second, it means
@@ -1086,7 +1088,9 @@ static void reqsk_timer_handler(struct timer_list *t)
}
}
- syn_ack_recalc(req, max_syn_ack_retries, READ_ONCE(queue->rskq_defer_accept),
+ syn_ack_recalc(req, max_syn_ack_retries,
+ min_t(u8, READ_ONCE(queue->rskq_defer_accept),
+ MAX_TCP_SYNACK_RETRIES),
&expire, &resend);
tcp_syn_ack_timeout(req);
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index ca1180dba1de..f9d233b98bbc 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -35,6 +35,7 @@ static int ip_ttl_min = 1;
static int ip_ttl_max = 255;
static int tcp_syn_retries_min = 1;
static int tcp_syn_retries_max = MAX_TCP_SYNCNT;
+static int tcp_synack_retries_max = MAX_TCP_SYNACK_RETRIES;
static int tcp_syn_linear_timeouts_max = MAX_TCP_SYNCNT;
static unsigned long ip_ping_group_range_min[] = { 0, 0 };
static unsigned long ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX };
@@ -1034,6 +1035,7 @@ static struct ctl_table ipv4_net_table[] = {
.maxlen = sizeof(u8),
.mode = 0644,
.proc_handler = proc_dou8vec_minmax,
+ .extra2 = &tcp_synack_retries_max
},
#ifdef CONFIG_SYN_COOKIES
{
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index bf171b5e1eb3..bbedf2b9e1bc 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -467,6 +467,7 @@ static void tcp_fastopen_synack_timer(struct sock *sk, struct request_sock *req)
*/
max_retries = READ_ONCE(icsk->icsk_syn_retries) ? :
READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_synack_retries) + 1;
+ max_retries = min_t(int, max_retries, MAX_TCP_SYNACK_RETRIES);
if (req->num_timeout >= max_retries) {
tcp_write_err(sk);
@@ -488,7 +489,7 @@ static void tcp_fastopen_synack_timer(struct sock *sk, struct request_sock *req)
if (!tp->retrans_stamp)
tp->retrans_stamp = tcp_time_stamp_ts(tp);
tcp_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
- req->timeout << req->num_timeout, false);
+ tcp_reqsk_timeout_sk(sk, req), false);
}
static bool tcp_rtx_probe0_timed_out(const struct sock *sk,
--
2.43.0
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH net v3 1/1] tcp: bound SYN-ACK timers to reqsk timeout range
2026-07-02 9:52 [PATCH net v3 1/1] tcp: bound SYN-ACK timers to reqsk timeout range Ren Wei
@ 2026-07-09 10:13 ` Paolo Abeni
0 siblings, 0 replies; 2+ messages in thread
From: Paolo Abeni @ 2026-07-09 10:13 UTC (permalink / raw)
To: Ren Wei, netdev
Cc: edumazet, ncardwell, kuniyu, davem, horms, chia-yu.chang, ij,
idosch, fmancera, bronzed_45_vested, yuuchihsu, yuantan098,
yifanwucs, tomapufckgml, bird, roxy520tt
On 7/2/26 11:52 AM, Ren Wei wrote:
> @@ -1034,6 +1035,7 @@ static struct ctl_table ipv4_net_table[] = {
> .maxlen = sizeof(u8),
> .mode = 0644,
> .proc_handler = proc_dou8vec_minmax,
> + .extra2 = &tcp_synack_retries_max
This new restriction, even if correct, may break existing scripts.
Since the rest of the patch enforces the upper bound at every
sysctl_tcp_synack_retries usage, what about dropping this chunk?
/P
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-07-09 10:13 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-02 9:52 [PATCH net v3 1/1] tcp: bound SYN-ACK timers to reqsk timeout range Ren Wei
2026-07-09 10:13 ` Paolo Abeni
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox