Thread (2 messages) flat view 2 messages, 2 authors, 5d ago

Re: [PATCH AUTOSEL 6.18-6.1] HID: hidpp: fix potential UAF in hidpp_connect_event()

From: sashiko-bot@kernel.org
Date: 2026-08-31 17:39:34

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:

Pre-existing issues:
- [Critical] Force feedback initialization in `hidpp_ff_init()` creates a TOCTOU race that leads to a guaranteed NULL pointer dereference in `input_ff_upload()`.
- [Critical] Missing `hid_hw_stop()` and resource cleanup in the `probe()` error path for G920 devices leads to a catastrophic Use-After-Free.
- [High] Concurrent access to `hidpp->input` between `hidpp_connect_event()` error path and `hidpp_raw_event()` leaves a race window leading to a Use-After-Free.
- [High] Unhandled permanent Use-After-Free for non-delayed initialization devices if `hidinput_connect()` fails.
- [High] Missing `cancel_work_sync(&hidpp->reset_hi_res_work)` in the `hidpp_probe()` error path leads to a Use-After-Free if the work was scheduled.
--

commit 4c51abc31c5c6d9a8be9e395178ab70d3b017d36
Author: Jiri Kosina [off-list ref]
Subject: HID: hidpp: fix potential UAF in hidpp_connect_event()

This commit attempts to fix a potential use-after-free (UAF) by setting
hidpp->input to NULL before calling input_free_device() in the error
path of hidpp_connect_event().
quoted hunk ↗ jump to hunk
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 5e763de4b94fd..bc8761ed41a1c 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -4276,6 +4276,7 @@ static void hidpp_connect_event(struct work_struct *work)
 
 	ret = input_register_device(input);
 	if (ret) {
+		hidpp->input = NULL;
[Severity: High]
This is a pre-existing issue, but does this still leave a TOCTOU race window?

hidpp_populate_input() assigns the allocated input to hidpp->input before
calling input_register_device(), exposing it to concurrent raw hardware
events processed in SoftIRQ (like wtp_raw_event()).

If a concurrent SoftIRQ thread evaluates !hidpp->input just before it is
set to NULL here, will it subsequently dereference the freed pointer?
 		input_free_device(input);
 		return;
 	}
[Severity: High]
This isn't a bug introduced by this patch, but does this leave a permanent
dangling pointer if registration fails?

drivers/hid/hid-logitech-hidpp.c:hidpp_input_configured() {
	...
	if (!hidpp)
		return 0;

	hidpp_populate_input(hidpp, input);
	...
}

hidinput_connect() allocates input_dev and calls .input_configured, which
unconditionally sets hidpp->input = input here.

If input_register_device() then fails inside hidinput_connect(), the core
branches to out_unwind and frees the input device.

However, hid_connect() may still return success (e.g., if hidraw binds
successfully), allowing probe to finish. hidpp->input is never cleared and
remains a dangling pointer, accessed on the next hardware event.

[Severity: Critical]
This is a pre-existing issue, but does this FF initialization create a TOCTOU
race leading to a NULL pointer dereference?

drivers/hid/hid-logitech-hidpp.c:hidpp_probe() {
	...
	if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
		struct hidpp_ff_private_data data;

		ret = g920_get_config(hidpp, &data);
		if (!ret)
			ret = hidpp_ff_init(hidpp, &data);
	...
}

hid_connect() registers the input device, making it exposed to userspace.
Then hidpp_ff_init() is called, which calls input_ff_create() setting the
EV_FF bit.

If a subsequent memory allocation in hidpp_ff_init() fails, it returns
-ENOMEM leaving ff->upload as NULL. Because the device is already
registered, userspace can open it and issue the EVIOCSFF ioctl, which
will blindly execute ff->upload(dev, effect, old).

[Severity: Critical]
This is a pre-existing issue, but does this bypass the error cleanup labels
and skip hid_hw_stop() when G920 initialization fails?

drivers/hid/hid-logitech-hidpp.c:hidpp_probe() {
	...
		if (ret)
			hid_warn(hidpp->hid_dev,
		     "Unable to initialize force feedback support, errno %d\n",
				 ret);
	}

	/*
	 * This relies on logi_dj_ll_close() being a no-op so that DJ connection
	 * events will still be received.
	 */
	hid_hw_close(hdev);
	return ret;
	...
}

When ret is non-zero, it returns directly here. This leaves the device
active in the HID subsystem, processing hardware interrupts, while the
driver's devm resources are freed by the core, leading to a Use-After-Free.

[Severity: High]
This is a pre-existing issue, but does this error path fail to cancel
reset_hi_res_work?

drivers/hid/hid-logitech-hidpp.c:hidpp_probe() {
	...
hid_hw_start_fail:
	sysfs_remove_group(&hdev->dev.kobj, &ps_attribute_group);
	cancel_work_sync(&hidpp->work);
	mutex_destroy(&hidpp->send_mutex);
	return ret;
}

hidpp_probe() calls hid_device_io_start(), enabling incoming hardware events.
A battery online event can trigger hidpp_raw_hidpp_event() to schedule
reset_hi_res_work.

If a subsequent step in probe (like hid_connect()) fails, the error cleanup
path cancels hidpp->work but misses hidpp->reset_hi_res_work. The hidpp
struct is then freed by devres, leaving the scheduled work item pointing to
freed memory.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260831133314.4125787-633-sashal@kernel.org?part=1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help