blk-mq: Fix a use-after-free
PATCH 1/1 blk-mq: Fix a use-after-free
Since the tag set structure can be embedded in a structure that is freed before the last queue put occurs (e.g. the SCSI host structure), the block layer must not access the tag set after the SCSI host structure has been freed. This patch avoids that the following kernel oops is triggered with memory poisoning enabled:
general protection fault: 0000 [#1] SMP RAX: 0000000000000000 RBX: 6b6b6b6b6b6b6b6b RCX: 0000000000000000 Call Trace: [<ffffffff8109a7c4>] lock_acquire+0xc4/0x270 [<ffffffff814ce111>] mutex_lock_nested+0x61/0x380 [<ffffffff812575f0>] blk_mq_free_queue+0x30/0x180 [<ffffffff8124d654>] blk_release_queue+0x84/0xd0 [<ffffffff8126c29b>] kobject_cleanup+0x7b/0x1a0 [<ffffffff8126c140>] kobject_put+0x30/0x70 [<ffffffff81245895>] blk_put_queue+0x15/0x20 [<ffffffff8125c409>] disk_release+0x99/0xd0 [<ffffffff8133d056>] device_release+0x36/0xb0 [<ffffffff8126c29b>] kobject_cleanup+0x7b/0x1a0 [<ffffffff8126c140>] kobject_put+0x30/0x70 [<ffffffff8125a78a>] put_disk+0x1a/0x20 [<ffffffff811d4cb5>] __blkdev_put+0x135/0x1b0 [<ffffffff811d56a0>] blkdev_put+0x50/0x160 [<ffffffff81199eb4>] kill_block_super+0x44/0x70 [<ffffffff8119a2a4>] deactivate_locked_super+0x44/0x60 [<ffffffff8119a87e>] deactivate_super+0x4e/0x70 [<ffffffff811b9833>] cleanup_mnt+0x43/0x90 [<ffffffff811b98d2>] __cleanup_mnt+0x12/0x20 [<ffffffff8107252c>] task_work_run+0xac/0xe0 [<ffffffff81002c01>] do_notify_resume+0x61/0xa0 [<ffffffff814d2c58>] int_signal+0x12/0x17
Signed-off-by Bart Van Assche <[email protected]>
Cc Christoph Hellwig <[email protected]>
Cc Robert Elliott <[email protected]>
Cc Ming Lei <[email protected]>
Cc <[email protected]> # v3.12+
--- block/blk-core.c | 3 +++ block/blk-sysfs.c | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-)
block/blk-core.c +3 -0
@@ -525,6 +525,9 @@ void blk_cleanup_queue(struct request_queue *q)del_timer_sync (&q->backing_dev_info.laptop_mode_wb_timer);blk_sync_queue (q); +if (q->mq_ops) +blk_mq_free_queue (q); +spin_lock_irq (lock);if (q->queue_lock != &q->__queue_lock) q->queue_lock = &q->__queue_lock;
block/blk-sysfs.c +1 -3
@@ -517,9 +517,7 @@ static void blk_release_queue(struct kobject *kobj)if (q->queue_tags)__blk_queue_free_tags (q); -if (q->mq_ops) -blk_mq_free_queue (q); -else +if (!q->mq_ops)blk_free_flush_queue (q->fq);blk_trace_shutdown (q);
Signature · 1 line
1.8.4.5