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

sfq_init() sets q->quantum = psched_mtu(qdisc_dev(sch)) (unsigned). A
device with a huge MTU (e.g. dummy with max_mtu == 0 accepting MTU
2147483634) makes psched_mtu() return 0x80000000, so slot->allot = INT_MIN
and INT_MIN + INT_MIN toggles between INT_MIN and 0 forever, spinning
sfq_dequeue() under the qdisc lock.

Clamp the quantum to [256, 1 << 20] so the refill loop terminates. The
lower bound also covers q->quantum == 0 (psched_mtu() returning 0),
which spins sfq_dequeue() identically. sfq_change() already rejects a
negative quantum, so only the init path was exposed.

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: 1da177e4c3f4 ("Linux-2.6.12-rc2")
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-7-jhs@mojatatu.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/sched/sch_sfq.c

index 96eb2f122973ad5f38311e4669b01539fdbeaeda..645e40f2f402d7649db8e9f09be814f1719f28f2 100644 (file)
@@ -796,7 +796,8 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt,
        q->tail = NULL;
        q->divisor = SFQ_DEFAULT_HASH_DIVISOR;
        q->maxflows = SFQ_DEFAULT_FLOWS;
-       q->quantum = psched_mtu(qdisc_dev(sch));
+       q->quantum = clamp_t(u32, psched_mtu(qdisc_dev(sch)),
+                            256, 1 << 20);
        q->perturb_period = 0;
        get_random_bytes(&q->perturbation, sizeof(q->perturbation));