summaryrefslogtreecommitdiffstats
path: root/drivers/hid/usbhid
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2010-08-13 12:19:45 +0200
committerJiri Kosina <jkosina@suse.cz>2010-08-13 12:19:45 +0200
commit9c9e54a8df0be48aa359744f412377cc55c3b7d2 (patch)
tree1df6c9dde015a961c2841437cb757e36119e7ea6 /drivers/hid/usbhid
parentHID: hiddev: protect against disconnect/NULL-dereference race (diff)
downloadlinux-9c9e54a8df0be48aa359744f412377cc55c3b7d2.tar.xz
linux-9c9e54a8df0be48aa359744f412377cc55c3b7d2.zip
HID: hiddev: fix memory corruption due to invalid intfdata
Commit bd25f4dd6972755579d0 ("HID: hiddev: use usb_find_interface, get rid of BKL") introduced using of private intfdata in hiddev for purpose of storing hiddev pointer. This is a problem, because intf pointer is already being set to struct hid_device pointer by HID core. This obviously lead to memory corruptions at device disconnect time, such as WARNING: at lib/kobject.c:595 kobject_put+0x37/0x4b() kobject: '(null)' (ffff88011e9cd898): is not initialized, yet kobject_put() is being called. Convert hiddev into accessing hiddev through struct hid_device which is in intfdata already. Reported-and-tested-by: Markus Trippelsdorf <markus@trippelsdorf.de> Reported-and-tested-by: Heinz Diehl <htd@fritha.org> Reported-and-tested-by: Alan Ott <alan@signal11.us> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/usbhid')
-rw-r--r--drivers/hid/usbhid/hiddev.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index f2850171a69b..0a29c51114aa 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -266,13 +266,15 @@ static int hiddev_open(struct inode *inode, struct file *file)
{
struct hiddev_list *list;
struct usb_interface *intf;
+ struct hid_device *hid;
struct hiddev *hiddev;
int res;
intf = usb_find_interface(&hiddev_driver, iminor(inode));
if (!intf)
return -ENODEV;
- hiddev = usb_get_intfdata(intf);
+ hid = usb_get_intfdata(intf);
+ hiddev = hid->hiddev;
if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
return -ENOMEM;
@@ -890,7 +892,6 @@ int hiddev_connect(struct hid_device *hid, unsigned int force)
hid->hiddev = hiddev;
hiddev->hid = hid;
hiddev->exist = 1;
- usb_set_intfdata(usbhid->intf, usbhid);
retval = usb_register_dev(usbhid->intf, &hiddev_class);
if (retval) {
err_hid("Not able to get a minor for this device.");