[PATCH 1/1] nvme: correctly account for namespace head reference counter
Nilay Shroff
nilay at linux.ibm.com
Tue Jun 24 06:30:39 PDT 2025
On 6/23/25 1:48 PM, Daniel Wagner wrote:
> Hi Nilay,
>
> On Fri, Jun 20, 2025 at 01:32:43PM +0530, Nilay Shroff wrote:
>> --- a/drivers/nvme/host/core.c
>> +++ b/drivers/nvme/host/core.c
>> @@ -4089,6 +4089,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
>> struct nvme_ns *ns;
>> struct gendisk *disk;
>> int node = ctrl->numa_node;
>> + bool last_path = false;
>>
>> ns = kzalloc_node(sizeof(*ns), GFP_KERNEL, node);
>> if (!ns)
>> @@ -4181,9 +4182,13 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
>> out_unlink_ns:
>> mutex_lock(&ctrl->subsys->lock);
>> list_del_rcu(&ns->siblings);
>> - if (list_empty(&ns->head->list))
>> + if (list_empty(&ns->head->list)) {
>> list_del_init(&ns->head->entry);
>> + last_path = true;
>> + }
>> mutex_unlock(&ctrl->subsys->lock);
>> + if (last_path)
>> + nvme_put_ns_head(ns->head);
>> nvme_put_ns_head(ns->head);
>
> Could the put moved in front of 'goto out_unlink_ns'?
I believe you would want to move the second nvme_put_ns_head()
above as the first statement under out_unlink_ns label as shown
below:
out_unlink_ns:
nvme_put_ns_head(ns->head);
mutex_lock(&ctrl->subsys->lock);
list_del_rcu(&ns->siblings);
if (list_empty(&ns->head->list)) {
list_del_init(&ns->head->entry);
last_path = true;
}
mutex_unlock(&ctrl->subsys->lock);
if (last_path)
nvme_put_ns_head(ns->head);
If that's the case, and this is indeed the last reference to ns->head,
then nvme_put_ns_head() could potentially free the ns->head object.
If that happens, any access to ns->head afterward — such as ns->head->list
— would result in a use-after-free and potentially trigger a kernel oops,
correct?
Thanks,
--Nilay
More information about the Linux-nvme
mailing list