Skip to content

Commit 2b15593

Browse files
committed
net_sched: sch_ets: implement lockless ets_dump()
jira VULN-136263 cve-pre CVE-2025-38684 commit-author Eric Dumazet <edumazet@google.com> commit c5f1dde Instead of relying on RTNL, ets_dump() can use READ_ONCE() annotations, paired with WRITE_ONCE() ones in ets_change(). Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net> (cherry picked from commit c5f1dde) Signed-off-by: Brett Mastbergen <bmastbergen@ciq.com>
1 parent eccd121 commit 2b15593

File tree

1 file changed

+14
-11
lines changed

1 file changed

+14
-11
lines changed

net/sched/sch_ets.c

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
658658

659659
sch_tree_lock(sch);
660660

661-
q->nbands = nbands;
661+
WRITE_ONCE(q->nbands, nbands);
662662
for (i = nstrict; i < q->nstrict; i++) {
663663
if (q->classes[i].qdisc->q.qlen) {
664664
list_add_tail(&q->classes[i].alist, &q->active);
@@ -670,11 +670,11 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
670670
list_del_init(&q->classes[i].alist);
671671
qdisc_purge_queue(q->classes[i].qdisc);
672672
}
673-
q->nstrict = nstrict;
673+
WRITE_ONCE(q->nstrict, nstrict);
674674
memcpy(q->prio2band, priomap, sizeof(priomap));
675675

676676
for (i = 0; i < q->nbands; i++)
677-
q->classes[i].quantum = quanta[i];
677+
WRITE_ONCE(q->classes[i].quantum, quanta[i]);
678678

679679
for (i = oldbands; i < q->nbands; i++) {
680680
q->classes[i].qdisc = queues[i];
@@ -688,7 +688,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
688688
for (i = q->nbands; i < oldbands; i++) {
689689
qdisc_put(q->classes[i].qdisc);
690690
q->classes[i].qdisc = NULL;
691-
q->classes[i].quantum = 0;
691+
WRITE_ONCE(q->classes[i].quantum, 0);
692692
q->classes[i].deficit = 0;
693693
gnet_stats_basic_sync_init(&q->classes[i].bstats);
694694
memset(&q->classes[i].qstats, 0, sizeof(q->classes[i].qstats));
@@ -747,6 +747,7 @@ static int ets_qdisc_dump(struct Qdisc *sch, struct sk_buff *skb)
747747
struct ets_sched *q = qdisc_priv(sch);
748748
struct nlattr *opts;
749749
struct nlattr *nest;
750+
u8 nbands, nstrict;
750751
int band;
751752
int prio;
752753
int err;
@@ -759,21 +760,22 @@ static int ets_qdisc_dump(struct Qdisc *sch, struct sk_buff *skb)
759760
if (!opts)
760761
goto nla_err;
761762

762-
if (nla_put_u8(skb, TCA_ETS_NBANDS, q->nbands))
763+
nbands = READ_ONCE(q->nbands);
764+
if (nla_put_u8(skb, TCA_ETS_NBANDS, nbands))
763765
goto nla_err;
764766

765-
if (q->nstrict &&
766-
nla_put_u8(skb, TCA_ETS_NSTRICT, q->nstrict))
767+
nstrict = READ_ONCE(q->nstrict);
768+
if (nstrict && nla_put_u8(skb, TCA_ETS_NSTRICT, nstrict))
767769
goto nla_err;
768770

769-
if (q->nbands > q->nstrict) {
771+
if (nbands > nstrict) {
770772
nest = nla_nest_start(skb, TCA_ETS_QUANTA);
771773
if (!nest)
772774
goto nla_err;
773775

774-
for (band = q->nstrict; band < q->nbands; band++) {
776+
for (band = nstrict; band < nbands; band++) {
775777
if (nla_put_u32(skb, TCA_ETS_QUANTA_BAND,
776-
q->classes[band].quantum))
778+
READ_ONCE(q->classes[band].quantum)))
777779
goto nla_err;
778780
}
779781

@@ -785,7 +787,8 @@ static int ets_qdisc_dump(struct Qdisc *sch, struct sk_buff *skb)
785787
goto nla_err;
786788

787789
for (prio = 0; prio <= TC_PRIO_MAX; prio++) {
788-
if (nla_put_u8(skb, TCA_ETS_PRIOMAP_BAND, q->prio2band[prio]))
790+
if (nla_put_u8(skb, TCA_ETS_PRIOMAP_BAND,
791+
READ_ONCE(q->prio2band[prio])))
789792
goto nla_err;
790793
}
791794

0 commit comments

Comments
 (0)