* [PATCH net-next 1/3] tcp_bic: fix divide by zero on max_increment == 0
2026-09-30 10:09 [PATCH net-next 0/3] tcp: fix a few divide-by-zero in congestion control modules Jiayuan Chen
@ 2026-09-30 10:09 ` Jiayuan Chen
2026-09-30 11:22 ` Eric Dumazet
2026-09-30 10:09 ` [PATCH net-next 2/3] tcp_hybla: fix divide by zero on rtt0 " Jiayuan Chen
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Jiayuan Chen @ 2026-09-30 10:09 UTC (permalink / raw)
To: netdev
Cc: Jiayuan Chen, VEGA, Eric Dumazet, Neal Cardwell,
Kuniyuki Iwashima, David S. Miller, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stephen Hemminger, linux-kernel
max_increment is how many packets cwnd can grow per RTT, so 0 makes
no sense, and bictcp_update() divides by it.
Reject values below 1 when the parameter is written.
Fixes: 83803034f423 ("[TCP]: Add TCP BIC congestion control module.")
Reported-by: VEGA <vega@nebusec.ai>
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
Target net-next since it is not a big problem.
---
net/ipv4/tcp_bic.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c
index 65444ff142413..27d2e38ff7932 100644
--- a/net/ipv4/tcp_bic.c
+++ b/net/ipv4/tcp_bic.c
@@ -27,15 +27,25 @@
*/
static int fast_convergence = 1;
-static int max_increment = 16;
+static unsigned int max_increment = 16;
static int low_window = 14;
static int beta = 819; /* = 819/1024 (BICTCP_BETA_SCALE) */
static int initial_ssthresh;
static int smooth_part = 20;
+static int max_increment_set(const char *val, const struct kernel_param *kp)
+{
+ return param_set_uint_minmax(val, kp, 1, INT_MAX);
+}
+
+static const struct kernel_param_ops max_increment_ops = {
+ .set = max_increment_set,
+ .get = param_get_uint,
+};
+
module_param(fast_convergence, int, 0644);
MODULE_PARM_DESC(fast_convergence, "turn on/off fast convergence");
-module_param(max_increment, int, 0644);
+module_param_cb(max_increment, &max_increment_ops, &max_increment, 0644);
MODULE_PARM_DESC(max_increment, "Limit on increment allowed during binary search");
module_param(low_window, int, 0644);
MODULE_PARM_DESC(low_window, "lower bound on congestion window (for TCP friendliness)");
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH net-next 1/3] tcp_bic: fix divide by zero on max_increment == 0
2026-09-30 10:09 ` [PATCH net-next 1/3] tcp_bic: fix divide by zero on max_increment == 0 Jiayuan Chen
@ 2026-09-30 11:22 ` Eric Dumazet
0 siblings, 0 replies; 9+ messages in thread
From: Eric Dumazet @ 2026-09-30 11:22 UTC (permalink / raw)
To: Jiayuan Chen
Cc: netdev, VEGA, Neal Cardwell, Kuniyuki Iwashima, David S. Miller,
Jakub Kicinski, Paolo Abeni, Simon Horman, Stephen Hemminger,
linux-kernel
On Wed, Sep 30, 2026 at 12:10 PM Jiayuan Chen <jiayuan.chen@linux.dev> wrote:
>
> max_increment is how many packets cwnd can grow per RTT, so 0 makes
> no sense, and bictcp_update() divides by it.
>
> Reject values below 1 when the parameter is written.
>
> Fixes: 83803034f423 ("[TCP]: Add TCP BIC congestion control module.")
> Reported-by: VEGA <vega@nebusec.ai>
> Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Reviewed-by: Eric Dumazet <edumazet@kernel.org>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH net-next 2/3] tcp_hybla: fix divide by zero on rtt0 == 0
2026-09-30 10:09 [PATCH net-next 0/3] tcp: fix a few divide-by-zero in congestion control modules Jiayuan Chen
2026-09-30 10:09 ` [PATCH net-next 1/3] tcp_bic: fix divide by zero on max_increment == 0 Jiayuan Chen
@ 2026-09-30 10:09 ` Jiayuan Chen
2026-09-30 11:23 ` Eric Dumazet
2026-09-30 10:09 ` [PATCH net-next 3/3] tcp_cubic: fix divide by zero and endless loop on bad module params Jiayuan Chen
2026-09-30 10:14 ` [PATCH net-next 0/3] tcp: fix a few divide-by-zero in congestion control modules netdev-bot+sinfo
3 siblings, 1 reply; 9+ messages in thread
From: Jiayuan Chen @ 2026-09-30 10:09 UTC (permalink / raw)
To: netdev
Cc: Jiayuan Chen, VEGA, Eric Dumazet, Neal Cardwell,
Kuniyuki Iwashima, David S. Miller, Jakub Kicinski, Paolo Abeni,
Simon Horman, Stephen Hemminger, linux-kernel
rtt0 is the reference RTT in ms, so 0 makes no sense, and
hybla_recalc_param() divides by it right from hybla_init().
Reject values below 1 when the parameter is written. Also cap it at
U32_MAX / USEC_PER_MSEC, since rtt0 * USEC_PER_MSEC can wrap to 0 on
32-bit. An rtt0 above that (about 71 minutes) makes no sense anyway.
Fixes: 835b3f0c0d7e ("[TCP]: Add TCP Hybla congestion control module.")
Fixes: 740b0f1841f6 ("tcp: switch rtt estimations to usec resolution")
Reported-by: VEGA <vega@nebusec.ai>
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
Target net-next since it is not a big problem.
---
net/ipv4/tcp_hybla.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/tcp_hybla.c b/net/ipv4/tcp_hybla.c
index abd7d91807e54..b9b482180d30b 100644
--- a/net/ipv4/tcp_hybla.c
+++ b/net/ipv4/tcp_hybla.c
@@ -26,8 +26,20 @@ struct hybla {
};
/* Hybla reference round trip time (default= 1/40 sec = 25 ms), in ms */
-static int rtt0 = 25;
-module_param(rtt0, int, 0644);
+static unsigned int rtt0 = 25;
+
+static int rtt0_set(const char *val, const struct kernel_param *kp)
+{
+ /* avoid rtt0 * USEC_PER_MSEC overflow */
+ return param_set_uint_minmax(val, kp, 1, U32_MAX / USEC_PER_MSEC);
+}
+
+static const struct kernel_param_ops rtt0_ops = {
+ .set = rtt0_set,
+ .get = param_get_uint,
+};
+
+module_param_cb(rtt0, &rtt0_ops, &rtt0, 0644);
MODULE_PARM_DESC(rtt0, "reference rout trip time (ms)");
/* This is called to refresh values for hybla parameters */
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH net-next 2/3] tcp_hybla: fix divide by zero on rtt0 == 0
2026-09-30 10:09 ` [PATCH net-next 2/3] tcp_hybla: fix divide by zero on rtt0 " Jiayuan Chen
@ 2026-09-30 11:23 ` Eric Dumazet
0 siblings, 0 replies; 9+ messages in thread
From: Eric Dumazet @ 2026-09-30 11:23 UTC (permalink / raw)
To: Jiayuan Chen
Cc: netdev, VEGA, Neal Cardwell, Kuniyuki Iwashima, David S. Miller,
Jakub Kicinski, Paolo Abeni, Simon Horman, Stephen Hemminger,
linux-kernel
On Wed, Sep 30, 2026 at 12:10 PM Jiayuan Chen <jiayuan.chen@linux.dev> wrote:
>
> rtt0 is the reference RTT in ms, so 0 makes no sense, and
> hybla_recalc_param() divides by it right from hybla_init().
>
> Reject values below 1 when the parameter is written. Also cap it at
> U32_MAX / USEC_PER_MSEC, since rtt0 * USEC_PER_MSEC can wrap to 0 on
> 32-bit. An rtt0 above that (about 71 minutes) makes no sense anyway.
>
> Fixes: 835b3f0c0d7e ("[TCP]: Add TCP Hybla congestion control module.")
> Fixes: 740b0f1841f6 ("tcp: switch rtt estimations to usec resolution")
> Reported-by: VEGA <vega@nebusec.ai>
> Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
> ---
Reviewed-by: Eric Dumazet <edumazet@kernel.org>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH net-next 3/3] tcp_cubic: fix divide by zero and endless loop on bad module params
2026-09-30 10:09 [PATCH net-next 0/3] tcp: fix a few divide-by-zero in congestion control modules Jiayuan Chen
2026-09-30 10:09 ` [PATCH net-next 1/3] tcp_bic: fix divide by zero on max_increment == 0 Jiayuan Chen
2026-09-30 10:09 ` [PATCH net-next 2/3] tcp_hybla: fix divide by zero on rtt0 " Jiayuan Chen
@ 2026-09-30 10:09 ` Jiayuan Chen
2026-09-30 11:21 ` Eric Dumazet
2026-09-30 10:14 ` [PATCH net-next 0/3] tcp: fix a few divide-by-zero in congestion control modules netdev-bot+sinfo
3 siblings, 1 reply; 9+ messages in thread
From: Jiayuan Chen @ 2026-09-30 10:09 UTC (permalink / raw)
To: netdev
Cc: Jiayuan Chen, Eric Dumazet, Neal Cardwell, Kuniyuki Iwashima,
David S. Miller, Jakub Kicinski, Paolo Abeni, Simon Horman,
Stephen Hemminger, linux-kernel
beta_scale and cube_factor are computed once at module init, and they
need 1024 - beta and bic_scale * 10 to be positive: beta == 1024 or
bic_scale == 0 crash right there, beta > 1024 or a negative bic_scale
gives garbage or wraps to 0. Negative beta can also make beta_scale 0.
Reject them.
A small beta also gives a small beta_scale, and (cwnd * scale) >> 3
truncates to 0 for a tiny cwnd (e.g. 2), so the TCP friendliness loop
never ends. Clamp delta to 1.
Fixes: df3271f3361b ("[TCP] BIC: CUBIC window growth (2.0)")
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
Target net-next since it is not a big problem.
---
net/ipv4/tcp_cubic.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index 119bf8cbb007c..2f04dca5be095 100644
--- a/net/ipv4/tcp_cubic.c
+++ b/net/ipv4/tcp_cubic.c
@@ -298,7 +298,7 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd, u32 acked)
if (tcp_friendliness) {
u32 scale = beta_scale;
- delta = (cwnd * scale) >> 3;
+ delta = max((cwnd * scale) >> 3, 1U);
while (ca->ack_cnt > delta) { /* update tcp cwnd */
ca->ack_cnt -= delta;
ca->tcp_cwnd++;
@@ -504,6 +504,11 @@ static int __init cubictcp_register(void)
BUILD_BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE);
+ if (beta < 0 || beta >= BICTCP_BETA_SCALE || bic_scale <= 0) {
+ pr_err("tcp_cubic: invalid beta %d or bic_scale %d\n", beta, bic_scale);
+ return -EINVAL;
+ }
+
/* Precompute a bunch of the scaling factors that are used per-packet
* based on SRTT of 100ms
*/
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH net-next 3/3] tcp_cubic: fix divide by zero and endless loop on bad module params
2026-09-30 10:09 ` [PATCH net-next 3/3] tcp_cubic: fix divide by zero and endless loop on bad module params Jiayuan Chen
@ 2026-09-30 11:21 ` Eric Dumazet
2026-09-30 14:03 ` Jiayuan Chen
0 siblings, 1 reply; 9+ messages in thread
From: Eric Dumazet @ 2026-09-30 11:21 UTC (permalink / raw)
To: Jiayuan Chen
Cc: netdev, Neal Cardwell, Kuniyuki Iwashima, David S. Miller,
Jakub Kicinski, Paolo Abeni, Simon Horman, Stephen Hemminger,
linux-kernel
On Wed, Sep 30, 2026 at 12:10 PM Jiayuan Chen <jiayuan.chen@linux.dev> wrote:
>
> beta_scale and cube_factor are computed once at module init, and they
> need 1024 - beta and bic_scale * 10 to be positive: beta == 1024 or
> bic_scale == 0 crash right there, beta > 1024 or a negative bic_scale
> gives garbage or wraps to 0. Negative beta can also make beta_scale 0.
> Reject them.
>
> A small beta also gives a small beta_scale, and (cwnd * scale) >> 3
> truncates to 0 for a tiny cwnd (e.g. 2), so the TCP friendliness loop
> never ends. Clamp delta to 1.
>
> Fixes: df3271f3361b ("[TCP] BIC: CUBIC window growth (2.0)")
> Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
> ---
> Target net-next since it is not a big problem.
> ---
> net/ipv4/tcp_cubic.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
> index 119bf8cbb007c..2f04dca5be095 100644
> --- a/net/ipv4/tcp_cubic.c
> +++ b/net/ipv4/tcp_cubic.c
> @@ -298,7 +298,7 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd, u32 acked)
> if (tcp_friendliness) {
> u32 scale = beta_scale;
>
> - delta = (cwnd * scale) >> 3;
I would prefer not adding a test in the fast path to work around
silly module parameters.
beta_scale is computed once at module init, we can make sure it is >= 8
there. tcp_snd_cwnd() is >= 1, so delta would be >= 1.
With the integer divisions, beta_scale >= 8 iff beta >= 512,
so the default beta (717 -> beta_scale = 15) is not affected.
> + delta = max((cwnd * scale) >> 3, 1U);
> while (ca->ack_cnt > delta) { /* update tcp cwnd */
> ca->ack_cnt -= delta;
> ca->tcp_cwnd++;
> @@ -504,6 +504,11 @@ static int __init cubictcp_register(void)
>
> BUILD_BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE);
>
> + if (beta < 0 || beta >= BICTCP_BETA_SCALE || bic_scale <= 0) {
bic_scale * 10 can overflow if bic_scale > INT_MAX / 10
> + pr_err("tcp_cubic: invalid beta %d or bic_scale %d\n", beta, bic_scale);
> + return -EINVAL;
> + }
> +
Something like this (untested) :
if (beta < 0 || beta >= BICTCP_BETA_SCALE ||
bic_scale <= 0 || bic_scale > INT_MAX / 10) {
pr_err("tcp_cubic: invalid beta %d or bic_scale %d\n",
beta, bic_scale);
return -EINVAL;
}
/* Precompute a bunch of the scaling factors that are used per-packet
* based on SRTT of 100ms
*/
beta_scale = 8*(BICTCP_BETA_SCALE+beta) / 3
/ (BICTCP_BETA_SCALE - beta);
/* bictcp_update() needs (cwnd * beta_scale) >> 3 to be >= 1 */
beta_scale = max(beta_scale, 8U);
Thanks.
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH net-next 3/3] tcp_cubic: fix divide by zero and endless loop on bad module params
2026-09-30 11:21 ` Eric Dumazet
@ 2026-09-30 14:03 ` Jiayuan Chen
0 siblings, 0 replies; 9+ messages in thread
From: Jiayuan Chen @ 2026-09-30 14:03 UTC (permalink / raw)
To: Eric Dumazet
Cc: netdev, Neal Cardwell, Kuniyuki Iwashima, David S. Miller,
Jakub Kicinski, Paolo Abeni, Simon Horman, Stephen Hemminger,
linux-kernel
On 9/30/26 7:21 PM, Eric Dumazet wrote:
> On Wed, Sep 30, 2026 at 12:10 PM Jiayuan Chen <jiayuan.chen@linux.dev> wrote:
>> beta_scale and cube_factor are computed once at module init, and they
>> need 1024 - beta and bic_scale * 10 to be positive: beta == 1024 or
>> bic_scale == 0 crash right there, beta > 1024 or a negative bic_scale
>> gives garbage or wraps to 0. Negative beta can also make beta_scale 0.
>> Reject them.
>>
>> A small beta also gives a small beta_scale, and (cwnd * scale) >> 3
>> truncates to 0 for a tiny cwnd (e.g. 2), so the TCP friendliness loop
>> never ends. Clamp delta to 1.
>>
>> Fixes: df3271f3361b ("[TCP] BIC: CUBIC window growth (2.0)")
>> Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
>> ---
>> Target net-next since it is not a big problem.
>> ---
>> net/ipv4/tcp_cubic.c | 7 ++++++-
>> 1 file changed, 6 insertions(+), 1 deletion(-)
>>
>> diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
>> index 119bf8cbb007c..2f04dca5be095 100644
>> --- a/net/ipv4/tcp_cubic.c
>> +++ b/net/ipv4/tcp_cubic.c
>> @@ -298,7 +298,7 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd, u32 acked)
>> if (tcp_friendliness) {
>> u32 scale = beta_scale;
>>
>> - delta = (cwnd * scale) >> 3;
> I would prefer not adding a test in the fast path to work around
> silly module parameters.
>
> beta_scale is computed once at module init, we can make sure it is >= 8
> there. tcp_snd_cwnd() is >= 1, so delta would be >= 1.
Agreed. beta_scale is 8 / alpha_cubic, so >= 8 just caps alpha_cubic
at 1
>
> With the integer divisions, beta_scale >= 8 iff beta >= 512,
> so the default beta (717 -> beta_scale = 15) is not affected.
>
>
>> + delta = max((cwnd * scale) >> 3, 1U);
>> while (ca->ack_cnt > delta) { /* update tcp cwnd */
>> ca->ack_cnt -= delta;
>> ca->tcp_cwnd++;
>> @@ -504,6 +504,11 @@ static int __init cubictcp_register(void)
>>
>> BUILD_BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE);
>>
>> + if (beta < 0 || beta >= BICTCP_BETA_SCALE || bic_scale <= 0) {
> bic_scale * 10 can overflow if bic_scale > INT_MAX / 10
Right, will add it.
>> + pr_err("tcp_cubic: invalid beta %d or bic_scale %d\n", beta, bic_scale);
>> + return -EINVAL;
>> + }
>> +
> Something like this (untested) :
>
> if (beta < 0 || beta >= BICTCP_BETA_SCALE ||
> bic_scale <= 0 || bic_scale > INT_MAX / 10) {
> pr_err("tcp_cubic: invalid beta %d or bic_scale %d\n",
> beta, bic_scale);
> return -EINVAL;
> }
> /* Precompute a bunch of the scaling factors that are used per-packet
> * based on SRTT of 100ms
> */
> beta_scale = 8*(BICTCP_BETA_SCALE+beta) / 3
> / (BICTCP_BETA_SCALE - beta);
> /* bictcp_update() needs (cwnd * beta_scale) >> 3 to be >= 1 */
> beta_scale = max(beta_scale, 8U);
>
> Thanks.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net-next 0/3] tcp: fix a few divide-by-zero in congestion control modules
2026-09-30 10:09 [PATCH net-next 0/3] tcp: fix a few divide-by-zero in congestion control modules Jiayuan Chen
` (2 preceding siblings ...)
2026-09-30 10:09 ` [PATCH net-next 3/3] tcp_cubic: fix divide by zero and endless loop on bad module params Jiayuan Chen
@ 2026-09-30 10:14 ` netdev-bot+sinfo
3 siblings, 0 replies; 9+ messages in thread
From: netdev-bot+sinfo @ 2026-09-30 10:14 UTC (permalink / raw)
To: Jiayuan Chen
Cc: netdev, Eric Dumazet, Neal Cardwell, Kuniyuki Iwashima,
David S. Miller, Jakub Kicinski, Paolo Abeni, Simon Horman,
Stephen Hemminger, linux-kernel
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- Whether the issue was actually triggered, or is only theoretical
(e.g. found by code inspection). If it was triggered please include
the symptoms, like the stack trace or error messages.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 9+ messages in thread