Skip to content

Commit 377c4c7

Browse files
be286gregkh
authored andcommitted
HID: fix HID device resource race between HID core and debugging support
[ Upstream commit fc43e9c ] hid_debug_events_release releases resources bound to the HID device instance. hid_device_release releases the underlying HID device instance potentially before hid_debug_events_release has completed releasing debug resources bound to the same HID device instance. Reference count to prevent the HID device instance from being torn down preemptively when HID debugging support is used. When count reaches zero, release core resources of HID device instance using hiddev_free. The crash: [ 120.728477][ T4396] kernel BUG at lib/list_debug.c:53! [ 120.728505][ T4396] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP [ 120.739806][ T4396] Modules linked in: bcmdhd dhd_static_buf 8822cu pcie_mhi r8168 [ 120.747386][ T4396] CPU: 1 PID: 4396 Comm: hidt_bridge Not tainted 5.10.110 #257 [ 120.754771][ T4396] Hardware name: Rockchip RK3588 EVB4 LP4 V10 Board (DT) [ 120.761643][ T4396] pstate: 60400089 (nZCv daIf +PAN -UAO -TCO BTYPE=--) [ 120.768338][ T4396] pc : __list_del_entry_valid+0x98/0xac [ 120.773730][ T4396] lr : __list_del_entry_valid+0x98/0xac [ 120.779120][ T4396] sp : ffffffc01e62bb60 [ 120.783126][ T4396] x29: ffffffc01e62bb60 x28: ffffff818ce3a200 [ 120.789126][ T4396] x27: 0000000000000009 x26: 0000000000980000 [ 120.795126][ T4396] x25: ffffffc012431000 x24: ffffff802c6d4e00 [ 120.801125][ T4396] x23: ffffff8005c66f00 x22: ffffffc01183b5b8 [ 120.807125][ T4396] x21: ffffff819df2f100 x20: 0000000000000000 [ 120.813124][ T4396] x19: ffffff802c3f0700 x18: ffffffc01d2cd058 [ 120.819124][ T4396] x17: 0000000000000000 x16: 0000000000000000 [ 120.825124][ T4396] x15: 0000000000000004 x14: 0000000000003fff [ 120.831123][ T4396] x13: ffffffc012085588 x12: 0000000000000003 [ 120.837123][ T4396] x11: 00000000ffffbfff x10: 0000000000000003 [ 120.843123][ T4396] x9 : 455103d46b329300 x8 : 455103d46b329300 [ 120.849124][ T4396] x7 : 74707572726f6320 x6 : ffffffc0124b8cb5 [ 120.855124][ T4396] x5 : ffffffffffffffff x4 : 0000000000000000 [ 120.861123][ T4396] x3 : ffffffc011cf4f90 x2 : ffffff81fee7b948 [ 120.867122][ T4396] x1 : ffffffc011cf4f90 x0 : 0000000000000054 [ 120.873122][ T4396] Call trace: [ 120.876259][ T4396] __list_del_entry_valid+0x98/0xac [ 120.881304][ T4396] hid_debug_events_release+0x48/0x12c [ 120.886617][ T4396] full_proxy_release+0x50/0xbc [ 120.891323][ T4396] __fput+0xdc/0x238 [ 120.895075][ T4396] ____fput+0x14/0x24 [ 120.898911][ T4396] task_work_run+0x90/0x148 [ 120.903268][ T4396] do_exit+0x1bc/0x8a4 [ 120.907193][ T4396] do_group_exit+0x8c/0xa4 [ 120.911458][ T4396] get_signal+0x468/0x744 [ 120.915643][ T4396] do_signal+0x84/0x280 [ 120.919650][ T4396] do_notify_resume+0xd0/0x218 [ 120.924262][ T4396] work_pending+0xc/0x3f0 [ Rahul Rameshbabu <[email protected]>: rework changelog ] Fixes: cd667ce ("HID: use debugfs for events/reports dumping") Signed-off-by: Charles Yi <[email protected]> Signed-off-by: Jiri Kosina <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 8e9a649 commit 377c4c7

File tree

3 files changed

+16
-2
lines changed

3 files changed

+16
-2
lines changed

drivers/hid/hid-core.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -707,15 +707,22 @@ static void hid_close_report(struct hid_device *device)
707707
* Free a device structure, all reports, and all fields.
708708
*/
709709

710-
static void hid_device_release(struct device *dev)
710+
void hiddev_free(struct kref *ref)
711711
{
712-
struct hid_device *hid = to_hid_device(dev);
712+
struct hid_device *hid = container_of(ref, struct hid_device, ref);
713713

714714
hid_close_report(hid);
715715
kfree(hid->dev_rdesc);
716716
kfree(hid);
717717
}
718718

719+
static void hid_device_release(struct device *dev)
720+
{
721+
struct hid_device *hid = to_hid_device(dev);
722+
723+
kref_put(&hid->ref, hiddev_free);
724+
}
725+
719726
/*
720727
* Fetch a report description item from the data stream. We support long
721728
* items, though they are not used yet.
@@ -2813,6 +2820,7 @@ struct hid_device *hid_allocate_device(void)
28132820
spin_lock_init(&hdev->debug_list_lock);
28142821
sema_init(&hdev->driver_input_lock, 1);
28152822
mutex_init(&hdev->ll_open_lock);
2823+
kref_init(&hdev->ref);
28162824

28172825
return hdev;
28182826
}

drivers/hid/hid-debug.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,7 @@ static int hid_debug_events_open(struct inode *inode, struct file *file)
11321132
goto out;
11331133
}
11341134
list->hdev = (struct hid_device *) inode->i_private;
1135+
kref_get(&list->hdev->ref);
11351136
file->private_data = list;
11361137
mutex_init(&list->read_mutex);
11371138

@@ -1224,6 +1225,8 @@ static int hid_debug_events_release(struct inode *inode, struct file *file)
12241225
list_del(&list->node);
12251226
spin_unlock_irqrestore(&list->hdev->debug_list_lock, flags);
12261227
kfifo_free(&list->hid_debug_fifo);
1228+
1229+
kref_put(&list->hdev->ref, hiddev_free);
12271230
kfree(list);
12281231

12291232
return 0;

include/linux/hid.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,10 +653,13 @@ struct hid_device { /* device report descriptor */
653653
struct list_head debug_list;
654654
spinlock_t debug_list_lock;
655655
wait_queue_head_t debug_wait;
656+
struct kref ref;
656657

657658
unsigned int id; /* system unique id */
658659
};
659660

661+
void hiddev_free(struct kref *ref);
662+
660663
#define to_hid_device(pdev) \
661664
container_of(pdev, struct hid_device, dev)
662665

0 commit comments

Comments
 (0)