Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

HID: picolcd: Prevent NULL pointer dereference on _remove()

When picolcd is switched into bootloader mode (for FW flashing) make
sure not to try to dereference NULL-pointers of feature-devices during
unplug/unbind.

This fixes following BUG:
BUG: unable to handle kernel NULL pointer dereference at 00000298
IP: [<f811f56b>] picolcd_exit_framebuffer+0x1b/0x80 [hid_picolcd]
*pde = 00000000
Oops: 0000 [#1]
Modules linked in: hid_picolcd syscopyarea sysfillrect sysimgblt fb_sys_fops
CPU: 0 PID: 15 Comm: khubd Not tainted 3.11.0-rc7-00002-g50d62d4 #2
EIP: 0060:[<f811f56b>] EFLAGS: 00010292 CPU: 0
EIP is at picolcd_exit_framebuffer+0x1b/0x80 [hid_picolcd]
Call Trace:
[<f811d1ab>] picolcd_remove+0xcb/0x120 [hid_picolcd]
[<c1469b09>] hid_device_remove+0x59/0xc0
[<c13464ca>] __device_release_driver+0x5a/0xb0
[<c134653f>] device_release_driver+0x1f/0x30
[<c134603d>] bus_remove_device+0x9d/0xd0
[<c13439a5>] device_del+0xd5/0x150
[<c14696a4>] hid_destroy_device+0x24/0x60
[<c1474cbb>] usbhid_disconnect+0x1b/0x40
...

Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
Cc: stable@kernel.org
Signed-off-by: Jiri Kosina <jkosina@suse.cz>

authored by

Bruno Prémont and committed by
Jiri Kosina
1cde501b 9e0bf92c

+7 -2
+2 -1
drivers/hid/hid-picolcd_cir.c
··· 145 145 struct rc_dev *rdev = data->rc_dev; 146 146 147 147 data->rc_dev = NULL; 148 - rc_unregister_device(rdev); 148 + if (rdev) 149 + rc_unregister_device(rdev); 149 150 } 150 151
+5 -1
drivers/hid/hid-picolcd_fb.c
··· 593 593 void picolcd_exit_framebuffer(struct picolcd_data *data) 594 594 { 595 595 struct fb_info *info = data->fb_info; 596 - struct picolcd_fb_data *fbdata = info->par; 596 + struct picolcd_fb_data *fbdata; 597 597 unsigned long flags; 598 598 599 + if (!info) 600 + return; 601 + 599 602 device_remove_file(&data->hdev->dev, &dev_attr_fb_update_rate); 603 + fbdata = info->par; 600 604 601 605 /* disconnect framebuffer from HID dev */ 602 606 spin_lock_irqsave(&fbdata->lock, flags);