[PATCH] HID: core: fix device cleanup on allocation failure
Tristan Madani <[email protected]>
| Newsgroups | org.kernel.vger.linux-input,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
From: Tristan Madani <[email protected]> hid_allocate_device() calls hid_destroy_device() in its error path when hid_bpf_device_init() fails. hid_destroy_device() in turn calls hid_bpf_destroy_device() which invokes synchronize_srcu() and cleanup_srcu_struct() on the SRCU structure. However, at this point init_srcu_struct() has not been called (or has failed), so the SRCU internal pointers are all zeroed from kzalloc. Dereferencing them causes a general protection fault: general protection fault in check_init_srcu_struct KASAN: null-ptr-deref in range [0x00000000000001c0-0x00000000000001c7] Call Trace: synchronize_srcu+0x1c/0x2b0 hid_bpf_destroy_device+0x64/0x90 hid_destroy_device+0x29/0x240 hid_allocate_device+0x420/0x4e0 uhid_dev_create2+0x161/0x890 Fix this by replacing hid_destroy_device() with put_device() in the error path. At this point in hid_allocate_device(), the device has been initialized (device_initialize) but not yet added (device_add), so put_device() is the correct cleanup call. It triggers the release callback which frees the hid_device without attempting to clean up resources that were never set up. Found by syzkaller on Ubuntu 6.14.11 KASAN. Fixes: 6cd735f0e57a ("HID: bpf: protect HID-BPF prog_list access by a SRCU") Cc: [email protected] Signed-off-by: Tristan Madani <[email protected]> --- drivers/hid/hid-core.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index cf123347a2af7..9534de5317783 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -3060,7 +3060,12 @@ struct hid_device *hid_allocate_device(void) return hdev; out_err: - hid_destroy_device(hdev); + /* + * hid_destroy_device() cannot be used here because + * hid_bpf_device_init() failed and the SRCU struct was never + * initialized. Release the device directly. + */ + put_device(&hdev->dev); return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(hid_allocate_device); -- 2.47.3