From 9aed1bd79531d91513cd16ed90872e4349425acc Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 17 Apr 2015 23:50:48 -0400 Subject: [PATCH 1/2] block: blk-mq: fix race between timeout and CPU hotplug Firstly during CPU hotplug, even queue is freezed, timeout handler still may come and access hctx->tags, which may cause use after free, so this patch deactivates timeout handler inside CPU hotplug notifier. Secondly, tags can be shared by more than one queues, so we have to check if the hctx has been disabled, otherwise still use-after-free on tags can be triggered. Cc: Reported-by: Dongsu Park Signed-off-by: Ming Lei --- block/blk-mq.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 67f01a0..58a3b4c 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -677,8 +677,11 @@ static void blk_mq_rq_timer(unsigned long priv) data.next = blk_rq_timeout(round_jiffies_up(data.next)); mod_timer(&q->timeout, data.next); } else { - queue_for_each_hw_ctx(q, hctx, i) - blk_mq_tag_idle(hctx); + queue_for_each_hw_ctx(q, hctx, i) { + /* the hctx may be disabled, so we have to check here */ + if (hctx->tags) + blk_mq_tag_idle(hctx); + } } } @@ -2085,9 +2088,13 @@ static int blk_mq_queue_reinit_notify(struct notifier_block *nb, */ list_for_each_entry(q, &all_q_list, all_q_node) blk_mq_freeze_queue_start(q); - list_for_each_entry(q, &all_q_list, all_q_node) + list_for_each_entry(q, &all_q_list, all_q_node) { blk_mq_freeze_queue_wait(q); + /* deactivate timeout handler */ + del_timer_sync(&q->timeout); + } + list_for_each_entry(q, &all_q_list, all_q_node) blk_mq_queue_reinit(q); -- 1.9.1