]> git.itanic.dy.fi Git - linux-stable/commitdiff
nvmet: fix a use-after-free
authorBart Van Assche <bvanassche@acm.org>
Fri, 12 Aug 2022 21:03:17 +0000 (14:03 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 28 Sep 2022 09:02:52 +0000 (11:02 +0200)
[ Upstream commit 6a02a61e81c231cc5c680c5dbf8665275147ac52 ]

Fix the following use-after-free complaint triggered by blktests nvme/004:

BUG: KASAN: user-memory-access in blk_mq_complete_request_remote+0xac/0x350
Read of size 4 at addr 0000607bd1835943 by task kworker/13:1/460
Workqueue: nvmet-wq nvme_loop_execute_work [nvme_loop]
Call Trace:
 show_stack+0x52/0x58
 dump_stack_lvl+0x49/0x5e
 print_report.cold+0x36/0x1e2
 kasan_report+0xb9/0xf0
 __asan_load4+0x6b/0x80
 blk_mq_complete_request_remote+0xac/0x350
 nvme_loop_queue_response+0x1df/0x275 [nvme_loop]
 __nvmet_req_complete+0x132/0x4f0 [nvmet]
 nvmet_req_complete+0x15/0x40 [nvmet]
 nvmet_execute_io_connect+0x18a/0x1f0 [nvmet]
 nvme_loop_execute_work+0x20/0x30 [nvme_loop]
 process_one_work+0x56e/0xa70
 worker_thread+0x2d1/0x640
 kthread+0x183/0x1c0
 ret_from_fork+0x1f/0x30

Cc: stable@vger.kernel.org
Fixes: a07b4970f464 ("nvmet: add a generic NVMe target")
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/nvme/target/core.c

index 1a35d73c39c35c59ef46da05f4e891a3bd8b2b9e..80b5aae1bdc9b0b6005b7f326e5083fbda1f3efe 100644 (file)
@@ -504,6 +504,7 @@ static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
 {
        u32 old_sqhd, new_sqhd;
        u16 sqhd;
+       struct nvmet_ns *ns = req->ns;
 
        if (status)
                nvmet_set_status(req, status);
@@ -520,9 +521,9 @@ static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
        req->rsp->sq_id = cpu_to_le16(req->sq->qid);
        req->rsp->command_id = req->cmd->common.command_id;
 
-       if (req->ns)
-               nvmet_put_namespace(req->ns);
        req->ops->queue_response(req);
+       if (ns)
+               nvmet_put_namespace(ns);
 }
 
 void nvmet_req_complete(struct nvmet_req *req, u16 status)