Skip to content

Commit 34577e3

Browse files
committed
net_sched: ets: Fix double list add in class with netem as child qdisc
jira VULN-73369 cve CVE-2025-37914 commit-author Victor Nogueira <victor@mojatatu.com> commit 1a6d0c0 As described in Gerrard's report [1], there are use cases where a netem child qdisc will make the parent qdisc's enqueue callback reentrant. In the case of ets, there won't be a UAF, but the code will add the same classifier to the list twice, which will cause memory corruption. In addition to checking for qlen being zero, this patch checks whether the class was already added to the active_list (cl_is_active) before doing the addition to cater for the reentrant case. [1] https://lore.kernel.org/netdev/CAHcdcOm+03OD2j6R0=YHKqmy=VgJ8xEOKuP6c7mSgnp-TEJJbw@mail.gmail.com/ Fixes: 37d9cf1 ("sched: Fix detection of empty queues in child qdiscs") Acked-by: Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: Victor Nogueira <victor@mojatatu.com> Link: https://patch.msgid.link/20250425220710.3964791-4-victor@mojatatu.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> (cherry picked from commit 1a6d0c0) Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
1 parent d99a806 commit 34577e3

File tree

1 file changed

+6
-3
lines changed

1 file changed

+6
-3
lines changed

net/sched/sch_ets.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ static const struct nla_policy ets_class_policy[TCA_ETS_MAX + 1] = {
7474
[TCA_ETS_QUANTA_BAND] = { .type = NLA_U32 },
7575
};
7676

77+
static bool cl_is_active(struct ets_class *cl)
78+
{
79+
return !list_empty(&cl->alist);
80+
}
81+
7782
static int ets_quantum_parse(struct Qdisc *sch, const struct nlattr *attr,
7883
unsigned int *quantum,
7984
struct netlink_ext_ack *extack)
@@ -422,7 +427,6 @@ static int ets_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
422427
struct ets_sched *q = qdisc_priv(sch);
423428
struct ets_class *cl;
424429
int err = 0;
425-
bool first;
426430

427431
cl = ets_classify(skb, sch, &err);
428432
if (!cl) {
@@ -432,7 +436,6 @@ static int ets_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
432436
return err;
433437
}
434438

435-
first = !cl->qdisc->q.qlen;
436439
err = qdisc_enqueue(skb, cl->qdisc, to_free);
437440
if (unlikely(err != NET_XMIT_SUCCESS)) {
438441
if (net_xmit_drop_count(err)) {
@@ -442,7 +445,7 @@ static int ets_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
442445
return err;
443446
}
444447

445-
if (first && !ets_class_is_strict(q, cl)) {
448+
if (!cl_is_active(cl) && !ets_class_is_strict(q, cl)) {
446449
list_add_tail(&cl->alist, &q->active);
447450
cl->deficit = cl->quantum;
448451
}

0 commit comments

Comments
 (0)