Author: grehan
Date: Fri Jun 26 08:20:38 2020
New Revision: 362644
URL: https://svnweb.freebsd.org/changeset/base/362644

Log:
  Prevent calling USB backends multiple times.
  
  The TRB processing loop could potentially call a back-end twice
  with the same status transaction. While this was generally benign,
  some code paths in the tablet backend weren't set up to handle
  this case, resulting in a NULL dereference.
  
  Fix by
   - returning a STALL error when an invalid request was seen in the backend
   - skipping a call to the backend if the number of packets in a status
     transaction was zero (this code fragment was taken from the Intel ACRN
     xhci backend)
  
  PR:   246964
  Reported by:  Ali Abdallah
  Discussed with: Leon Dang (author)
  Reviewed by: jhb (#bhyve), Leon Dang
  Approved by: jhb
  Obtained from:  Intel ACRN (partially)
  MFC after: 2 weeks
  Differential Revision:        https://reviews.freebsd.org/D25228

Modified:
  head/usr.sbin/bhyve/pci_xhci.c
  head/usr.sbin/bhyve/usb_mouse.c

Modified: head/usr.sbin/bhyve/pci_xhci.c
==============================================================================
--- head/usr.sbin/bhyve/pci_xhci.c      Fri Jun 26 06:11:50 2020        
(r362643)
+++ head/usr.sbin/bhyve/pci_xhci.c      Fri Jun 26 08:20:38 2020        
(r362644)
@@ -1843,6 +1843,9 @@ retry:
 
        DPRINTF(("pci_xhci[%d]: xfer->ndata %u", __LINE__, xfer->ndata));
 
+       if (xfer->ndata <= 0)
+               goto errout;
+
        if (epid == 1) {
                err = USB_ERR_NOT_STARTED;
                if (dev->dev_ue->ue_request != NULL)
@@ -1857,6 +1860,7 @@ retry:
 
        err = USB_TO_XHCI_ERR(err);
        if ((err == XHCI_TRB_ERROR_SUCCESS) ||
+           (err == XHCI_TRB_ERROR_STALL) ||
            (err == XHCI_TRB_ERROR_SHORT_PKT)) {
                err = pci_xhci_xfer_complete(sc, xfer, slot, epid, &do_intr);
                if (err != XHCI_TRB_ERROR_SUCCESS)

Modified: head/usr.sbin/bhyve/usb_mouse.c
==============================================================================
--- head/usr.sbin/bhyve/usb_mouse.c     Fri Jun 26 06:11:50 2020        
(r362643)
+++ head/usr.sbin/bhyve/usb_mouse.c     Fri Jun 26 08:20:38 2020        
(r362644)
@@ -390,7 +390,7 @@ umouse_request(void *scarg, struct usb_data_xfer *xfer
                                 "sizeof(umouse_dev_desc) %lu",
                                 len, sizeof(umouse_dev_desc)));
                        if ((value & 0xFF) != 0) {
-                               err = USB_ERR_IOERROR;
+                               err = USB_ERR_STALLED;
                                goto done;
                        }
                        if (len > sizeof(umouse_dev_desc)) {
@@ -405,7 +405,7 @@ umouse_request(void *scarg, struct usb_data_xfer *xfer
                case UDESC_CONFIG:
                        DPRINTF(("umouse: (->UDESC_CONFIG)"));
                        if ((value & 0xFF) != 0) {
-                               err = USB_ERR_IOERROR;
+                               err = USB_ERR_STALLED;
                                goto done;
                        }
                        if (len > sizeof(umouse_confd)) {
@@ -474,7 +474,7 @@ umouse_request(void *scarg, struct usb_data_xfer *xfer
 
                default:
                        DPRINTF(("umouse: unknown(%d)->ERROR", value >> 8));
-                       err = USB_ERR_IOERROR;
+                       err = USB_ERR_STALLED;
                        goto done;
                }
                eshort = data->blen > 0;
@@ -498,7 +498,7 @@ umouse_request(void *scarg, struct usb_data_xfer *xfer
                        break;
                default:
                        DPRINTF(("umouse: IO ERROR"));
-                       err = USB_ERR_IOERROR;
+                       err = USB_ERR_STALLED;
                        goto done;
                }
                eshort = data->blen > 0;
@@ -509,7 +509,7 @@ umouse_request(void *scarg, struct usb_data_xfer *xfer
                if (index != 0) {
                        DPRINTF(("umouse get_interface, invalid index %d",
                                index));
-                       err = USB_ERR_IOERROR;
+                       err = USB_ERR_STALLED;
                        goto done;
                }
 
@@ -580,7 +580,7 @@ umouse_request(void *scarg, struct usb_data_xfer *xfer
        case UREQ(UR_SET_FEATURE, UT_WRITE_INTERFACE):
        case UREQ(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
                DPRINTF(("umouse: (UR_CLEAR_FEATURE, UT_WRITE_INTERFACE)"));
-               err = USB_ERR_IOERROR;
+               err = USB_ERR_STALLED;
                goto done;
 
        case UREQ(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
@@ -619,7 +619,7 @@ umouse_request(void *scarg, struct usb_data_xfer *xfer
                        memcpy(data->buf, &sc->um_report, len);
                        data->bdone += len;
                } else {
-                       err = USB_ERR_IOERROR;
+                       err = USB_ERR_STALLED;
                        goto done;
                }
                eshort = data->blen > 0;
@@ -661,7 +661,7 @@ umouse_request(void *scarg, struct usb_data_xfer *xfer
 
        default:
                DPRINTF(("**** umouse request unhandled"));
-               err = USB_ERR_IOERROR;
+               err = USB_ERR_STALLED;
                break;
        }
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to