aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/hid/usbhid/usbhid.h
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2020-04-22 16:18:48 -0400
committerJiri Kosina <jkosina@suse.cz>2020-04-29 16:24:26 +0200
commit0ed08faded1da03eb3def61502b27f81aef2e615 (patch)
tree35b05447dc4293e0a4c29368253c432d8e071048 /drivers/hid/usbhid/usbhid.h
parentRevert "HID: wacom: generic: read the number of expected touches on a per collection basis" (diff)
downloadwireguard-linux-0ed08faded1da03eb3def61502b27f81aef2e615.tar.xz
wireguard-linux-0ed08faded1da03eb3def61502b27f81aef2e615.zip
HID: usbhid: Fix race between usbhid_close() and usbhid_stop()
The syzbot fuzzer discovered a bad race between in the usbhid driver between usbhid_stop() and usbhid_close(). In particular, usbhid_stop() does: usb_free_urb(usbhid->urbin); ... usbhid->urbin = NULL; /* don't mess up next start */ and usbhid_close() does: usb_kill_urb(usbhid->urbin); with no mutual exclusion. If the two routines happen to run concurrently so that usb_kill_urb() is called in between the usb_free_urb() and the NULL assignment, it will access the deallocated urb structure -- a use-after-free bug. This patch adds a mutex to the usbhid private structure and uses it to enforce mutual exclusion of the usbhid_start(), usbhid_stop(), usbhid_open() and usbhid_close() callbacks. Reported-and-tested-by: syzbot+7bf5a7b0f0a1f9446f4c@syzkaller.appspotmail.com Signed-off-by: Alan Stern <stern@rowland.harvard.edu> CC: <stable@vger.kernel.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to '')
-rw-r--r--drivers/hid/usbhid/usbhid.h1
1 files changed, 1 insertions, 0 deletions
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index 8620408bd7af..75fe85d3d27a 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -80,6 +80,7 @@ struct usbhid_device {
dma_addr_t outbuf_dma; /* Output buffer dma */
unsigned long last_out; /* record of last output for timeouts */
+ struct mutex mutex; /* start/stop/open/close */
spinlock_t lock; /* fifo spinlock */
unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
struct timer_list io_retry; /* Retry timer */