On Wed, 09 Sep 2026 11:11:44 +0800, Stanley Jhu <[email protected]> wrote:
> In the UFS emulator, outstanding SCSI requests are dispatched asynchronously
> to the block layer via scsi_req_enqueue(). When requests are cleared or
> aborted (e.g. during HCE reset or TMR aborts), ufs_clear_req() releases the
> scatter-gather list without cancelling the pending SCSIRequest. If an
> asynchronous AIO callback completes afterwards, ufs_scsi_command_complete()
> dereferences stale or freed request state, resulting in use-after-free
> hazards.
ufs_clear_req() currently releases request resources; it is not responsible
for cancelling in-flight SCSI requests. Its existing callers ensure that
the request is no longer in flight, so the current code does not have the
UAF described here. Please describe this as preparation for TMF support.
>
>
> diff --git a/hw/ufs/lu.c b/hw/ufs/lu.c
> index bdb1650851..a62ebb51fd 100644
> --- a/hw/ufs/lu.c
> +++ b/hw/ufs/lu.c
> @@ -173,6 +173,12 @@ static void ufs_scsi_command_complete(SCSIRequest
> *scsi_req, size_t resid)
> int16_t status = scsi_req->status;
> uint32_t transfered_len = scsi_req->cmd.xfer - resid;
>
> + if (!req) {
> + return;
> + }
Can we use assert(req != NULL) here? We only clear hba_private in the
completion and cancellation callbacks, so req should not be NULL here.
If that invariant is broken, it would be better to catch the bug with
an assertion than to silently return.
> @@ -190,6 +196,11 @@ static void ufs_scsi_command_complete(SCSIRequest
> *scsi_req, size_t resid)
>
> static void ufs_scsi_command_cancelled(SCSIRequest *scsi_req)
> {
> + UfsRequest *req = scsi_req->hba_private;
> +
> + if (req) {
Same here: can we use assert(req != NULL)?
--
Jeuk Kim <[email protected]>