2015-06-04 14:25:20

by Ming Lei

[permalink] [raw]
Subject: [PATCH v1] blk-mq: free hctx->ctxs in queue's release handler

Now blk_cleanup_queue() can be called before calling
del_gendisk()[1], inside which hctx->ctxs is touched
from blk_mq_unregister_hctx(), but the variable has
been freed by blk_cleanup_queue() at that time.

So this patch moves freeing of hctx->ctxs into queue's
release handler for fixing the oops reported by Stefan.

[1], 6cd18e711dd8075 (block: destroy bdi before blockdev is
unregistered)

Reported-by: Stefan Seyfried <[email protected]>
Cc: NeilBrown <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Cc: [email protected] (v4.0)
Signed-off-by: Ming Lei <[email protected]>
---
V1:
- fix commit log

block/blk-mq.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/block/blk-mq.c b/block/blk-mq.c
index e68b71b..594eea0 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1600,6 +1600,7 @@ static int blk_mq_hctx_notify(void *data, unsigned long action,
return NOTIFY_OK;
}

+/* hctx->ctxs will be freed in queue's release handler */
static void blk_mq_exit_hctx(struct request_queue *q,
struct blk_mq_tag_set *set,
struct blk_mq_hw_ctx *hctx, unsigned int hctx_idx)
@@ -1618,7 +1619,6 @@ static void blk_mq_exit_hctx(struct request_queue *q,

blk_mq_unregister_cpu_notifier(&hctx->cpu_notifier);
blk_free_flush_queue(hctx->fq);
- kfree(hctx->ctxs);
blk_mq_free_bitmap(&hctx->ctx_map);
}

@@ -1891,8 +1891,12 @@ void blk_mq_release(struct request_queue *q)
unsigned int i;

/* hctx kobj stays in hctx */
- queue_for_each_hw_ctx(q, hctx, i)
+ queue_for_each_hw_ctx(q, hctx, i) {
+ if (!hctx)
+ continue;
+ kfree(hctx->ctxs);
kfree(hctx);
+ }

kfree(q->queue_hw_ctx);

--
1.9.1


2015-06-09 09:28:53

by Ming Lei

[permalink] [raw]
Subject: Re: [PATCH v1] blk-mq: free hctx->ctxs in queue's release handler

Hi Jens,

Could you consider this patch for v4.1?

http://marc.info/?l=linux-kernel&m=143342792910832&w=2

The issue is one obvious use-after-free and can be reproduced easily
via 'sudo modprobe loop;sleep 1;sudo rmmod loop' on linus tree:

http://kernel.ubuntu.com/~ming/block/bug/4.1-rc7-blk-mq-oops.txt


Thanks,
Ming Lei

2015-06-09 21:32:22

by Jens Axboe

[permalink] [raw]
Subject: Re: [PATCH v1] blk-mq: free hctx->ctxs in queue's release handler

On 06/09/2015 03:28 AM, Ming Lei wrote:
> Hi Jens,
>
> Could you consider this patch for v4.1?
>
> http://marc.info/?l=linux-kernel&m=143342792910832&w=2
>
> The issue is one obvious use-after-free and can be reproduced easily
> via 'sudo modprobe loop;sleep 1;sudo rmmod loop' on linus tree:
>
> http://kernel.ubuntu.com/~ming/block/bug/4.1-rc7-blk-mq-oops.txt

I'll pull it in, thanks.

--
Jens Axboe