From: Eric Dumazet Date: Wed, 11 Jun 2025 11:15:14 +0000 (+0000) Subject: net_sched: ets: fix a race in ets_qdisc_change() X-Git-Tag: v5.10.239~216 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=eb7b74e9754e1ba2088f914ad1f57a778b11894b;p=thirdparty%2Fkernel%2Fstable.git net_sched: ets: fix a race in ets_qdisc_change() [ Upstream commit d92adacdd8c2960be856e0b82acc5b7c5395fddb ] Gerrard Tai reported a race condition in ETS, whenever SFQ perturb timer fires at the wrong time. The race is as follows: CPU 0 CPU 1 [1]: lock root [2]: qdisc_tree_flush_backlog() [3]: unlock root | | [5]: lock root | [6]: rehash | [7]: qdisc_tree_reduce_backlog() | [4]: qdisc_put() This can be abused to underflow a parent's qlen. Calling qdisc_purge_queue() instead of qdisc_tree_flush_backlog() should fix the race, because all packets will be purged from the qdisc before releasing the lock. Fixes: b05972f01e7d ("net: sched: tbf: don't call qdisc_put() while holding tree lock") Reported-by: Gerrard Tai Suggested-by: Gerrard Tai Signed-off-by: Eric Dumazet Link: https://patch.msgid.link/20250611111515.1983366-5-edumazet@google.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c index 55b3362d27106..4f4da11a2c779 100644 --- a/net/sched/sch_ets.c +++ b/net/sched/sch_ets.c @@ -675,7 +675,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, for (i = q->nbands; i < oldbands; i++) { if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) list_del_init(&q->classes[i].alist); - qdisc_tree_flush_backlog(q->classes[i].qdisc); + qdisc_purge_queue(q->classes[i].qdisc); } q->nstrict = nstrict; memcpy(q->prio2band, priomap, sizeof(priomap));