megasas_init_firmware() called megasas_reset_frames() without first
aborting in-flight SCSI requests. This destroyed their scatter-gather
lists (setting the AddressSpace pointer to NULL) while the requests were
still active. A subsequent MFI_IDB abort would then dereference the NULL
AddressSpace in dma_aio_cancel().
Abort all commands before resetting frames, mirroring what
megasas_soft_reset() already does.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4092
Cc: qemu-stable@nongnu.org
Signed-off-by: Bin Guo <guobin@linux.alibaba.com>
---
hw/scsi/megasas.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 9e712721f8..e9758ddb90 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -641,6 +641,7 @@ static int megasas_init_firmware(MegasasState *s, MegasasCmd *cmd)
struct mfi_init_qinfo *initq = NULL;
uint32_t flags;
int ret = MFI_STAT_OK;
+ int i;
if (s->reply_queue_pa) {
trace_megasas_initq_mapped(s->reply_queue_pa);
@@ -684,6 +685,9 @@ static int megasas_init_firmware(MegasasState *s, MegasasCmd *cmd)
trace_megasas_init_queue((unsigned long)s->reply_queue_pa,
s->reply_queue_len, s->reply_queue_head,
s->reply_queue_tail, flags);
+ for (i = 0; i < s->fw_cmds; i++) {
+ megasas_abort_command(&s->frames[i]);
+ }
megasas_reset_frames(s);
s->fw_state = MFI_FWSTATE_OPERATIONAL;
out:
--
2.50.1 (Apple Git-155)