diff mbox series

[4/4] esp: always check current_req is not NULL before use in DMA callbacks

Message ID 20210316233024.13560-5-mark.cave-ayland@ilande.co.uk
State New
Headers show
Series esp: fix asserts/segfaults discovered by fuzzer | expand

Commit Message

Mark Cave-Ayland March 16, 2021, 11:30 p.m. UTC
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 <mark.cave-ayland@ilande.co.uk>
---
 hw/scsi/esp.c | 30 ++++++++++++++++++------------
 1 file changed, 18 insertions(+), 12 deletions(-)
diff mbox series

Patch

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;
+            }
         }
     }