On Tue, 2017-08-29 at 11:13 -0700, Cong Wang wrote: > On Tue, Aug 29, 2017 at 11:09 AM, Eric Dumazet <eric.duma...@gmail.com> wrote: > > On Tue, 2017-08-29 at 20:58 +0300, Nikolay Aleksandrov wrote: > >> The commit below added a call to the ->destroy() callback for all qdiscs > >> which failed in their ->init(), but some were not prepared for such > >> change and can't handle partially initialized qdisc. HTB is one of them > >> and if any error occurs before the qdisc watchdog timer and qdisc work are > >> initialized then we can hit either a null ptr deref (timer->base) when > >> canceling in ->destroy or lockdep error info about trying to register > >> a non-static key and a stack dump. So to fix these two move the watchdog > >> timer and workqueue init before anything that can err out. > >> To reproduce userspace needs to send broken htb qdisc create request, > >> tested with a modified tc (q_htb.c). > > > >> Note that probably this bug goes further back because the default qdisc > >> handling always calls ->destroy on init failure too. > >> > >> Fixes: 87b60cfacf9f ("net_sched: fix error recovery at qdisc creation") > >> Signed-off-by: Nikolay Aleksandrov <niko...@cumulusnetworks.com> > >> --- > >> Always calling qdisc destroy on init failure in the default qdisc handling > >> was added in commit 0fbbeb1ba43b. I'm not sure if I should include that > >> one as fixes tag. > > > > Well, we probably need to audit init/destroy not only in net/sched, but > > other parts of networking stack. > > > > What about the qdisc_skb_head_init(&q->direct_queue) call ? > > It just zero the pointers: > > static inline void qdisc_skb_head_init(struct qdisc_skb_head *qh) > { > qh->head = NULL; > qh->tail = NULL; > qh->qlen = 0; > } > > And qdisc is already kzalloc()'ed.
Yeah, I was looking at some old tree, not having the __qdisc_reset_queue() yet.