* [PATCH net v3 0/9] net/sched: clamp quantum/psched_mtu in change paths
@ 2026-09-01 21:39 Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 1/9] net/sched: fq: clamp quantum and initial_quantum in change path Jamal Hadi Salim
` (8 more replies)
0 siblings, 9 replies; 16+ messages in thread
From: Jamal Hadi Salim @ 2026-09-01 21:39 UTC (permalink / raw)
To: netdev
Cc: Jamal Hadi Salim, Jiri Pirko, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Victor Nogueira, Vega,
stable, Toke Høiland-Jørgensen, Chia-Yu Chang,
Vijay Subramanian, Petr Machata
This is a followup to commit 709f34f7c28d ("net/sched: fq: add overflow
bounds to quantum and initial quantum").
The quantum_backlog_overflow series and the five siblings that followed
clamped the init-path quantum in fq, fq_codel, fq_pie, hhf, sfq. The
change() paths were not clamped but it is the same pattern, same writer
of q->quantum, same privilege level (CAP_NET_ADMIN in a user namespace).
A user can override the init clamp via tc qdisc change, restoring the
small-quantum deficit spin that the init clamp was meant to prevent.
This series also covers two siblings that were missed entirely by the
original series: sch_dualpi2 and sch_pie call psched_mtu() without any
clamp at all. With a crafted size table qdisc_pkt_len reaches ~2 GiB,
so quantum=1 (or a zero psched_mtu on a headerless device) makes the
deficit-refill loop spin ~2^31 times under the qdisc lock (a soft
lockup / denial of service).
Each patch fixes one qdisc with its own Fixes: tag so they can be
backported independently - the commits they fix shift differently in
the git tree.
Patch 1: fq - clamp TCA_FQ_QUANTUM and TCA_FQ_INITIAL_QUANTUM in change
Patch 2: fq_pie - clamp quantum in change path
Patch 3: sfq - clamp quantum and reject > 1<<20 in change path
Patch 4: hhf - clamp quantum in change and init paths
Patch 5: dualpi2 - clamp psched_mtu at all 3 call sites
Patch 6: pie - clamp psched_mtu in pie_drop_early
Patch 7: drr - clamp quantum in change class
Patch 8: ets - clamp quantum in parse and fallback paths
Patch 9: selftests - update ETS test 41f5 for clamped quanta
Conditions to recreate (applies to all): create the qdisc, then
tc qdisc change ... quantum 1 with a STAB size table inflating
qdisc_pkt_len. Requires CAP_NET_ADMIN in a user namespace (unshare -Urn).
Sashiko links:
- v1: https://sashiko.dev/#/patchset/20260826074056.7873-1-jhs@mojatatu.com
- v2: https://sashiko.dev/#/patchset/20260829081229.81708-1-jhs@mojatatu.com
v2 -> v3:
- Add patch 9/9: update tdc case 41f5 (ETS offload quanta wrap test) -
the [256, 1<<20] clamp in ets_quantum_parse() rejects/normalises the
wrapping quanta 41f5 asserts verbatim, so the tc executor run failed
(Jakub). 41f5 now matches the clamped values (quanta 1048576 256 256)
and its name reflects the new behavior.
- No kernel-code changes; patches 1-8 are identical to v2.
v1 -> v2:
- Split the single monolithic patch into 8 per-qdisc patches, each with
its own Fixes: tag, so stable backports can cherry-pick individually.
- Add cover letter.
- ETS: move 256 floor into ets_quantum_parse() so explicit quanta are
clamped, not just the fallback path (Sashiko gemini + nipa gpt-5-6-sol-1-7).
- DRR: add upper bound clamp_t(u32, quantum, 256, 1<<20) matching sfq
(Sashiko nipa gpt-5-6-sol-3-19).
- ETS: add upper bound clamp in ets_quantum_parse() and fallback path.
- sch_fq: add 256 floor in fq_change() for TCA_FQ_QUANTUM and clamp
fq_init() quantum to [256, 1<<20] for tiny-MTU devices
(Sashiko gemini + nipa main-1-1).
- hhf: clamp hhf_init() to [256, 1<<20] matching siblings
(Sashiko gemini + nipa gpt-5-6-sol-6-24).
- Add Fixes: dcc68b4d8084 for ETS (Sashiko nipa gpt-5-6-sol-1-8).
- Re-add Toke's Reviewed-by from v1 (kept since v2 only splits the patch,
the code Toke reviewed is unchanged in approach).
Jamal Hadi Salim (9):
net/sched: fq: clamp quantum and initial_quantum in change path
net/sched: fq_pie: clamp quantum in change path
net/sched: sfq: clamp quantum in change path
net/sched: hhf: clamp quantum in change and init paths
net/sched: dualpi2: clamp psched_mtu at all call sites
net/sched: pie: clamp psched_mtu in pie_drop_early
net/sched: drr: clamp quantum in change class
net/sched: ets: clamp quantum in parse and fallback paths
selftests: tc-testing: update ETS test 41f5 for clamped quanta
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH net v3 1/9] net/sched: fq: clamp quantum and initial_quantum in change path
2026-09-01 21:39 [PATCH net v3 0/9] net/sched: clamp quantum/psched_mtu in change paths Jamal Hadi Salim
@ 2026-09-01 21:39 ` Jamal Hadi Salim
2026-09-01 23:52 ` Eric Dumazet
2026-09-01 21:39 ` [PATCH net v3 2/9] net/sched: fq_pie: clamp quantum " Jamal Hadi Salim
` (7 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Jamal Hadi Salim @ 2026-09-01 21:39 UTC (permalink / raw)
To: netdev
Cc: Jamal Hadi Salim, Jiri Pirko, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Victor Nogueira, Vega,
stable, Toke Høiland-Jørgensen, Vijay Subramanian,
Petr Machata, Chia-Yu Chang
The fq change path accepts TCA_FQ_QUANTUM in [1, INT_MAX] and
TCA_FQ_INITIAL_QUANTUM up to INT_MAX, while fq_init() already clamps to
[1, 1<<20]. A user can override the init clamp via tc qdisc change,
restoring the small-quantum deficit spin that the init clamp prevents.
Narrow iq_range.max to 1<<20 so TCA_FQ_INITIAL_QUANTUM is rejected at
parse time. Clamp TCA_FQ_QUANTUM to [256, 1<<20] in fq_change() and
fq_init() quantum to [256, 1<<20] for tiny-MTU devices.
Conditions to recreate the bug:
CONFIG_NET_SCH_FQ=y. Requires CAP_NET_ADMIN (namespace-local via
unshare -Urn suffices).
tc qdisc add dev dummy0 root fq
tc qdisc change dev dummy0 root fq quantum 1 stab data 32768 size_log 15 cell_log 0
Fixes: 709f34f7c28d ("net/sched: fq: add overflow bounds to quantum and initial quantum")
Reported-by: Vega <vega@nebusec.ai>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
net/sched/sch_fq.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index 6144b5686f13..35f940b2205d 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -980,7 +980,7 @@ static int fq_resize(struct Qdisc *sch, u32 log)
}
static const struct netlink_range_validation iq_range = {
- .max = INT_MAX,
+ .max = 1 << 20,
};
static const struct nla_policy fq_policy[TCA_FQ_MAX + 1] = {
@@ -1106,14 +1106,10 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt,
nla_get_u32(tb[TCA_FQ_FLOW_PLIMIT]));
if (tb[TCA_FQ_QUANTUM]) {
- u32 quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]);
+ u32 quantum = clamp_t(u32, nla_get_u32(tb[TCA_FQ_QUANTUM]),
+ 256, 1 << 20);
- if (quantum > 0 && quantum <= (1 << 20)) {
- WRITE_ONCE(q->quantum, quantum);
- } else {
- NL_SET_ERR_MSG_MOD(extack, "invalid quantum");
- err = -EINVAL;
- }
+ WRITE_ONCE(q->quantum, quantum);
}
if (tb[TCA_FQ_INITIAL_QUANTUM])
@@ -1232,7 +1228,7 @@ static int fq_init(struct Qdisc *sch, struct nlattr *opt,
sch->limit = 10000;
q->flow_plimit = 100;
mtu = clamp_t(u32, psched_mtu(qdisc_dev(sch)), 1, 1 << 20);
- q->quantum = min_t(u32, 2 * mtu, 1 << 20);
+ q->quantum = clamp_t(u32, 2 * mtu, 256, 1 << 20);
q->initial_quantum = min_t(u32, 10 * mtu, 1 << 20);
q->flow_refill_delay = msecs_to_jiffies(40);
q->flow_max_rate = ~0UL;
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH net v3 2/9] net/sched: fq_pie: clamp quantum in change path
2026-09-01 21:39 [PATCH net v3 0/9] net/sched: clamp quantum/psched_mtu in change paths Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 1/9] net/sched: fq: clamp quantum and initial_quantum in change path Jamal Hadi Salim
@ 2026-09-01 21:39 ` Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 3/9] net/sched: sfq: " Jamal Hadi Salim
` (6 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Jamal Hadi Salim @ 2026-09-01 21:39 UTC (permalink / raw)
To: netdev
Cc: Jamal Hadi Salim, Jiri Pirko, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Victor Nogueira, Vega,
stable, Toke Høiland-Jørgensen, Vijay Subramanian,
Petr Machata, Chia-Yu Chang
fq_pie_change() accepts any quantum value from userspace, including 1.
With a crafted size table qdisc_pkt_len reaches ~2 GiB, so quantum=1
makes the deficit-refill loop spin ~2^31 times under the qdisc lock
(a soft lockup / denial of service).
Add max(256U, ...) matching fq_codel_change().
Conditions to recreate the bug:
CONFIG_NET_SCH_FQ_PIE=y. Requires CAP_NET_ADMIN (namespace-local via
unshare -Urn suffices).
tc qdisc add dev dummy0 root fq_pie
tc qdisc change dev dummy0 root fq_pie quantum 1 stab data 32768 size_log 15 cell_log 0
Fixes: ec97ecf1ebe4 ("net: sched: add Flow Queue PIE packet scheduler")
Reported-by: Vega <vega@nebusec.ai>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
net/sched/sch_fq_pie.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/sched/sch_fq_pie.c b/net/sched/sch_fq_pie.c
index b27d95418707..5982847df8f8 100644
--- a/net/sched/sch_fq_pie.c
+++ b/net/sched/sch_fq_pie.c
@@ -341,7 +341,8 @@ static int fq_pie_change(struct Qdisc *sch, struct nlattr *opt,
nla_get_u32(tb[TCA_FQ_PIE_BETA]));
if (tb[TCA_FQ_PIE_QUANTUM])
- WRITE_ONCE(q->quantum, nla_get_u32(tb[TCA_FQ_PIE_QUANTUM]));
+ WRITE_ONCE(q->quantum,
+ max(256U, nla_get_u32(tb[TCA_FQ_PIE_QUANTUM])));
if (tb[TCA_FQ_PIE_MEMORY_LIMIT])
WRITE_ONCE(q->memory_limit,
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH net v3 3/9] net/sched: sfq: clamp quantum in change path
2026-09-01 21:39 [PATCH net v3 0/9] net/sched: clamp quantum/psched_mtu in change paths Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 1/9] net/sched: fq: clamp quantum and initial_quantum in change path Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 2/9] net/sched: fq_pie: clamp quantum " Jamal Hadi Salim
@ 2026-09-01 21:39 ` Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 4/9] net/sched: hhf: clamp quantum in change and init paths Jamal Hadi Salim
` (5 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Jamal Hadi Salim @ 2026-09-01 21:39 UTC (permalink / raw)
To: netdev
Cc: Jamal Hadi Salim, Jiri Pirko, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Victor Nogueira, Vega,
stable, Toke Høiland-Jørgensen, Vijay Subramanian,
Petr Machata, Chia-Yu Chang
sfq_change() accepts any non-negative quantum (only rejects
(int)ctl->quantum < 0). With a crafted size table qdisc_pkt_len reaches
~2 GiB, so quantum=1 makes the deficit-refill loop spin ~2^31 times
under the qdisc lock (a soft lockup / denial of service).
Add max(256U, ...) matching fq_codel_change(). Reject quantum > 1<<20
with -EINVAL, matching fq_codel_change() and the init clamp.
Conditions to recreate the bug:
CONFIG_NET_SCH_SFQ=y. Requires CAP_NET_ADMIN (namespace-local via
unshare -Urn suffices).
tc qdisc add dev dummy0 root sfq
tc qdisc change dev dummy0 root sfq quantum 1 stab data 32768 size_log 15 cell_log 0
Fixes: e4650d7ae425 ("net_sched: sch_sfq: handle bigger packets")
Reported-by: Vega <vega@nebusec.ai>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
net/sched/sch_sfq.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 187d3ed578f2..8bbcfc9e85d9 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -660,6 +660,11 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt,
return -EINVAL;
}
+ if (ctl->quantum > 1 << 20) {
+ NL_SET_ERR_MSG_MOD(extack, "quantum too large");
+ return -EINVAL;
+ }
+
if (ctl->perturb_period < 0 ||
ctl->perturb_period > INT_MAX / HZ) {
NL_SET_ERR_MSG_MOD(extack, "invalid perturb period");
@@ -688,7 +693,7 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt,
/* update and validate configuration */
if (ctl->quantum)
- quantum = ctl->quantum;
+ quantum = max(256U, ctl->quantum);
if (ctl->flows)
maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS);
if (ctl->divisor) {
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH net v3 4/9] net/sched: hhf: clamp quantum in change and init paths
2026-09-01 21:39 [PATCH net v3 0/9] net/sched: clamp quantum/psched_mtu in change paths Jamal Hadi Salim
` (2 preceding siblings ...)
2026-09-01 21:39 ` [PATCH net v3 3/9] net/sched: sfq: " Jamal Hadi Salim
@ 2026-09-01 21:39 ` Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 5/9] net/sched: dualpi2: clamp psched_mtu at all call sites Jamal Hadi Salim
` (4 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Jamal Hadi Salim @ 2026-09-01 21:39 UTC (permalink / raw)
To: netdev
Cc: Jamal Hadi Salim, Jiri Pirko, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Victor Nogueira, Vega,
stable, Toke Høiland-Jørgensen, Vijay Subramanian,
Petr Machata, Chia-Yu Chang
hhf_change() accepts any quantum from userspace, including 1. With a
crafted size table qdisc_pkt_len reaches ~2 GiB, so quantum=1 makes
the deficit-refill loop spin ~2^31 times under the qdisc lock
(a soft lockup / denial of service).
Add max(256U, ...) in hhf_change() matching fq_codel_change(). Clamp
hhf_init() to [256, 1<<20] matching the siblings, and remove the old
fallback that only set quantum=256 on overflow.
Conditions to recreate the bug:
CONFIG_NET_SCH_HHF=y. Requires CAP_NET_ADMIN (namespace-local via
unshare -Urn suffices).
tc qdisc add dev dummy0 root hhf
tc qdisc change dev dummy0 root hhf quantum 1 stab data 32768 size_log 15 cell_log 0
Fixes: 10239edf86f1 ("net-qdisc-hhf: Heavy-Hitter Filter (HHF) qdisc")
Reported-by: Vega <vega@nebusec.ai>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
net/sched/sch_hhf.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c
index 96acab6a8da0..fc72f825fbd9 100644
--- a/net/sched/sch_hhf.c
+++ b/net/sched/sch_hhf.c
@@ -551,7 +551,7 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt,
return err;
if (tb[TCA_HHF_QUANTUM])
- new_quantum = nla_get_u32(tb[TCA_HHF_QUANTUM]);
+ new_quantum = max(256U, nla_get_u32(tb[TCA_HHF_QUANTUM]));
if (tb[TCA_HHF_NON_HH_WEIGHT])
new_hhf_non_hh_weight = nla_get_u32(tb[TCA_HHF_NON_HH_WEIGHT]);
@@ -613,7 +613,7 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt,
int i;
sch->limit = 1000;
- q->quantum = psched_mtu(qdisc_dev(sch));
+ q->quantum = clamp_t(u32, psched_mtu(qdisc_dev(sch)), 256, 1 << 20);
get_random_bytes(&q->perturbation, sizeof(q->perturbation));
INIT_LIST_HEAD(&q->new_buckets);
INIT_LIST_HEAD(&q->old_buckets);
@@ -624,10 +624,6 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt,
q->hhf_evict_timeout = HZ; /* 1 sec */
q->hhf_non_hh_weight = 2;
- if ((int)q->quantum <= 0 ||
- (u64)q->quantum * q->hhf_non_hh_weight > INT_MAX)
- q->quantum = 256;
-
if (opt) {
int err = hhf_change(sch, opt, extack);
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH net v3 5/9] net/sched: dualpi2: clamp psched_mtu at all call sites
2026-09-01 21:39 [PATCH net v3 0/9] net/sched: clamp quantum/psched_mtu in change paths Jamal Hadi Salim
` (3 preceding siblings ...)
2026-09-01 21:39 ` [PATCH net v3 4/9] net/sched: hhf: clamp quantum in change and init paths Jamal Hadi Salim
@ 2026-09-01 21:39 ` Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 6/9] net/sched: pie: clamp psched_mtu in pie_drop_early Jamal Hadi Salim
` (3 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Jamal Hadi Salim @ 2026-09-01 21:39 UTC (permalink / raw)
To: netdev
Cc: Jamal Hadi Salim, Jiri Pirko, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Victor Nogueira, Vega,
stable, Toke Høiland-Jørgensen, Vijay Subramanian,
Petr Machata, Chia-Yu Chang
dualpi2_calculate_c_protection(), must_drop(), and get_memory_limit()
call psched_mtu() with no clamp. A huge MTU makes (s32)psched_mtu()
overflow in the signed multiply for c_protection_init, and 2 *
psched_mtu() wraps in get_memory_limit(). With a crafted size table
qdisc_pkt_len reaches ~2 GiB, causing a soft lockup / denial of service.
Clamp psched_mtu() to [1, 1<<20] at all three call sites.
Conditions to recreate the bug:
CONFIG_NET_SCH_DUALPI2=y. Requires CAP_NET_ADMIN (namespace-local via
unshare -Urn suffices).
tc qdisc add dev dummy0 root dualpi2
tc qdisc change dev dummy0 root dualpi2 stab data 32768 size_log 15 cell_log 0
Fixes: 320d031ad6e4 ("sched: Struct definition and parsing of dualpi2 qdisc")
Reported-by: Vega <vega@nebusec.ai>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
net/sched/sch_dualpi2.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/net/sched/sch_dualpi2.c b/net/sched/sch_dualpi2.c
index 4f678d4ff10e..4947def7c49e 100644
--- a/net/sched/sch_dualpi2.c
+++ b/net/sched/sch_dualpi2.c
@@ -208,9 +208,11 @@ static void dualpi2_reset_c_protection(struct dualpi2_sched_data *q)
static void dualpi2_calculate_c_protection(struct Qdisc *sch,
struct dualpi2_sched_data *q, u32 wc)
{
+ u32 mtu = clamp_t(u32, psched_mtu(qdisc_dev(sch)), 1, 1 << 20);
+
q->c_protection_wc = wc;
q->c_protection_wl = MAX_WC - wc;
- q->c_protection_init = (s32)psched_mtu(qdisc_dev(sch)) *
+ q->c_protection_init = (s32)mtu *
((int)q->c_protection_wc - (int)q->c_protection_wl);
dualpi2_reset_c_protection(q);
}
@@ -285,8 +287,9 @@ static bool must_drop(struct Qdisc *sch, struct dualpi2_sched_data *q,
u64 local_l_prob;
bool overload;
u32 prob;
+ u32 mtu = clamp_t(u32, psched_mtu(qdisc_dev(sch)), 1, 1 << 20);
- if (sch->qstats.backlog < 2 * psched_mtu(qdisc_dev(sch)))
+ if (sch->qstats.backlog < 2 * mtu)
return false;
prob = READ_ONCE(q->pi2_prob);
@@ -712,7 +715,8 @@ static u32 get_memory_limit(struct Qdisc *sch, u32 limit)
/* Apply rule of thumb, i.e., doubling the packet length,
* to further include per packet overhead in memory_limit.
*/
- u64 memlim = mul_u32_u32(limit, 2 * psched_mtu(qdisc_dev(sch)));
+ u64 memlim = mul_u32_u32(limit, 2 * clamp_t(u32, psched_mtu(qdisc_dev(sch)),
+ 1, 1 << 20));
if (upper_32_bits(memlim))
return U32_MAX;
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH net v3 6/9] net/sched: pie: clamp psched_mtu in pie_drop_early
2026-09-01 21:39 [PATCH net v3 0/9] net/sched: clamp quantum/psched_mtu in change paths Jamal Hadi Salim
` (4 preceding siblings ...)
2026-09-01 21:39 ` [PATCH net v3 5/9] net/sched: dualpi2: clamp psched_mtu at all call sites Jamal Hadi Salim
@ 2026-09-01 21:39 ` Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 7/9] net/sched: drr: clamp quantum in change class Jamal Hadi Salim
` (2 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Jamal Hadi Salim @ 2026-09-01 21:39 UTC (permalink / raw)
To: netdev
Cc: Jamal Hadi Salim, Jiri Pirko, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Victor Nogueira, Vega,
stable, Toke Høiland-Jørgensen, Vijay Subramanian,
Petr Machata, Chia-Yu Chang
pie_drop_early() calls psched_mtu() with no clamp. With mtu=0x80000000
the bytemode divide silently zeroes the drop probability, disabling AQM.
Clamp to [1, 1<<20].
Conditions to recreate the bug:
CONFIG_NET_SCH_PIE=y. Requires CAP_NET_ADMIN (namespace-local via
unshare -Urn suffices).
tc qdisc add dev dummy0 root pie
tc qdisc change dev dummy0 root pie stab data 32768 size_log 15 cell_log 0
Fixes: d4b36210c2e6 ("net: pkt_sched: PIE AQM scheme")
Reported-by: Vega <vega@nebusec.ai>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
net/sched/sch_pie.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sched/sch_pie.c b/net/sched/sch_pie.c
index b41f2def2e2c..3b7863ffd284 100644
--- a/net/sched/sch_pie.c
+++ b/net/sched/sch_pie.c
@@ -35,7 +35,7 @@ bool pie_drop_early(struct Qdisc *sch, struct pie_params *params,
{
u64 rnd;
u64 local_prob = vars->prob;
- u32 mtu = psched_mtu(qdisc_dev(sch));
+ u32 mtu = clamp_t(u32, psched_mtu(qdisc_dev(sch)), 1, 1 << 20);
/* If there is still burst allowance left skip random early drop */
if (vars->burst_time > 0)
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH net v3 7/9] net/sched: drr: clamp quantum in change class
2026-09-01 21:39 [PATCH net v3 0/9] net/sched: clamp quantum/psched_mtu in change paths Jamal Hadi Salim
` (5 preceding siblings ...)
2026-09-01 21:39 ` [PATCH net v3 6/9] net/sched: pie: clamp psched_mtu in pie_drop_early Jamal Hadi Salim
@ 2026-09-01 21:39 ` Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 8/9] net/sched: ets: clamp quantum in parse and fallback paths Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 9/9] selftests: tc-testing: update ETS test 41f5 for clamped quanta Jamal Hadi Salim
8 siblings, 0 replies; 16+ messages in thread
From: Jamal Hadi Salim @ 2026-09-01 21:39 UTC (permalink / raw)
To: netdev
Cc: Jamal Hadi Salim, Jiri Pirko, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Victor Nogueira, Vega,
stable, Toke Høiland-Jørgensen, Vijay Subramanian,
Petr Machata, Chia-Yu Chang
drr_change_class() rejects explicit quantum==0 but falls back to
psched_mtu() with no floor. With a crafted size table qdisc_pkt_len
reaches ~2 GiB, so quantum=1 (or a zero psched_mtu on a headerless
device) makes the deficit-refill loop spin under the qdisc lock.
Add clamp_t(u32, quantum, 256, 1<<20) after the zero reject and on the
fallback path. The explicit-zero reject is preserved.
Conditions to recreate the bug:
CONFIG_NET_SCH_DRR=y. Requires CAP_NET_ADMIN (namespace-local via
unshare -Urn suffices).
tc qdisc add dev dummy0 root drr
tc class add dev dummy0 parent 1: classid 1:1 drr quantum 1
Fixes: 13d2a1d2b032 ("pkt_sched: add DRR scheduler")
Reported-by: Vega <vega@nebusec.ai>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
net/sched/sch_drr.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c
index 91b1ef824afa..8621d057edd9 100644
--- a/net/sched/sch_drr.c
+++ b/net/sched/sch_drr.c
@@ -82,8 +82,9 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
NL_SET_ERR_MSG(extack, "Specified DRR quantum cannot be zero");
return -EINVAL;
}
+ quantum = clamp_t(u32, quantum, 256, 1 << 20);
} else
- quantum = psched_mtu(qdisc_dev(sch));
+ quantum = clamp_t(u32, (u32)psched_mtu(qdisc_dev(sch)), 256, 1 << 20);
if (cl != NULL) {
if (tca[TCA_RATE]) {
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH net v3 8/9] net/sched: ets: clamp quantum in parse and fallback paths
2026-09-01 21:39 [PATCH net v3 0/9] net/sched: clamp quantum/psched_mtu in change paths Jamal Hadi Salim
` (6 preceding siblings ...)
2026-09-01 21:39 ` [PATCH net v3 7/9] net/sched: drr: clamp quantum in change class Jamal Hadi Salim
@ 2026-09-01 21:39 ` Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 9/9] selftests: tc-testing: update ETS test 41f5 for clamped quanta Jamal Hadi Salim
8 siblings, 0 replies; 16+ messages in thread
From: Jamal Hadi Salim @ 2026-09-01 21:39 UTC (permalink / raw)
To: netdev
Cc: Jamal Hadi Salim, Jiri Pirko, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Victor Nogueira, Vega,
stable, Toke Høiland-Jørgensen, Vijay Subramanian,
Petr Machata, Chia-Yu Chang
ets_qdisc_change() falls back to psched_mtu() with no floor for bands
without an explicit quantum. With a crafted size table qdisc_pkt_len
reaches ~2 GiB, so a zero psched_mtu on a headerless device makes the
deficit-refill loop spin under the qdisc lock.
Move the floor into ets_quantum_parse() so explicitly configured quanta
are also clamped to [256, 1<<20], not just the fallback path.
Conditions to recreate the bug:
CONFIG_NET_SCH_ETS=y. Requires CAP_NET_ADMIN (namespace-local via
unshare -Urn suffices).
tc qdisc add dev dummy0 root ets bands 3 strict 2 quanta 1 1
Fixes: dcc68b4d8084 ("net: sch_ets: Add a new Qdisc")
Reported-by: Vega <vega@nebusec.ai>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
net/sched/sch_ets.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c
index 25fcf4079fec..6cc902a03838 100644
--- a/net/sched/sch_ets.c
+++ b/net/sched/sch_ets.c
@@ -83,11 +83,7 @@ static int ets_quantum_parse(struct Qdisc *sch, const struct nlattr *attr,
unsigned int *quantum,
struct netlink_ext_ack *extack)
{
- *quantum = nla_get_u32(attr);
- if (!*quantum) {
- NL_SET_ERR_MSG(extack, "ETS quantum cannot be zero");
- return -EINVAL;
- }
+ *quantum = clamp_t(u32, nla_get_u32(attr), 256, 1 << 20);
return 0;
}
@@ -632,11 +628,13 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
return err;
}
/* If there are more bands than strict + quanta provided, the remaining
- * ones are ETS with quantum of MTU. Initialize the missing values here.
+ * ones are ETS with quantum of max(MTU, 256). Initialize the missing
+ * values here.
*/
for (i = nstrict; i < nbands; i++) {
if (!quanta[i])
- quanta[i] = psched_mtu(qdisc_dev(sch));
+ quanta[i] = clamp_t(u32, (u32)psched_mtu(qdisc_dev(sch)),
+ 256, 1 << 20);
}
/* Before commit, make sure we can allocate all new qdiscs */
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH net v3 9/9] selftests: tc-testing: update ETS test 41f5 for clamped quanta
2026-09-01 21:39 [PATCH net v3 0/9] net/sched: clamp quantum/psched_mtu in change paths Jamal Hadi Salim
` (7 preceding siblings ...)
2026-09-01 21:39 ` [PATCH net v3 8/9] net/sched: ets: clamp quantum in parse and fallback paths Jamal Hadi Salim
@ 2026-09-01 21:39 ` Jamal Hadi Salim
8 siblings, 0 replies; 16+ messages in thread
From: Jamal Hadi Salim @ 2026-09-01 21:39 UTC (permalink / raw)
To: netdev
Cc: Jamal Hadi Salim, Jiri Pirko, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Victor Nogueira, Vega,
Shuah Khan, linux-kselftest, Toke Høiland-Jørgensen
Commit "net/sched: ets: clamp quantum in parse and fallback paths"
moved the quantum floor into ets_quantum_parse(), so every explicitly
configured quantum is now clamped to [256, 1 << 20], not just the
psched_mtu() fallback.
Test 41f5 passes "quanta 4294967294 1 1" and matches the values back
verbatim, so all three bands now differ from what it expects:
before: bands 3 quanta 4294967294 1 1
after: bands 3 quanta 1048576 256 256
Update the match pattern accordingly.
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
tools/testing/selftests/tc-testing/tc-tests/qdiscs/ets.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/ets.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/ets.json
index ee09e6d6fdf3..d2eab61c099a 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/ets.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/ets.json
@@ -987,7 +987,7 @@
},
{
"id": "41f5",
- "name": "ETS offload where the sum of quanta wraps u32",
+ "name": "ETS offload with out-of-range quanta clamped",
"category": [
"qdisc",
"ets"
@@ -1002,7 +1002,7 @@
"cmdUnderTest": "$TC qdisc add dev $ETH root ets quanta 4294967294 1 1",
"expExitCode": "0",
"verifyCmd": "$TC qdisc show dev $ETH",
- "matchPattern": "qdisc ets .*bands 3 quanta 4294967294 1 1",
+ "matchPattern": "qdisc ets .*bands 3 quanta 1048576 256 256",
"matchCount": "1",
"teardown": [
"echo \"1\" > /sys/bus/netdevsim/del_device"
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH net v3 1/9] net/sched: fq: clamp quantum and initial_quantum in change path
2026-09-01 21:39 ` [PATCH net v3 1/9] net/sched: fq: clamp quantum and initial_quantum in change path Jamal Hadi Salim
@ 2026-09-01 23:52 ` Eric Dumazet
2026-09-02 0:08 ` Eric Dumazet
0 siblings, 1 reply; 16+ messages in thread
From: Eric Dumazet @ 2026-09-01 23:52 UTC (permalink / raw)
To: Jamal Hadi Salim
Cc: netdev, Jiri Pirko, David S. Miller, Jakub Kicinski, Paolo Abeni,
Simon Horman, Victor Nogueira, Vega, stable,
Toke Høiland-Jørgensen, Vijay Subramanian, Petr Machata,
Chia-Yu Chang
On Tue, Sep 1, 2026 at 11:39 PM Jamal Hadi Salim <jhs@mojatatu.com> wrote:
>
> The fq change path accepts TCA_FQ_QUANTUM in [1, INT_MAX] and
> TCA_FQ_INITIAL_QUANTUM up to INT_MAX, while fq_init() already clamps to
> [1, 1<<20]. A user can override the init clamp via tc qdisc change,
> restoring the small-quantum deficit spin that the init clamp prevents.
>
> Narrow iq_range.max to 1<<20 so TCA_FQ_INITIAL_QUANTUM is rejected at
> parse time. Clamp TCA_FQ_QUANTUM to [256, 1<<20] in fq_change() and
> fq_init() quantum to [256, 1<<20] for tiny-MTU devices.
>
> Conditions to recreate the bug:
> CONFIG_NET_SCH_FQ=y. Requires CAP_NET_ADMIN (namespace-local via
> unshare -Urn suffices).
>
> tc qdisc add dev dummy0 root fq
> tc qdisc change dev dummy0 root fq quantum 1 stab data 32768 size_log 15 cell_log 0
>
> Fixes: 709f34f7c28d ("net/sched: fq: add overflow bounds to quantum and initial quantum")
> Reported-by: Vega <vega@nebusec.ai>
> Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
> Tested-by: Victor Nogueira <victor@mojatatu.com>
> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> ---
> net/sched/sch_fq.c | 14 +++++---------
> 1 file changed, 5 insertions(+), 9 deletions(-)
>
> diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
> index 6144b5686f13..35f940b2205d 100644
> --- a/net/sched/sch_fq.c
> +++ b/net/sched/sch_fq.c
> @@ -980,7 +980,7 @@ static int fq_resize(struct Qdisc *sch, u32 log)
> }
>
> static const struct netlink_range_validation iq_range = {
> - .max = INT_MAX,
> + .max = 1 << 20,
> };
>
> static const struct nla_policy fq_policy[TCA_FQ_MAX + 1] = {
> @@ -1106,14 +1106,10 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt,
> nla_get_u32(tb[TCA_FQ_FLOW_PLIMIT]));
>
> if (tb[TCA_FQ_QUANTUM]) {
> - u32 quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]);
> + u32 quantum = clamp_t(u32, nla_get_u32(tb[TCA_FQ_QUANTUM]),
> + 256, 1 << 20);
>
> - if (quantum > 0 && quantum <= (1 << 20)) {
> - WRITE_ONCE(q->quantum, quantum);
> - } else {
> - NL_SET_ERR_MSG_MOD(extack, "invalid quantum");
> - err = -EINVAL;
> - }
> + WRITE_ONCE(q->quantum, quantum);
> }
>
> if (tb[TCA_FQ_INITIAL_QUANTUM])
> @@ -1232,7 +1228,7 @@ static int fq_init(struct Qdisc *sch, struct nlattr *opt,
> sch->limit = 10000;
> q->flow_plimit = 100;
> mtu = clamp_t(u32, psched_mtu(qdisc_dev(sch)), 1, 1 << 20);
> - q->quantum = min_t(u32, 2 * mtu, 1 << 20);
> + q->quantum = clamp_t(u32, 2 * mtu, 256, 1 << 20);
> q->initial_quantum = min_t(u32, 10 * mtu, 1 << 20);
> q->flow_refill_delay = msecs_to_jiffies(40);
> q->flow_max_rate = ~0UL;
> --
> 2.43.0
>
If we consider dev->mtu admissible values, which are in [0, INT_MAX],
we have to guard against u32 overflows
for 2*mtu and 10*mtu expressions.
Commit 709f34f7c28d ("net/sched: fq: add overflow bounds to quantum
and initial quantum") missed this?
Please use for q->quantum: clamp_t(u64, 2ULL * mtu, 1ULL << 20)
and for q->initial_quantum: clamp_t(u64, 10ULL * mtu, 1ULL << 20)
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net v3 1/9] net/sched: fq: clamp quantum and initial_quantum in change path
2026-09-01 23:52 ` Eric Dumazet
@ 2026-09-02 0:08 ` Eric Dumazet
2026-09-02 12:40 ` Jamal Hadi Salim
0 siblings, 1 reply; 16+ messages in thread
From: Eric Dumazet @ 2026-09-02 0:08 UTC (permalink / raw)
To: Jamal Hadi Salim
Cc: netdev, Jiri Pirko, David S. Miller, Jakub Kicinski, Paolo Abeni,
Simon Horman, Victor Nogueira, Vega, stable,
Toke Høiland-Jørgensen, Vijay Subramanian, Petr Machata,
Chia-Yu Chang
On Wed, Sep 2, 2026 at 1:52 AM Eric Dumazet <edumazet@google.com> wrote:
>
> On Tue, Sep 1, 2026 at 11:39 PM Jamal Hadi Salim <jhs@mojatatu.com> wrote:
> >
> > The fq change path accepts TCA_FQ_QUANTUM in [1, INT_MAX] and
> > TCA_FQ_INITIAL_QUANTUM up to INT_MAX, while fq_init() already clamps to
> > [1, 1<<20]. A user can override the init clamp via tc qdisc change,
> > restoring the small-quantum deficit spin that the init clamp prevents.
> >
> > Narrow iq_range.max to 1<<20 so TCA_FQ_INITIAL_QUANTUM is rejected at
> > parse time. Clamp TCA_FQ_QUANTUM to [256, 1<<20] in fq_change() and
> > fq_init() quantum to [256, 1<<20] for tiny-MTU devices.
> >
> > Conditions to recreate the bug:
> > CONFIG_NET_SCH_FQ=y. Requires CAP_NET_ADMIN (namespace-local via
> > unshare -Urn suffices).
> >
> > tc qdisc add dev dummy0 root fq
> > tc qdisc change dev dummy0 root fq quantum 1 stab data 32768 size_log 15 cell_log 0
> >
> > Fixes: 709f34f7c28d ("net/sched: fq: add overflow bounds to quantum and initial quantum")
> > Reported-by: Vega <vega@nebusec.ai>
> > Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
> > Tested-by: Victor Nogueira <victor@mojatatu.com>
> > Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> > ---
> > net/sched/sch_fq.c | 14 +++++---------
> > 1 file changed, 5 insertions(+), 9 deletions(-)
> >
> > diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
> > index 6144b5686f13..35f940b2205d 100644
> > --- a/net/sched/sch_fq.c
> > +++ b/net/sched/sch_fq.c
> > @@ -980,7 +980,7 @@ static int fq_resize(struct Qdisc *sch, u32 log)
> > }
> >
> > static const struct netlink_range_validation iq_range = {
> > - .max = INT_MAX,
> > + .max = 1 << 20,
> > };
> >
> > static const struct nla_policy fq_policy[TCA_FQ_MAX + 1] = {
> > @@ -1106,14 +1106,10 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt,
> > nla_get_u32(tb[TCA_FQ_FLOW_PLIMIT]));
> >
> > if (tb[TCA_FQ_QUANTUM]) {
> > - u32 quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]);
> > + u32 quantum = clamp_t(u32, nla_get_u32(tb[TCA_FQ_QUANTUM]),
> > + 256, 1 << 20);
> >
> > - if (quantum > 0 && quantum <= (1 << 20)) {
> > - WRITE_ONCE(q->quantum, quantum);
> > - } else {
> > - NL_SET_ERR_MSG_MOD(extack, "invalid quantum");
> > - err = -EINVAL;
> > - }
> > + WRITE_ONCE(q->quantum, quantum);
> > }
> >
> > if (tb[TCA_FQ_INITIAL_QUANTUM])
> > @@ -1232,7 +1228,7 @@ static int fq_init(struct Qdisc *sch, struct nlattr *opt,
> > sch->limit = 10000;
> > q->flow_plimit = 100;
> > mtu = clamp_t(u32, psched_mtu(qdisc_dev(sch)), 1, 1 << 20);
> > - q->quantum = min_t(u32, 2 * mtu, 1 << 20);
> > + q->quantum = clamp_t(u32, 2 * mtu, 256, 1 << 20);
> > q->initial_quantum = min_t(u32, 10 * mtu, 1 << 20);
> > q->flow_refill_delay = msecs_to_jiffies(40);
> > q->flow_max_rate = ~0UL;
> > --
> > 2.43.0
> >
>
> If we consider dev->mtu admissible values, which are in [0, INT_MAX],
> we have to guard against u32 overflows
> for 2*mtu and 10*mtu expressions.
>
> Commit 709f34f7c28d ("net/sched: fq: add overflow bounds to quantum
> and initial quantum") missed this?
>
> Please use for q->quantum: clamp_t(u64, 2ULL * mtu, 1ULL << 20)
> and for q->initial_quantum: clamp_t(u64, 10ULL * mtu, 1ULL << 20)
Wait, I missed the
mtu = clamp_t(u32, psched_mtu(qdisc_dev(sch)), 1, 1 << 20);
Not clear why we have so many clamp_t(), this is quite confusing.
We could instead:
mtu = psched_mtu(qdisc_dev(sch));
q->quantum = clamp_t(u64, 2ULL * mtu, 256, 1ULL << 20);
q->initial_quantum = min_t(u64, 10ULL * mtu, 1ULL << 20);
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net v3 1/9] net/sched: fq: clamp quantum and initial_quantum in change path
2026-09-02 0:08 ` Eric Dumazet
@ 2026-09-02 12:40 ` Jamal Hadi Salim
2026-09-02 13:03 ` Eric Dumazet
0 siblings, 1 reply; 16+ messages in thread
From: Jamal Hadi Salim @ 2026-09-02 12:40 UTC (permalink / raw)
To: Eric Dumazet
Cc: netdev, Jiri Pirko, David S. Miller, Jakub Kicinski, Paolo Abeni,
Simon Horman, Victor Nogueira, Vega, stable,
Toke Høiland-Jørgensen, Vijay Subramanian, Petr Machata,
Chia-Yu Chang
On Tue, Sep 1, 2026 at 8:08 PM Eric Dumazet <edumazet@google.com> wrote:
>
> On Wed, Sep 2, 2026 at 1:52 AM Eric Dumazet <edumazet@google.com> wrote:
> >
> > On Tue, Sep 1, 2026 at 11:39 PM Jamal Hadi Salim <jhs@mojatatu.com> wrote:
> > >
> > > The fq change path accepts TCA_FQ_QUANTUM in [1, INT_MAX] and
> > > TCA_FQ_INITIAL_QUANTUM up to INT_MAX, while fq_init() already clamps to
> > > [1, 1<<20]. A user can override the init clamp via tc qdisc change,
> > > restoring the small-quantum deficit spin that the init clamp prevents.
> > >
> > > Narrow iq_range.max to 1<<20 so TCA_FQ_INITIAL_QUANTUM is rejected at
> > > parse time. Clamp TCA_FQ_QUANTUM to [256, 1<<20] in fq_change() and
> > > fq_init() quantum to [256, 1<<20] for tiny-MTU devices.
> > >
> > > Conditions to recreate the bug:
> > > CONFIG_NET_SCH_FQ=y. Requires CAP_NET_ADMIN (namespace-local via
> > > unshare -Urn suffices).
> > >
> > > tc qdisc add dev dummy0 root fq
> > > tc qdisc change dev dummy0 root fq quantum 1 stab data 32768 size_log 15 cell_log 0
> > >
> > > Fixes: 709f34f7c28d ("net/sched: fq: add overflow bounds to quantum and initial quantum")
> > > Reported-by: Vega <vega@nebusec.ai>
> > > Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
> > > Tested-by: Victor Nogueira <victor@mojatatu.com>
> > > Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> > > ---
> > > net/sched/sch_fq.c | 14 +++++---------
> > > 1 file changed, 5 insertions(+), 9 deletions(-)
> > >
> > > diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
> > > index 6144b5686f13..35f940b2205d 100644
> > > --- a/net/sched/sch_fq.c
> > > +++ b/net/sched/sch_fq.c
> > > @@ -980,7 +980,7 @@ static int fq_resize(struct Qdisc *sch, u32 log)
> > > }
> > >
> > > static const struct netlink_range_validation iq_range = {
> > > - .max = INT_MAX,
> > > + .max = 1 << 20,
> > > };
> > >
> > > static const struct nla_policy fq_policy[TCA_FQ_MAX + 1] = {
> > > @@ -1106,14 +1106,10 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt,
> > > nla_get_u32(tb[TCA_FQ_FLOW_PLIMIT]));
> > >
> > > if (tb[TCA_FQ_QUANTUM]) {
> > > - u32 quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]);
> > > + u32 quantum = clamp_t(u32, nla_get_u32(tb[TCA_FQ_QUANTUM]),
> > > + 256, 1 << 20);
> > >
> > > - if (quantum > 0 && quantum <= (1 << 20)) {
> > > - WRITE_ONCE(q->quantum, quantum);
> > > - } else {
> > > - NL_SET_ERR_MSG_MOD(extack, "invalid quantum");
> > > - err = -EINVAL;
> > > - }
> > > + WRITE_ONCE(q->quantum, quantum);
> > > }
> > >
> > > if (tb[TCA_FQ_INITIAL_QUANTUM])
> > > @@ -1232,7 +1228,7 @@ static int fq_init(struct Qdisc *sch, struct nlattr *opt,
> > > sch->limit = 10000;
> > > q->flow_plimit = 100;
> > > mtu = clamp_t(u32, psched_mtu(qdisc_dev(sch)), 1, 1 << 20);
> > > - q->quantum = min_t(u32, 2 * mtu, 1 << 20);
> > > + q->quantum = clamp_t(u32, 2 * mtu, 256, 1 << 20);
> > > q->initial_quantum = min_t(u32, 10 * mtu, 1 << 20);
> > > q->flow_refill_delay = msecs_to_jiffies(40);
> > > q->flow_max_rate = ~0UL;
> > > --
> > > 2.43.0
> > >
> >
> > If we consider dev->mtu admissible values, which are in [0, INT_MAX],
> > we have to guard against u32 overflows
> > for 2*mtu and 10*mtu expressions.
> >
> > Commit 709f34f7c28d ("net/sched: fq: add overflow bounds to quantum
> > and initial quantum") missed this?
> >
> > Please use for q->quantum: clamp_t(u64, 2ULL * mtu, 1ULL << 20)
> > and for q->initial_quantum: clamp_t(u64, 10ULL * mtu, 1ULL << 20)
>
> Wait, I missed the
> mtu = clamp_t(u32, psched_mtu(qdisc_dev(sch)), 1, 1 << 20);
>
> Not clear why we have so many clamp_t(), this is quite confusing.
>
> We could instead:
>
> mtu = psched_mtu(qdisc_dev(sch));
> q->quantum = clamp_t(u64, 2ULL * mtu, 256, 1ULL << 20);
> q->initial_quantum = min_t(u64, 10ULL * mtu, 1ULL << 20);
Trying to understand your concern: Are you arguing for
stylistic/readability improvement or robustness?
The only place i can see where the multiplies you describe could
happen is what the 709f34f7c28d patch closed. i.e this part:
- q->quantum = 2 * psched_mtu(qdisc_dev(sch));
- q->initial_quantum = 10 * psched_mtu(qdisc_dev(sch));
IIRC, you are suggesting restoring the original logic (x2 and x10) and
i am likely missing why that is a must do? Does it break anything?
cheers,
jamal
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net v3 1/9] net/sched: fq: clamp quantum and initial_quantum in change path
2026-09-02 12:40 ` Jamal Hadi Salim
@ 2026-09-02 13:03 ` Eric Dumazet
2026-09-02 13:55 ` Jamal Hadi Salim
0 siblings, 1 reply; 16+ messages in thread
From: Eric Dumazet @ 2026-09-02 13:03 UTC (permalink / raw)
To: Jamal Hadi Salim
Cc: netdev, Jiri Pirko, David S. Miller, Jakub Kicinski, Paolo Abeni,
Simon Horman, Victor Nogueira, Vega, stable,
Toke Høiland-Jørgensen, Vijay Subramanian, Petr Machata,
Chia-Yu Chang
On Wed, Sep 2, 2026 at 2:40 PM Jamal Hadi Salim <jhs@mojatatu.com> wrote:
>
>
> Trying to understand your concern: Are you arguing for
> stylistic/readability improvement or robustness?
> The only place i can see where the multiplies you describe could
> happen is what the 709f34f7c28d patch closed. i.e this part:
>
> - q->quantum = 2 * psched_mtu(qdisc_dev(sch));
> - q->initial_quantum = 10 * psched_mtu(qdisc_dev(sch));
>
> IIRC, you are suggesting restoring the original logic (x2 and x10) and
> i am likely missing why that is a must do? Does it break anything?
It does not break anything; it just causes a cascade of various clamps.
After your patch we will have:
mtu = clamp_t(u32, psched_mtu(qdisc_dev(sch)), 1, 1 << 20);
q->quantum = clamp_t(u32, 2 * mtu, 256, 1 << 20);
q->initial_quantum = min_t(u32, 10 * mtu, 1 << 20);
So @mtu is no longer the psched mtu anymore.
This is fine.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net v3 1/9] net/sched: fq: clamp quantum and initial_quantum in change path
2026-09-02 13:03 ` Eric Dumazet
@ 2026-09-02 13:55 ` Jamal Hadi Salim
2026-09-02 14:26 ` Eric Dumazet
0 siblings, 1 reply; 16+ messages in thread
From: Jamal Hadi Salim @ 2026-09-02 13:55 UTC (permalink / raw)
To: Eric Dumazet
Cc: netdev, Jiri Pirko, David S. Miller, Jakub Kicinski, Paolo Abeni,
Simon Horman, Victor Nogueira, Vega, stable,
Toke Høiland-Jørgensen, Vijay Subramanian, Petr Machata,
Chia-Yu Chang
On Wed, Sep 2, 2026 at 9:04 AM Eric Dumazet <edumazet@google.com> wrote:
>
> On Wed, Sep 2, 2026 at 2:40 PM Jamal Hadi Salim <jhs@mojatatu.com> wrote:
> >
> >
> > Trying to understand your concern: Are you arguing for
> > stylistic/readability improvement or robustness?
> > The only place i can see where the multiplies you describe could
> > happen is what the 709f34f7c28d patch closed. i.e this part:
> >
> > - q->quantum = 2 * psched_mtu(qdisc_dev(sch));
> > - q->initial_quantum = 10 * psched_mtu(qdisc_dev(sch));
> >
> > IIRC, you are suggesting restoring the original logic (x2 and x10) and
> > i am likely missing why that is a must do? Does it break anything?
>
> It does not break anything; it just causes a cascade of various clamps.
>
> After your patch we will have:
>
> mtu = clamp_t(u32, psched_mtu(qdisc_dev(sch)), 1, 1 << 20);
> q->quantum = clamp_t(u32, 2 * mtu, 256, 1 << 20);
> q->initial_quantum = min_t(u32, 10 * mtu, 1 << 20);
>
> So @mtu is no longer the psched mtu anymore.
>
> This is fine.
The u64 variant would read cleaner for sure. If i didnt misread you
though you are saying the current the mtu-no-longer-psched_mtu
aliasing is fine. So would it be ok to see if any other comments
spring up from says sashiko that are worth reviewing the patch before
I proceed with this? Or do you want a v4 or a followup?
cheers,
jamal
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net v3 1/9] net/sched: fq: clamp quantum and initial_quantum in change path
2026-09-02 13:55 ` Jamal Hadi Salim
@ 2026-09-02 14:26 ` Eric Dumazet
0 siblings, 0 replies; 16+ messages in thread
From: Eric Dumazet @ 2026-09-02 14:26 UTC (permalink / raw)
To: Jamal Hadi Salim
Cc: netdev, Jiri Pirko, David S. Miller, Jakub Kicinski, Paolo Abeni,
Simon Horman, Victor Nogueira, Vega, stable,
Toke Høiland-Jørgensen, Vijay Subramanian, Petr Machata,
Chia-Yu Chang
On Wed, Sep 2, 2026 at 3:55 PM Jamal Hadi Salim <jhs@mojatatu.com> wrote:
>
> On Wed, Sep 2, 2026 at 9:04 AM Eric Dumazet <edumazet@google.com> wrote:
> >
> > On Wed, Sep 2, 2026 at 2:40 PM Jamal Hadi Salim <jhs@mojatatu.com> wrote:
> > >
> > >
> > > Trying to understand your concern: Are you arguing for
> > > stylistic/readability improvement or robustness?
> > > The only place i can see where the multiplies you describe could
> > > happen is what the 709f34f7c28d patch closed. i.e this part:
> > >
> > > - q->quantum = 2 * psched_mtu(qdisc_dev(sch));
> > > - q->initial_quantum = 10 * psched_mtu(qdisc_dev(sch));
> > >
> > > IIRC, you are suggesting restoring the original logic (x2 and x10) and
> > > i am likely missing why that is a must do? Does it break anything?
> >
> > It does not break anything; it just causes a cascade of various clamps.
> >
> > After your patch we will have:
> >
> > mtu = clamp_t(u32, psched_mtu(qdisc_dev(sch)), 1, 1 << 20);
> > q->quantum = clamp_t(u32, 2 * mtu, 256, 1 << 20);
> > q->initial_quantum = min_t(u32, 10 * mtu, 1 << 20);
> >
> > So @mtu is no longer the psched mtu anymore.
> >
> > This is fine.
>
> The u64 variant would read cleaner for sure. If i didnt misread you
> though you are saying the current the mtu-no-longer-psched_mtu
> aliasing is fine. So would it be ok to see if any other comments
> spring up from says sashiko that are worth reviewing the patch before
> I proceed with this? Or do you want a v4 or a followup?
I think v3 is fine, thanks.
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2026-09-02 14:26 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-01 21:39 [PATCH net v3 0/9] net/sched: clamp quantum/psched_mtu in change paths Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 1/9] net/sched: fq: clamp quantum and initial_quantum in change path Jamal Hadi Salim
2026-09-01 23:52 ` Eric Dumazet
2026-09-02 0:08 ` Eric Dumazet
2026-09-02 12:40 ` Jamal Hadi Salim
2026-09-02 13:03 ` Eric Dumazet
2026-09-02 13:55 ` Jamal Hadi Salim
2026-09-02 14:26 ` Eric Dumazet
2026-09-01 21:39 ` [PATCH net v3 2/9] net/sched: fq_pie: clamp quantum " Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 3/9] net/sched: sfq: " Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 4/9] net/sched: hhf: clamp quantum in change and init paths Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 5/9] net/sched: dualpi2: clamp psched_mtu at all call sites Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 6/9] net/sched: pie: clamp psched_mtu in pie_drop_early Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 7/9] net/sched: drr: clamp quantum in change class Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 8/9] net/sched: ets: clamp quantum in parse and fallback paths Jamal Hadi Salim
2026-09-01 21:39 ` [PATCH net v3 9/9] selftests: tc-testing: update ETS test 41f5 for clamped quanta Jamal Hadi Salim
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox