summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2016-06-13 10:15:04 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2016-06-13 10:15:04 +0000
commitfb652f1341d7d273fc8db5919c71dbff4b2b0276 (patch)
treeded81accbe6637d5d4f6ca51b88f9c76df34da85 /sys
parent4ff8b7fb051b7c23e55ffe1e208c374abb678d64 (diff)
Do not execute the callback if the device is beeing detached.
Should prevent a race triggering a use-after-free reported by martijn@ on bugs@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/usb/uhidev.c25
1 files changed, 13 insertions, 12 deletions
diff --git a/sys/dev/usb/uhidev.c b/sys/dev/usb/uhidev.c
index 2598e2d5868..256ec08933d 100644
--- a/sys/dev/usb/uhidev.c
+++ b/sys/dev/usb/uhidev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uhidev.c,v 1.73 2016/01/09 04:14:42 jcs Exp $ */
+/* $OpenBSD: uhidev.c,v 1.74 2016/06/13 10:15:03 mpi Exp $ */
/* $NetBSD: uhidev.c,v 1.14 2003/03/11 16:44:00 augustss Exp $ */
/*
@@ -96,8 +96,7 @@ void uhidev_attach(struct device *, struct device *, void *);
int uhidev_detach(struct device *, int);
int uhidev_activate(struct device *, int);
-void uhidev_get_report_async_cb(struct usbd_xfer *xfer, void *priv,
- usbd_status status);
+void uhidev_get_report_async_cb(struct usbd_xfer *, void *, usbd_status);
struct cfdriver uhidev_cd = {
NULL, "uhidev", DV_DULL
@@ -754,17 +753,19 @@ uhidev_get_report_async_cb(struct usbd_xfer *xfer, void *priv, usbd_status err)
char *buf;
int len = -1;
- if (err == USBD_NORMAL_COMPLETION || err == USBD_SHORT_XFER) {
- len = xfer->actlen;
- buf = KERNADDR(&xfer->dmabuf, 0);
- if (info->id > 0) {
- len--;
- memcpy(info->data, buf + 1, len);
- } else {
- memcpy(info->data, buf, len);
+ if (!usbd_is_dying(xfer->pipe->device)) {
+ if (err == USBD_NORMAL_COMPLETION || err == USBD_SHORT_XFER) {
+ len = xfer->actlen;
+ buf = KERNADDR(&xfer->dmabuf, 0);
+ if (info->id > 0) {
+ len--;
+ memcpy(info->data, buf + 1, len);
+ } else {
+ memcpy(info->data, buf, len);
+ }
}
+ info->callback(info->priv, info->id, info->data, len);
}
- info->callback(info->priv, info->id, info->data, len);
free(info, M_TEMP, sizeof(*info));
usbd_free_xfer(xfer);
}