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:
parent
1649caabbb
commit
71ab6f9708
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user