Use after free in dispatch_hid_bpf_output_report()
From: Petr Tesařík <hidden>
Date: 2025-05-09 09:47:45
Subsystem:
hid core layer, the rest · Maintainers:
Jiri Kosina, Benjamin Tissoires, Linus Torvalds
Hi all, after installing v6.15-rc5 on my laptop, I'm running into an invalid pointer dereference in dispatch_hid_bpf_output_report() on suspend. I added some debugging messages (see patch below), and I can see this sequence of events: [ 1568.571776] [ T7420] PM: suspend entry (deep) [ 1568.602245] [ T7420] Filesystems sync: 0.030 seconds [ 1568.613183] [ T1704] hid-generic 0005:04F2:182A.0004: CLEANED UP srcu 00000000b7570e01 [ 1568.613348] [ T724] hid-generic 0005:04F2:182A.0004: UAF srcu 00000000b7570e01 [ 1568.616215] [ T7420] Freezing user space processes The HID device is a Bluetooth keyboard (using bluez 5.79), which (presumably) gets disconnected on suspend. FTR I didn't encounter any such issues with v6.14. Petr T
diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
index 2e96ec6a3073..f284175e8b0b 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.c
+++ b/drivers/hid/bpf/hid_bpf_dispatch.c@@ -130,6 +130,11 @@ int dispatch_hid_bpf_output_report(struct hid_device *hdev, struct hid_bpf_ops *e; int ret, idx; + if (unlikely(!hdev->bpf.srcu.sda)) { + hid_warn(hdev, "UAF srcu %p", &hdev->bpf.srcu); + return 0; + } + idx = srcu_read_lock(&hdev->bpf.srcu); list_for_each_entry_srcu(e, &hdev->bpf.prog_list, list, srcu_read_lock_held(&hdev->bpf.srcu)) {
@@ -143,6 +148,8 @@ int dispatch_hid_bpf_output_report(struct hid_device *hdev, ret = 0; out: + if (unlikely(!hdev->bpf.srcu.sda)) + hid_warn(hdev, "RACE srcu %p", &hdev->bpf.srcu); srcu_read_unlock(&hdev->bpf.srcu, idx); return ret; }
@@ -631,6 +638,7 @@ void hid_bpf_destroy_device(struct hid_device *hdev) synchronize_srcu(&hdev->bpf.srcu); cleanup_srcu_struct(&hdev->bpf.srcu); + hid_info(hdev, "CLEANED UP srcu %p", &hdev->bpf.srcu); } EXPORT_SYMBOL_GPL(hid_bpf_destroy_device);