]> git.hungrycats.org Git - linux/commitdiff
net/sched: hhf: clamp quantum before hhf_change() to avoid overflow
authorJamal Hadi Salim <jhs@mojatatu.com>
Sat, 22 Aug 2026 19:55:08 +0000 (15:55 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 14 Sep 2026 11:36:13 +0000 (13:36 +0200)
[ Upstream commit 2164b512b97bb053e8ce4d6e95576f11bed6a005 ]

hhf_init() sets q->quantum = psched_mtu(qdisc_dev(sch)) with no overflow
check. A device with a huge MTU (e.g. dummy with max_mtu == 0 accepting
MTU 2147483634) makes weight * quantum overflow the signed deficit in
hhf_dequeue(), spinning forever.

Clamp q->quantum before hhf_change() so both the opt and !opt paths see
a sane quantum. Without this, bare "tc qdisc add ... hhf" succeeds with
a clamped quantum but "tc qdisc add ... hhf limit 1000" (any option
present) fails with -EINVAL because hhf_change() re-validates the
unclamped default (sch_hhf.c:559). 256 matches fq_codel's floor and is
a sane minimum for a DRR quantum.

Conditions to recreate the bug: a device whose MTU (plus
hard_header_len) wraps psched_mtu() into the sign bit (e.g. a dummy
device with max_mtu == 0 accepting MTU 2147483634). Requires
CAP_NET_ADMIN in a user namespace.

Fixes: 10239edf86f1 ("net-qdisc-hhf: Heavy-Hitter Filter (HHF) qdisc")
Reported-by: vega@nebusec.ai
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/20260822195509.112717-6-jhs@mojatatu.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/sched/sch_hhf.c

index e1c9d1edc8a99b1d979e02d01258712474be044f..863a5b3e1d096bdff058c1caedbe31ed83a02630 100644 (file)
@@ -623,6 +623,10 @@ 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);