In the Linux kernel, the following vulnerability has been resolved:
net: enetc: avoid deadlock in enetctxonestep_tstamp()
This lockdep splat says it better than I could:
================================ WARNING: inconsistent lock state
inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage. kworker/1:3/179 [HC0[0]:SC0[0]:HE1:SE1] takes: ffff3ec4036ce098 (xmitETHER#2){+.?.}-{3:3}, at: netiffreezequeues+0x5c/0xc0 {IN-SOFTIRQ-W} state was registered at: rawspinlock+0x5c/0xc0 schdirectxmit+0x148/0x37c devqueuexmit+0x528/0x111c ip6finishoutput2+0x5ec/0xb7c ip6finishoutput+0x240/0x3f0 ip6output+0x78/0x360 ndiscsendskb+0x33c/0x85c ndiscsendrs+0x54/0x12c addrconfrstimer+0x154/0x260 calltimerfn+0xb8/0x3a0 _runtimers.part.0+0x214/0x26c runtimersoftirq+0x3c/0x74 _dosoftirq+0x14c/0x5d8 dosoftirq+0x10/0x20 callonirqstack+0x2c/0x5c dosoftirqownstack+0x1c/0x30 irqexitrcu+0x168/0x1a0 irqexitrcu+0x10/0x40 el1interrupt+0x38/0x64 irq event stamp: 7825 hardirqs last enabled at (7825): [<ffffdf1f7200cae4>] exittokernelmode+0x34/0x130 hardirqs last disabled at (7823): [<ffffdf1f708105f0>] _dosoftirq+0x550/0x5d8 softirqs last enabled at (7824): [<ffffdf1f7081050c>] _dosoftirq+0x46c/0x5d8 softirqs last disabled at (7811): [<ffffdf1f708166e0>] _do_softirq+0x10/0x20
other info that might help us debug this: Possible unsafe locking scenario:
CPU0
----
lock(xmitETHER#2); <Interrupt> lock(xmitETHER#2);
* DEADLOCK *
3 locks held by kworker/1:3/179: #0: ffff3ec400004748 ((wqcompletion)events){+.+.}-{0:0}, at: processonework+0x1f4/0x6c0 #1: ffff80000a0bbdc8 ((workcompletion)(&priv->txonesteptstamp)){+.+.}-{0:0}, at: processonework+0x1f4/0x6c0 #2: ffff3ec4036cd438 (&dev->txgloballock){+.+.}-{3:3}, at: netiftxlock+0x1c/0x34
Workqueue: events enetctxonesteptstamp Call trace: printusagebug.part.0+0x208/0x22c marklock+0x7f0/0x8b0 _lockacquire+0x7c4/0x1ce0 lockacquire.part.0+0xe0/0x220 lockacquire+0x68/0x84 rawspinlock+0x5c/0xc0 netiffreezequeues+0x5c/0xc0 netiftxlock+0x24/0x34 enetctxonesteptstamp+0x20/0x100 processonework+0x28c/0x6c0 worker_thread+0x74/0x450 kthread+0x118/0x11c
but I'll say it anyway: the enetctxonesteptstamp() work item runs in process context, therefore with softirqs enabled (i.o.w., it can be interrupted by a softirq). If we hold the netiftxlock() when there is an interrupt, and the NETTX softirq then gets scheduled, this will take the netiftxlock() a second time and deadlock the kernel.
To solve this, use netiftxlock_bh(), which blocks softirqs from running.