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

Re: [PATCH] HID: hid-oxp: fix UAF on pending work in remove()

From: sashiko-bot@kernel.org
Date: 2026-08-03 23:30:11

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

Pre-existing issues:
- [High] The transition to `cancel_delayed_work_sync()` is ineffective because the delayed works can be immediately re-queued after cancellation, leading to the same use-after-free the patch attempts to fix.
- [High] The driver stores per-device state in a single static global `drvdata` structure instead of using per-device contexts, leading to memory corruption, timer list corruption, and Use-After-Free if multiple matching devices or interfaces are probed.
- [High] Delayed works are leaked and will execute on a freed `hid_device` if `oxp_cfg_probe()` encounters an error after arming the work.
--
--- Patch [1]: [PATCH] HID: hid-oxp: fix UAF on pending work in remove() ---
commit 9da1adfd8fd14b4d1b17ae38165e5f4aa4ff44f5
Author: Shengzhuo Wei [off-list ref]

    HID: hid-oxp: fix UAF on pending work in remove()
    
    Drain oxp_rgb_queue, oxp_btn_queue, and oxp_mcu_init works with
    cancel_delayed_work_sync() in oxp_hid_remove() so they exit before the
    hid_device is freed.
quoted hunk ↗ jump to hunk
diff --git a/drivers/hid/hid-oxp.c b/drivers/hid/hid-oxp.c
index 20a54f337220d..d8fb6a69d40d4 100644
--- a/drivers/hid/hid-oxp.c
+++ b/drivers/hid/hid-oxp.c
@@ -1552,9 +1552,9 @@ static int oxp_hid_probe(struct hid_device *hdev,
 
 static void oxp_hid_remove(struct hid_device *hdev)
 {
-	cancel_delayed_work(&drvdata.oxp_rgb_queue);
-	cancel_delayed_work(&drvdata.oxp_btn_queue);
-	cancel_delayed_work(&drvdata.oxp_mcu_init);
+	cancel_delayed_work_sync(&drvdata.oxp_rgb_queue);
+	cancel_delayed_work_sync(&drvdata.oxp_btn_queue);
+	cancel_delayed_work_sync(&drvdata.oxp_mcu_init);
[Severity: High]
This isn't a bug introduced by this patch, but is it possible for the works
to be re-armed immediately after they are cancelled here?

Since hid_hw_stop() is called after the cancellations, hardware events can
still arrive and trigger oxp_hid_raw_event_gen_2(), which could re-arm
oxp_mcu_init.

Similarly, since devres cleans up sysfs attributes and the LED class device
after remove() returns, userspace could still trigger oxp_rgb_brightness_set()
and re-arm oxp_rgb_queue:

drivers/hid/hid-oxp.c:oxp_rgb_brightness_set() {
    ...
    mod_delayed_work(system_wq, &drvdata.oxp_rgb_queue, msecs_to_jiffies(50));
}

Could this lead to the same use-after-free this patch is attempting to fix
by allowing the works to run on a freed hid_device?

[Severity: High]
This is a pre-existing issue, but does using a single static global drvdata
structure cause memory corruption if multiple matching devices are probed?

When oxp_cfg_probe() runs, it unconditionally re-initializes the global state:

drivers/hid/hid-oxp.c:oxp_cfg_probe() {
    ...
    drvdata.hdev = hdev;
    ...
    INIT_DELAYED_WORK(&drvdata.oxp_rgb_queue, oxp_rgb_queue_fn);
}

If a second device (or a composite device with multiple matching interfaces)
is connected, calling INIT_DELAYED_WORK() on an already active work item
could corrupt the workqueue linked lists.

Additionally, removing one device would cancel the workers for the other
while leaving drvdata.hdev pointing to a freed device.

[Severity: High]
This is also a pre-existing issue, but does the probe error path leak the
delayed works?

In oxp_cfg_probe(), the work is armed before all resources are guaranteed to
be initialized:

drivers/hid/hid-oxp.c:oxp_cfg_probe() {
    ...
    mod_delayed_work(system_wq, &drvdata.oxp_mcu_init, msecs_to_jiffies(50));

    ret = devm_device_add_group(&hdev->dev, &oxp_cfg_attrs_group);
    if (ret)
        return dev_err_probe(...);
}

If devm_device_add_group() fails, oxp_cfg_probe() returns an error. The caller
oxp_hid_probe() handles this by calling hid_hw_close() and hid_hw_stop(), but
it does not appear to cancel the pending delayed works before the HID core
frees the device.

Will the delayed work execute on a freed hid_device when the timer expires in
this error scenario?
 	hid_hw_close(hdev);
 	hid_hw_stop(hdev);
 }
-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260804-oxp-fix-v1-1-51a4fe787167@cherr.cc?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