summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpi <mpi@openbsd.org>2020-01-04 11:40:56 +0000
committermpi <mpi@openbsd.org>2020-01-04 11:40:56 +0000
commitea9883cc1d60bfac84af96526b0c3b2a89cf3cac (patch)
tree90ded78abb249352e5a9adbe3ae7b4b67edd0d04
parentConvert sleep to tsleep_nsec(9) and use unique sleeping identifiers. (diff)
downloadwireguard-openbsd-ea9883cc1d60bfac84af96526b0c3b2a89cf3cac.tar.xz
wireguard-openbsd-ea9883cc1d60bfac84af96526b0c3b2a89cf3cac.zip
Prevent use-after-free in uhidev_close().
Close pipes before freeing transfers, otherwise accessing elements in pipe->queue, like in usbd_abort_pipe(), will result in a crash. Problem reported by reyk@, ok visa@
-rw-r--r--sys/dev/usb/uhidev.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/sys/dev/usb/uhidev.c b/sys/dev/usb/uhidev.c
index 8f55b056507..c4cac47ba37 100644
--- a/sys/dev/usb/uhidev.c
+++ b/sys/dev/usb/uhidev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uhidev.c,v 1.77 2019/11/13 10:40:03 patrick Exp $ */
+/* $OpenBSD: uhidev.c,v 1.78 2020/01/04 11:40:56 mpi Exp $ */
/* $NetBSD: uhidev.c,v 1.14 2003/03/11 16:44:00 augustss Exp $ */
/*
@@ -606,6 +606,19 @@ uhidev_close(struct uhidev *scd)
return;
DPRINTF(("uhidev_close: close pipe\n"));
+ /* Disable interrupts. */
+ if (sc->sc_opipe != NULL) {
+ usbd_abort_pipe(sc->sc_opipe);
+ usbd_close_pipe(sc->sc_opipe);
+ sc->sc_opipe = NULL;
+ }
+
+ if (sc->sc_ipipe != NULL) {
+ usbd_abort_pipe(sc->sc_ipipe);
+ usbd_close_pipe(sc->sc_ipipe);
+ sc->sc_ipipe = NULL;
+ }
+
if (sc->sc_oxfer != NULL) {
usbd_free_xfer(sc->sc_oxfer);
sc->sc_oxfer = NULL;
@@ -621,19 +634,6 @@ uhidev_close(struct uhidev *scd)
sc->sc_ixfer = NULL;
}
- /* Disable interrupts. */
- if (sc->sc_opipe != NULL) {
- usbd_abort_pipe(sc->sc_opipe);
- usbd_close_pipe(sc->sc_opipe);
- sc->sc_opipe = NULL;
- }
-
- if (sc->sc_ipipe != NULL) {
- usbd_abort_pipe(sc->sc_ipipe);
- usbd_close_pipe(sc->sc_ipipe);
- sc->sc_ipipe = NULL;
- }
-
if (sc->sc_ibuf != NULL) {
free(sc->sc_ibuf, M_USBDEV, sc->sc_isize);
sc->sc_ibuf = NULL;