summaryrefslogtreecommitdiff
path: root/include/linux/usb/usbnet.h
diff options
context:
space:
mode:
authorOliver Neukum <oneukum@suse.de>2014-03-26 17:32:51 +0400
committerJiri Slaby <jslaby@suse.cz>2014-04-18 13:07:13 +0400
commit0631987d442761501dc65c8ecb9a1267e0b2050d (patch)
treede2502b77c33892cc8edc2550a95b5bb98e11476 /include/linux/usb/usbnet.h
parent3552f3fcb4da06e0129eb4a66c31ad410ecbb9e4 (diff)
downloadlinux-0631987d442761501dc65c8ecb9a1267e0b2050d.tar.xz
usbnet: include wait queue head in device structure
[ Upstream commit 14a0d635d18d0fb552dcc979d6d25106e6541f2e ] This fixes a race which happens by freeing an object on the stack. Quoting Julius: > The issue is > that it calls usbnet_terminate_urbs() before that, which temporarily > installs a waitqueue in dev->wait in order to be able to wait on the > tasklet to run and finish up some queues. The waiting itself looks > okay, but the access to 'dev->wait' is totally unprotected and can > race arbitrarily. I think in this case usbnet_bh() managed to succeed > it's dev->wait check just before usbnet_terminate_urbs() sets it back > to NULL. The latter then finishes and the waitqueue_t structure on its > stack gets overwritten by other functions halfway through the > wake_up() call in usbnet_bh(). The fix is to just not allocate the data structure on the stack. As dev->wait is abused as a flag it also takes a runtime PM change to fix this bug. Signed-off-by: Oliver Neukum <oneukum@suse.de> Reported-by: Grant Grundler <grundler@google.com> Tested-by: Grant Grundler <grundler@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Diffstat (limited to 'include/linux/usb/usbnet.h')
-rw-r--r--include/linux/usb/usbnet.h2
1 files changed, 1 insertions, 1 deletions
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index e303eef94dd5..0662e98fef72 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -30,7 +30,7 @@ struct usbnet {
struct driver_info *driver_info;
const char *driver_name;
void *driver_priv;
- wait_queue_head_t *wait;
+ wait_queue_head_t wait;
struct mutex phy_mutex;
unsigned char suspend_count;
unsigned char pkt_cnt, pkt_err;