Re: [PATCH v2] nvmet: pci-epf: fix use-after-free in nvmet_pci_epf_exec_iod_work()

Damien Le Moal <[email protected]>
Newsgroups org.infradead.lists.linux-nvme
Organization Western Digital Research
Message-ID <[email protected]>
On 7/14/26 13:00, Shin'ichiro Kawasaki wrote:
> nvmet_pci_epf_exec_iod_work() submits an I/O command with req->execute()
> and then waits for the command to complete and transfers the data back
> to the host. This wait is not needed for commands that do not transfer
> data from the device to the host. To decide whether that wait is needed,
> it reads iod->data_len and iod->dma_dir after calling req->execute().
> 
> However, once req->execute() is called, the command may complete
> asynchronously on another CPU. For commands that do not require a
> device-to-host data transfer, nvmet_pci_epf_queue_response() calls
> nvmet_pci_epf_complete_iod() directly, which can free the iod before it
> reads iod->data_len and iod->dma_dir, resulting in the KFENCE use-after-
> free:
> 
>  BUG: KFENCE: use-after-free read in nvmet_pci_epf_exec_iod_work+0x288/0x798 [nvmet_pci_epf]
> 
>  Use-after-free read at 0x00000000fdfa6d03 (in kfence-#63):
>   nvmet_pci_epf_exec_iod_work+0x288/0x798 [nvmet_pci_epf]
>   process_one_work+0x15c/0x4f0
>   worker_thread+0x18c/0x30c
>   kthread+0x130/0x140
>   ret_from_fork+0x10/0x20
> 
>  kfence-#63: 0x00000000e3de0e71-0x00000000c938ad62, size=712, cache=kmalloc-1k
> 
>  allocated by task 10 on cpu 0 at 73.995480s (0.005122s ago):
>   mempool_kmalloc+0x1c/0x28
>   mempool_alloc_noprof+0x40/0x9c
>   nvmet_pci_epf_poll_sqs_work+0xd4/0x344 [nvmet_pci_epf]
>   process_one_work+0x15c/0x4f0
>   worker_thread+0x18c/0x30c
>   kthread+0x130/0x140
>   ret_from_fork+0x10/0x20
> 
>  freed by task 131 on cpu 3 at 73.995521s (0.008385s ago):
>   mempool_kfree+0x10/0x20
>   mempool_free+0x44/0x64
>   nvmet_pci_epf_free_iod+0x88/0x98 [nvmet_pci_epf]
>   nvmet_pci_epf_cq_work+0xfc/0x280 [nvmet_pci_epf]
>   process_one_work+0x15c/0x4f0
>   worker_thread+0x18c/0x30c
>   kthread+0x130/0x140
>   ret_from_fork+0x10/0x20
> 
> Fix this by referring to iod->data_len and iod->dma_dir before calling
> req->execute(). The remaining iod accesses such as iod->status are only
> reached on the device-to-host read path. In this case,
> nvmet_pci_epf_queue_response() signals iod->done instead of freeing the
> iod, so the iod stays valid.
> 
> Fixes: 0faa0fe6f90e ("nvmet: New NVMe PCI endpoint function target driver")
> Cc: [email protected]
> Signed-off-by: Shin'ichiro Kawasaki <[email protected]>

Looks good to me.

Reviewed-by: Damien Le Moal <[email protected]>


-- 
Damien Le Moal
Western Digital Research
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.