summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpi <mpi@openbsd.org>2014-11-07 14:06:43 +0000
committermpi <mpi@openbsd.org>2014-11-07 14:06:43 +0000
commitffa66e8462b2d0b1a0a33af4e9f8ce79da531db4 (patch)
tree1f1609d2b8a7928f288c6911b35dc10ff7ae7fa9
parentRun eap_parse on the actual message and only when the length is right (diff)
downloadwireguard-openbsd-ffa66e8462b2d0b1a0a33af4e9f8ce79da531db4.tar.xz
wireguard-openbsd-ffa66e8462b2d0b1a0a33af4e9f8ce79da531db4.zip
Prevent a race when submitting a command by using the appropriate spl
protection. Fix a panic reported by Patrick Wildt.
-rw-r--r--sys/dev/usb/xhci.c22
1 files changed, 13 insertions, 9 deletions
diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index 204bc3e190a..c774bfc8331 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xhci.c,v 1.34 2014/11/01 18:21:07 mpi Exp $ */
+/* $OpenBSD: xhci.c,v 1.35 2014/11/07 14:06:43 mpi Exp $ */
/*
* Copyright (c) 2014 Martin Pieuchot
@@ -1381,39 +1381,43 @@ int
xhci_command_submit(struct xhci_softc *sc, struct xhci_trb *trb0, int timeout)
{
struct xhci_trb *trb;
- int error = 0;
+ int s, error = 0;
KASSERT(timeout == 0 || sc->sc_cmd_trb == NULL);
trb0->trb_flags |= htole32(sc->sc_cmd_ring.toggle);
trb = xhci_ring_dequeue(sc, &sc->sc_cmd_ring, 0);
+ if (trb == NULL)
+ return (EAGAIN);
memcpy(trb, trb0, sizeof(struct xhci_trb));
usb_syncmem(&sc->sc_cmd_ring.dma, TRBOFF(sc->sc_cmd_ring, trb),
sizeof(struct xhci_trb), BUS_DMASYNC_PREWRITE);
- if (timeout)
- sc->sc_cmd_trb = trb;
-
- XDWRITE4(sc, XHCI_DOORBELL(0), 0);
-
- if (timeout == 0)
+ if (timeout == 0) {
+ XDWRITE4(sc, XHCI_DOORBELL(0), 0);
return (0);
+ }
assertwaitok();
+ s = splusb();
+ sc->sc_cmd_trb = trb;
+ XDWRITE4(sc, XHCI_DOORBELL(0), 0);
error = tsleep(&sc->sc_cmd_trb, PZERO, "xhcicmd",
(timeout*hz+999)/ 1000 + 1);
if (error) {
#ifdef XHCI_DEBUG
printf("%s: tsleep() = %d\n", __func__, error);
- printf("cmd = %d " ,XHCI_TRB_TYPE(letoh32(trb->trb_flags)));
+ printf("cmd = %d ", XHCI_TRB_TYPE(letoh32(trb->trb_flags)));
xhci_dump_trb(trb);
#endif
KASSERT(sc->sc_cmd_trb == trb);
sc->sc_cmd_trb = NULL;
+ splx(s);
return (error);
}
+ splx(s);
memcpy(trb0, &sc->sc_result_trb, sizeof(struct xhci_trb));