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
This commit is contained in:
Peter Grehan 2020-06-26 08:20:38 +00:00
parent 1649caabbb
commit 71ab6f9708
2 changed files with 12 additions and 8 deletions

View File

@ -1843,6 +1843,9 @@ pci_xhci_handle_transfer(struct pci_xhci_softc *sc,
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 @@ pci_xhci_handle_transfer(struct pci_xhci_softc *sc,
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)

View File

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