On Tue, 2017-08-29 at 11:09 -0700, Eric Dumazet 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 ? > > I am surprised you do not crash in __skb_queue_purge(&q->direct_queue);
Oh, this is because skb_peek() is happy if queue->next is NULL.