From: sashiko-bot@kernel.org
To: "Shengzhuo Wei" <me@cherr.cc>
Cc: linux-input@vger.kernel.org, dmitry.torokhov@gmail.com
Subject: Re: [PATCH v2] HID: hid-oxp: fix UAF on pending work in remove()
Date: Tue, 04 Aug 2026 10:06:18 +0000 [thread overview]
Message-ID: <20260804100619.59A541F00A3D@smtp.kernel.org> (raw)
In-Reply-To: <20260804-oxp-fix-v2-1-b2d56e4c8a2c@cherr.cc>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
New issues:
- [High] Global workqueues permanently disabled on inert interface removal
Pre-existing issues:
- [High] Use-After-Free on devres-managed led_classdev in probe error path
- [High] Uninitialized work struct access during early raw events
- [High] State corruption and Use-After-Free due to static global drvdata
- [High] NULL Pointer Dereference in early raw event handling
- [Medium] Out-of-Bounds Read in raw event handler
--
--- Patch [1]: [PATCH v2] HID: hid-oxp: fix UAF on pending work in remove() ---
commit 3701229efb152cb11ba2c2b9567116728fd2754a
Author: Shengzhuo Wei <me@cherr.cc>
HID: hid-oxp: fix UAF on pending work in remove()
The patch updates the hid-oxp driver to use disable_delayed_work_sync()
instead of cancel_delayed_work() in the remove path to prevent workers from
firing after device teardown. It also delays the initialization and arming
of the oxp_mcu_init worker in probe to prevent it from pending during a probe
failure.
Link: https://lore.kernel.org/r/20260804-oxp-fix-v1-1-51a4fe787167@cherr.cc
> diff --git a/drivers/hid/hid-oxp.c b/drivers/hid/hid-oxp.c
> --- a/drivers/hid/hid-oxp.c
> +++ b/drivers/hid/hid-oxp.c
> @@ -1501,14 +1501,14 @@ static int oxp_cfg_probe(struct hid_device *hdev, u16 up)
> drvdata.gamepad_mode = OXP_GP_MODE_XINPUT;
> drvdata.rumble_intensity = 5;
>
> - INIT_DELAYED_WORK(&drvdata.oxp_mcu_init, oxp_mcu_init_fn);
> - 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(&hdev->dev, ret,
> "Failed to attach configuration attributes\n");
>
> + INIT_DELAYED_WORK(&drvdata.oxp_mcu_init, oxp_mcu_init_fn);
> + mod_delayed_work(system_wq, &drvdata.oxp_mcu_init, msecs_to_jiffies(50));
> +
[Severity: High]
This is a pre-existing issue, but does moving the initialization to the end
of probe widen a race window with raw events?
Since hid_hw_start() and hid_hw_open() are called earlier in oxp_hid_probe(),
the hardware is active and raw events can arrive before probe completes. If a
device sends a status report early, oxp_hid_raw_event_gen_2() calls
mod_delayed_work() on drvdata.oxp_mcu_init.
Because the delayed work is now initialized at the very end of oxp_cfg_probe(),
could an early event queue an uninitialized work item with a null function
pointer, leading to a kernel panic when the timer fires?
[Severity: High]
This is a pre-existing issue, but does the probe error path leak the pending
work if we fail earlier?
If oxp_cfg_probe() fails after devm_led_classdev_multicolor_register(), for
example during devm_device_add_group(), it returns without canceling
drvdata.oxp_rgb_queue:
oxp_cfg_probe() {
...
ret = devm_device_add_group(drvdata.led_mc->led_cdev.dev,
&oxp_rgb_attr_group);
if (ret)
return dev_err_probe(...);
}
Since the LED class device is briefly registered, userspace or udev can
trigger oxp_rgb_brightness_set(), queueing the delayed work. When probe
returns an error, devres frees the led_classdev. Could the pending work
execute and dereference the freed device pointer?
[Severity: High]
This is a pre-existing issue, but does the driver support multiple devices
safely?
The driver uses a single static global drvdata struct to store per-device
state:
static struct oxp_hid_cfg drvdata;
In oxp_cfg_probe(), this global state is overwritten for each probed device:
oxp_cfg_probe() {
hid_set_drvdata(hdev, &drvdata);
mutex_init(&drvdata.cfg_mutex);
drvdata.hdev = hdev;
...
}
If multiple OneXPlayer devices are connected, the second call will overwrite
drvdata.hdev and reinitialize cfg_mutex, destroying the mutex state for the
first device. Could unplugging one device then leave dangling pointers and
corrupted work structures for the remaining device?
[Severity: High]
This is a pre-existing issue, but could early raw events trigger a null
pointer dereference?
Because hid_hw_start() and hid_hw_open() are called before
oxp_cfg_probe(), raw events can be routed to oxp_hid_raw_event_gen_2()
before drvdata.led_mc is initialized.
Since drvdata is zero-initialized, an early event matching
OXP_FID_GEN2_STATUS_EVENT and OXP_GET_PROPERTY would access
drvdata.led_mc:
oxp_hid_raw_event_gen_2() {
...
led_mc->led_cdev.brightness = rgb_rep->brightness / 4 *
led_mc->led_cdev.max_brightness;
}
Will this dereference a null pointer if probe hasn't completed?
[Severity: Medium]
This is a pre-existing issue, but does the raw event handler verify the
report size?
The HID core passes the actual report size to the raw event handler, but
oxp_hid_raw_event() formats OXP_PACKET_SIZE bytes:
oxp_hid_raw_event() {
...
dev_dbg(&hdev->dev, "raw event data: [%*ph]\n", OXP_PACKET_SIZE, data);
}
oxp_hid_raw_event_gen_2() also accesses specific offsets like data[3] without
checking the boundaries.
If a malicious USB device sends a short HID report, could these handlers
read beyond the allocated buffer and leak uninitialized memory to dmesg?
> return 0;
> }
[ ... ]
> @@ -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);
> + disable_delayed_work_sync(&drvdata.oxp_rgb_queue);
> + disable_delayed_work_sync(&drvdata.oxp_btn_queue);
> + disable_delayed_work_sync(&drvdata.oxp_mcu_init);
[Severity: High]
Do these calls to disable_delayed_work_sync() permanently break the workers?
Because the driver successfully binds to all interfaces of the USB device
and uses a single global drvdata structure, unbinding any inert interface
will trigger oxp_hid_remove().
Since disable_delayed_work_sync() is used, the works are disabled. However,
enable_delayed_work() is never called anywhere in the driver. Could
removing an inert interface permanently break RGB updates, button mappings,
and MCU initialization for the active gamepad interface until it is rebound?
> hid_hw_close(hdev);
> hid_hw_stop(hdev);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260804-oxp-fix-v2-1-b2d56e4c8a2c@cherr.cc?part=1
next prev parent reply other threads:[~2026-08-04 10:06 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-04 9:50 [PATCH v2] HID: hid-oxp: fix UAF on pending work in remove() Shengzhuo Wei
2026-08-04 10:06 ` sashiko-bot [this message]
2026-08-04 20:06 ` Shengzhuo Wei
2026-08-04 21:24 ` Derek John Clark
2026-08-05 4:53 ` Dmitry Torokhov
2026-08-05 8:01 ` Shengzhuo Wei
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260804100619.59A541F00A3D@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dmitry.torokhov@gmail.com \
--cc=linux-input@vger.kernel.org \
--cc=me@cherr.cc \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.