[PATCH] nvmet: Fix a use-after-free
Sagi Grimberg
sagi at grimberg.me
Wed Aug 17 03:17:07 PDT 2022
>>>> nvmet_req *req, u16 status)
>>>> trace_nvmet_req_complete(req);
>>>> - if (req->ns)
>>>> - nvmet_put_namespace(req->ns);
>>>> req->ops->queue_response(req);
>>>> + if (ns)
>>>> + nvmet_put_namespace(ns);
>>>
>>> Why did the put change position?
>>> I'm not exactly clear what was used-after-free here..
>>
>> Hi Sagi,
>>
>> Is my understanding correct that the NVMe target namespace owns the
>> block device `req` is associated with and hence that the namespace
>> reference count must only be dropped after dereferencing the `req`
>> pointer has finished?
>>
>> This is what I found in the NVMe target code:
>> * nvmet_put_namespace() decreases ns->ref.
>> * Dropping the last ns->ref causes nvmet_destroy_namespace() to be
>> called. That function completes ns->disable_done.
>> * nvmet_ns_disable() waits on that completion and calls
>> nvmet_ns_dev_disable().
>> * For a block device, nvmet_ns_dev_disable() calls blkdev_put().
>> * The last blkdev_put() call calls disk_release().
>> * disk_release() calls blk_put_queue().
>> * The last blk_put_queue() call calls blk_release_queue().
>> * blk_release_queue() frees struct request_queue.
>> * blk_mq_complete_request_remote() dereferences req->q.
>
> The analysis is correct, specifically for loop transport, but it is not
> the same request_queue...
>
> blk_mq_complete_request_remote references the initiator block device
> created from the namespace, but nvmet_ns_dev_disable puts the backend
> blockdev, which is a separate blockdev...
>
> Maybe I'm misunderstanding your point?
And specifically your stack trace references nvmet_execute_io_connect
which is not addressed to a namespace... This I think that the
request_queue is actually the ctrl->connect_q, which is used for
io_connect commands.
It is unclear to me how this one ended up with a use-after-free...
Maybe we have a stray io_connect command lingering after we teardown
the controller?
More information about the Linux-nvme
mailing list