From ad99383a259a1c775bff1267df94b5e1bbd4cb06 Mon Sep 17 00:00:00 2001 From: maxv Date: Sat, 14 Sep 2019 12:38:40 +0000 Subject: [PATCH] Fix error handling, to prevent kernel crashes when detaching an umcs0 device. Found with vHCI. --- sys/dev/usb/umcs.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/sys/dev/usb/umcs.c b/sys/dev/usb/umcs.c index da80396dd46b..ba11a4fea27e 100644 --- a/sys/dev/usb/umcs.c +++ b/sys/dev/usb/umcs.c @@ -1,4 +1,4 @@ -/* $NetBSD: umcs.c,v 1.13 2019/05/09 02:43:35 mrg Exp $ */ +/* $NetBSD: umcs.c,v 1.14 2019/09/14 12:38:40 maxv Exp $ */ /* $FreeBSD: head/sys/dev/usb/serial/umcs.c 260559 2014-01-12 11:44:28Z hselasky $ */ /*- @@ -41,7 +41,7 @@ * */ #include -__KERNEL_RCSID(0, "$NetBSD: umcs.c,v 1.13 2019/05/09 02:43:35 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: umcs.c,v 1.14 2019/09/14 12:38:40 maxv Exp $"); #include #include @@ -85,6 +85,10 @@ struct umcs7840_softc_oneport { struct umcs7840_softc { device_t sc_dev; /* ourself */ + enum { + UMCS_INIT_NONE, + UMCS_INIT_INITED + } sc_init_state; struct usbd_interface *sc_iface; /* the usb interface */ struct usbd_device *sc_udev; /* the usb device */ struct usbd_pipe *sc_intr_pipe; /* interrupt pipe */ @@ -193,6 +197,7 @@ umcs7840_attach(device_t parent, device_t self, void *aux) sc->sc_dev = self; sc->sc_udev = uaa->uaa_device; sc->sc_dying = false; + sc->sc_init_state = UMCS_INIT_NONE; if (usbd_set_config_index(sc->sc_udev, MCS7840_CONFIG_INDEX, 1) != 0) { aprint_error(": could not set configuration no\n"); @@ -288,6 +293,8 @@ umcs7840_attach(device_t parent, device_t self, void *aux) usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); + sc->sc_init_state = UMCS_INIT_INITED; + memset(&ucaa, 0, sizeof(ucaa)); ucaa.ucaa_ibufsize = 256; ucaa.ucaa_obufsize = 256; @@ -517,6 +524,10 @@ umcs7840_detach(device_t self, int flags) kmem_free(sc->sc_intr_buf, sc->sc_intr_buflen); sc->sc_intr_buf = NULL; } + + if (sc->sc_init_state < UMCS_INIT_INITED) + return 0; + usb_rem_task_wait(sc->sc_udev, &sc->sc_change_task, USB_TASKQ_DRIVER, NULL);