qdisc_reset() should always be called with qdisc spinlock
and with BH disabled, otherwise qdisc ->reset() could race
with TX BH.

Fixes: 7bbde83b1860 ("net: sched: drop qdisc_reset from dev_graft_qdisc")
Reported-by: Jakub Kicinski <jakub.kicin...@netronome.com>
Cc: John Fastabend <john.fastab...@gmail.com>
Signed-off-by: Cong Wang <xiyou.wangc...@gmail.com>
---
 net/sched/sch_generic.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 10aaa3b615ce..00ddb5f8f430 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -1097,8 +1097,11 @@ static void dev_qdisc_reset(struct net_device *dev,
 {
        struct Qdisc *qdisc = dev_queue->qdisc_sleeping;
 
-       if (qdisc)
+       if (qdisc) {
+               spin_lock_bh(qdisc_lock(qdisc));
                qdisc_reset(qdisc);
+               spin_unlock_bh(qdisc_lock(qdisc));
+       }
 }
 
 /**
-- 
2.13.0

Reply via email to