diff options
| author | Cong Wang <xiyou.wangcong@gmail.com> | 2025-05-27 14:47:32 -0700 |
|---|---|---|
| committer | Manuel Diewald <manuel.diewald@canonical.com> | 2025-06-13 18:36:24 +0200 |
| commit | 7804135b4bdd82525f3ca0c4ad139ada6b7662d4 (patch) | |
| tree | ef635082b8ec684ac1dd93e2a0e56bd39731bdfa | |
| parent | 7b9221025d59ef155fc33223d67def54e175dbbf (diff) | |
sch_drr: make drr_qlen_notify() idempotent
drr_qlen_notify() always deletes the DRR class from its active list
with list_del(), therefore, it is not idempotent and not friendly
to its callers, like fq_codel_dequeue().
Let's make it idempotent to ease qdisc_tree_reduce_backlog() callers'
life. Also change other list_del()'s to list_del_init() just to be
extra safe.
Reported-by: Gerrard Tai <gerrard.tai@starlabs.sg>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20250403211033.166059-3-xiyou.wangcong@gmail.com
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
(backported from commit df008598b3a00be02a8051fde89ca0fbc416bd55)
[ijwhitfield: Adjusted context due to missing commit:
67c9e6270f30 ("net: sched: Protect Qdisc::bstats with u64_stats")]
CVE-2025-37798
Signed-off-by: Ian Whitfield <ian.whitfield@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Acked-by: Edoardo Canepa <edoardo.canepa@canonical.com>
Signed-off-by: Mehmet Basaran <mehmet.basaran@canonical.com>
| -rw-r--r-- | net/sched/sch_drr.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index 80a88e208d2b..986169daa8a9 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c @@ -106,6 +106,7 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid, if (cl == NULL) return -ENOBUFS; + INIT_LIST_HEAD(&cl->alist); cl->common.classid = classid; cl->quantum = quantum; cl->qdisc = qdisc_create_dflt(sch->dev_queue, @@ -230,7 +231,7 @@ static void drr_qlen_notify(struct Qdisc *csh, unsigned long arg) { struct drr_class *cl = (struct drr_class *)arg; - list_del(&cl->alist); + list_del_init(&cl->alist); } static int drr_dump_class(struct Qdisc *sch, unsigned long arg, @@ -399,7 +400,7 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch) if (unlikely(skb == NULL)) goto out; if (cl->qdisc->q.qlen == 0) - list_del(&cl->alist); + list_del_init(&cl->alist); bstats_update(&cl->bstats, skb); qdisc_bstats_update(sch, skb); @@ -440,7 +441,7 @@ static void drr_reset_qdisc(struct Qdisc *sch) for (i = 0; i < q->clhash.hashsize; i++) { hlist_for_each_entry(cl, &q->clhash.hash[i], common.hnode) { if (cl->qdisc->q.qlen) - list_del(&cl->alist); + list_del_init(&cl->alist); qdisc_reset(cl->qdisc); } } |
