In the Linux kernel, the following vulnerability has been resolved:
blk-iocost: use spinlockirqsave in adjustinuseandcalccost
adjustinuseandcalccost() use spinlockirq() and IRQ will be enabled when unlock. DEADLOCK might happen if we have held other locks and disabled IRQ before invoking it.
Fix it by using spinlockirqsave() instead, which can keep IRQ state consistent with before when unlock.
================================ WARNING: inconsistent lock state 5.10.0-02758-g8e5f91fd772f #26 Not tainted
inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage. kworker/2:3/388 [HC0[0]:SC0[0]:HE0:SE1] takes: ffff888118c00c28 (&bfqd->lock){?.-.}-{2:2}, at: spinlockirq ffff888118c00c28 (&bfqd->lock){?.-.}-{2:2}, at: bfqbiomerge+0x141/0x390 {IN-HARDIRQ-W} state was registered at: _lockacquire+0x3d7/0x1070 lockacquire+0x197/0x4a0 _rawspinlockirqsave _rawspinlockirqsave+0x3b/0x60 bfqidleslicetimerbody bfqidleslicetimer+0x53/0x1d0 _runhrtimer+0x477/0xa70 _hrtimerrunqueues+0x1c6/0x2d0 hrtimerinterrupt+0x302/0x9e0 localapictimerinterrupt _sysvecapictimerinterrupt+0xfd/0x420 runsysveconirqstackcond sysvecapictimerinterrupt+0x46/0xa0 asmsysvecapictimerinterrupt+0x12/0x20 irq event stamp: 837522 hardirqs last enabled at (837521): [<ffffffff84b9419d>] _rawspinunlockirqrestore hardirqs last enabled at (837521): [<ffffffff84b9419d>] _rawspinunlockirqrestore+0x3d/0x40 hardirqs last disabled at (837522): [<ffffffff84b93fa3>] _rawspinlockirq hardirqs last disabled at (837522): [<ffffffff84b93fa3>] rawspinlockirq+0x43/0x50 softirqs last enabled at (835852): [<ffffffff84e00558>] _dosoftirq+0x558/0x8ec softirqs last disabled at (835845): [<ffffffff84c010ff>] asmcallirqonstack+0xf/0x20
other info that might help us debug this: Possible unsafe locking scenario:
CPU0
----
lock(&bfqd->lock);
<Interrupt>
lock(&bfqd->lock);
* DEADLOCK *
3 locks held by kworker/2:3/388: #0: ffff888107af0f38 ((wqcompletion)kthrotld){+.+.}-{0:0}, at: processonework+0x742/0x13f0 #1: ffff8881176bfdd8 ((workcompletion)(&td->dispatchwork)){+.+.}-{0:0}, at: processonework+0x777/0x13f0 #2: ffff888118c00c28 (&bfqd->lock){?.-.}-{2:2}, at: spinlockirq #2: ffff888118c00c28 (&bfqd->lock){?.-.}-{2:2}, at: bfqbio_merge+0x141/0x390
stack backtrace: CPU: 2 PID: 388 Comm: kworker/2:3 Not tainted 5.10.0-02758-g8e5f91fd772f #26 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014 Workqueue: kthrotld blkthrotldispatchworkfn Call Trace: _dumpstack lib/dumpstack.c:77 [inline] dumpstack+0x107/0x167 printusagebug validstate marklockirq.cold+0x32/0x3a marklock+0x693/0xbc0 markheldlocks+0x9e/0xe0 _tracehardirqsoncaller lockdephardirqsonprepare.part.0+0x151/0x360 tracehardirqson+0x5b/0x180 _rawspinunlockirq _rawspinunlockirq+0x24/0x40 spinunlockirq adjustinuseandcalccost+0x4fb/0x970 iocrqosmerge+0x277/0x740 _rqqosmerge+0x62/0xb0 rqqosmerge bioattemptbackmerge+0x12c/0x4a0 blkmqschedtrymerge+0x1b6/0x4d0 bfqbiomerge+0x24a/0x390 _blkmqschedbiomerge+0xa6/0x460 blkmqschedbiomerge blkmqsubmitbio+0x2e7/0x1ee0 _submitbionoacctmq+0x175/0x3b0 submitbionoacct+0x1fb/0x270 blkthrotldispatchworkfn+0x1ef/0x2b0 processonework+0x83e/0x13f0 processscheduledworks workerthread+0x7e3/0xd80 kthread+0x353/0x470 retfrom_fork+0x1f/0x30