After issuing a SCSI command the SCSI layer can call the SCSIBusInfo .cancel callback which resets both current_req and current_dev to NULL. If any data is left in the transfer buffer (async_len != 0) then the next TI (Transfer Information) command will attempt to reference the NULL pointer causing a segfault.
Buglink: https://bugs.launchpad.net/qemu/+bug/1910723 Buglink: https://bugs.launchpad.net/qemu/+bug/1909247 Signed-off-by: Mark Cave-Ayland <[email protected]> --- hw/scsi/esp.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index ae362c9dfb..7216903ce0 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -524,7 +524,9 @@ static void do_dma_pdma_cb(ESPState *s) } if (s->async_len == 0) { - scsi_req_continue(s->current_req); + if (s->current_req) { + scsi_req_continue(s->current_req); + } return; } @@ -674,14 +676,16 @@ static void esp_do_dma(ESPState *s) s->ti_size -= len; } if (s->async_len == 0) { - scsi_req_continue(s->current_req); - /* - * If there is still data to be read from the device then - * complete the DMA operation immediately. Otherwise defer - * until the scsi layer has completed. - */ - if (to_device || esp_get_tc(s) != 0 || s->ti_size == 0) { - return; + if (s->current_req) { + scsi_req_continue(s->current_req); + /* + * If there is still data to be read from the device then + * complete the DMA operation immediately. Otherwise defer + * until the scsi layer has completed. + */ + if (to_device || esp_get_tc(s) != 0 || s->ti_size == 0) { + return; + } } } @@ -744,10 +748,12 @@ static void esp_do_nodma(ESPState *s) } if (s->async_len == 0) { - scsi_req_continue(s->current_req); + if (s->current_req) { + scsi_req_continue(s->current_req); - if (to_device || s->ti_size == 0) { - return; + if (to_device || s->ti_size == 0) { + return; + } } } -- 2.20.1
