From cea5aa85691d7f26b7ea995417d41a32802691b7 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 30 Aug 2022 08:38:26 +0200 Subject: usb/msd: move usb_msd_packet_complete() Change ordering to avoid adding forward declarations in following patches. Fix comment code style while being at it. No functional change. Signed-off-by: Gerd Hoffmann Message-Id: <20220830063827.813053-2-kraxel@redhat.com> --- hw/usb/dev-storage.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'hw/usb/dev-storage.c') diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 9863969..140ef2a 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -177,6 +177,20 @@ static const USBDesc desc = { .str = desc_strings, }; +static void usb_msd_packet_complete(MSDState *s) +{ + USBPacket *p = s->packet; + + /* + * Set s->packet to NULL before calling usb_packet_complete + * because another request may be issued before + * usb_packet_complete returns. + */ + trace_usb_msd_packet_complete(); + s->packet = NULL; + usb_packet_complete(&s->dev, p); +} + static void usb_msd_copy_data(MSDState *s, USBPacket *p) { uint32_t len; @@ -208,18 +222,6 @@ static void usb_msd_send_status(MSDState *s, USBPacket *p) memset(&s->csw, 0, sizeof(s->csw)); } -static void usb_msd_packet_complete(MSDState *s) -{ - USBPacket *p = s->packet; - - /* Set s->packet to NULL before calling usb_packet_complete - because another request may be issued before - usb_packet_complete returns. */ - trace_usb_msd_packet_complete(); - s->packet = NULL; - usb_packet_complete(&s->dev, p); -} - void usb_msd_transfer_data(SCSIRequest *req, uint32_t len) { MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); -- cgit v1.1 From 12b69878fc7b4b92b1bbd3959f2c3d4c717881fb Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 30 Aug 2022 08:38:27 +0200 Subject: usb/msd: add usb_msd_fatal_error() and fix guest-triggerable assert Add handler for fatal errors. Moves device into error state where it stops responding until the guest resets it. Guest can send illegal requests where scsi command and usb packet transfer directions are inconsistent. Use the new usb_msd_fatal_error() function instead of assert() in that case. Reported-by: Qiang Liu Signed-off-by: Gerd Hoffmann Tested-by: Qiang Liu Message-Id: <20220830063827.813053-3-kraxel@redhat.com> --- hw/usb/dev-storage.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'hw/usb/dev-storage.c') diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 140ef2a..e3bcffb 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -191,6 +191,23 @@ static void usb_msd_packet_complete(MSDState *s) usb_packet_complete(&s->dev, p); } +static void usb_msd_fatal_error(MSDState *s) +{ + trace_usb_msd_fatal_error(); + + if (s->packet) { + s->packet->status = USB_RET_STALL; + usb_msd_packet_complete(s); + } + + /* + * Guest messed up up device state with illegal requests. Go + * ignore any requests until the guests resets the device (and + * brings it into a known state that way). + */ + s->needs_reset = true; +} + static void usb_msd_copy_data(MSDState *s, USBPacket *p) { uint32_t len; @@ -227,7 +244,11 @@ void usb_msd_transfer_data(SCSIRequest *req, uint32_t len) MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); USBPacket *p = s->packet; - assert((s->mode == USB_MSDM_DATAOUT) == (req->cmd.mode == SCSI_XFER_TO_DEV)); + if ((s->mode == USB_MSDM_DATAOUT) != (req->cmd.mode == SCSI_XFER_TO_DEV)) { + usb_msd_fatal_error(s); + return; + } + s->scsi_len = len; s->scsi_off = 0; if (p) { @@ -317,6 +338,8 @@ void usb_msd_handle_reset(USBDevice *dev) memset(&s->csw, 0, sizeof(s->csw)); s->mode = USB_MSDM_CBW; + + s->needs_reset = false; } static void usb_msd_handle_control(USBDevice *dev, USBPacket *p, @@ -382,6 +405,11 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) SCSIDevice *scsi_dev; uint32_t len; + if (s->needs_reset) { + p->status = USB_RET_STALL; + return; + } + switch (p->pid) { case USB_TOKEN_OUT: if (devep != 2) -- cgit v1.1