From 8edbf6c23363563e508a61f3f26f4e4b6eec9dd5 Mon Sep 17 00:00:00 2001 From: Jiayuan Chen Date: Thu, 8 Oct 2026 17:26:34 +0800 Subject: [PATCH 1/3] tcp_bic: fix divide by zero on max_increment == 0 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 Signed-off-by: Jiayuan Chen Reviewed-by: Eric Dumazet Link: https://patch.msgid.link/20261008092641.140777-2-jiayuan.chen@linux.dev Signed-off-by: Paolo Abeni --- 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 65444ff14241..27d2e38ff793 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)"); From f09eb97322b16a6f709a47599c95b62f786905f9 Mon Sep 17 00:00:00 2001 From: Jiayuan Chen Date: Thu, 8 Oct 2026 17:26:35 +0800 Subject: [PATCH 2/3] tcp_hybla: fix divide by zero on rtt0 == 0 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 Signed-off-by: Jiayuan Chen Reviewed-by: Eric Dumazet Link: https://patch.msgid.link/20261008092641.140777-3-jiayuan.chen@linux.dev Signed-off-by: Paolo Abeni --- 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 abd7d91807e5..b9b482180d30 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 */ From 7d52b5d16afc1cf8484ae321658e217a80e3ff4d Mon Sep 17 00:00:00 2001 From: Jiayuan Chen Date: Thu, 8 Oct 2026 17:26:36 +0800 Subject: [PATCH 3/3] tcp_cubic: fix divide by zero and endless loop on bad module params beta_scale and cube_factor are computed once at module init, and beta == 1024 or bic_scale == 0 is a divide by zero right there. Other out of range values give garbage: negative beta can make beta_scale 0, and bic_scale * 10 can overflow. Reject them. Read beta once, as it can be written through sysfs before the init function runs. A small beta also gives a small beta_scale, and (cwnd * beta_scale) >> 3 truncates to 0 for a tiny cwnd, so the TCP friendliness loop never ends. Rather than testing delta on every ACK, make sure beta_scale is at least 8 at init, so delta is >= 1 within the cwnd < 1 million packets limit this code is designed for. This slows the TCP friendly estimate for beta < 512, a backoff harder than Reno's 0.5, which is not a setting anyone should use. Fixes: df3271f3361b ("[TCP] BIC: CUBIC window growth (2.0)") Suggested-by: Eric Dumazet Reviewed-by: Eric Dumazet Signed-off-by: Jiayuan Chen Link: https://patch.msgid.link/20261008092641.140777-4-jiayuan.chen@linux.dev Signed-off-by: Paolo Abeni --- net/ipv4/tcp_cubic.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index 119bf8cbb007..a88e4bf86150 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c @@ -500,16 +500,26 @@ static const struct btf_kfunc_id_set tcp_cubic_kfunc_set = { static int __init cubictcp_register(void) { + int b = READ_ONCE(beta); int ret; BUILD_BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE); + if (b < 0 || b >= BICTCP_BETA_SCALE || + bic_scale <= 0 || bic_scale > INT_MAX / 10) { + pr_err("tcp_cubic: invalid beta %d or bic_scale %d\n", + b, 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); + beta_scale = 8 * (BICTCP_BETA_SCALE + b) / 3 + / (BICTCP_BETA_SCALE - b); + /* bictcp_update() needs (cwnd * beta_scale) >> 3 to be >= 1 */ + beta_scale = max(beta_scale, 8U); cube_rtt_scale = (bic_scale * 10); /* 1024*c/rtt */