* [PATCH v2] HID: wacom: validate report length in wacom_intuos_pro2_bt_irq
From: Ibrahim Hashimov @ 2026-07-13 9:34 UTC (permalink / raw)
To: ping.cheng, jason.gerecke, jikos, bentiss
Cc: dmitry.torokhov, linux-input, linux-kernel, stable
In-Reply-To: <20260713075110.92469-1-security@auditcode.ai>
wacom_intuos_pro2_bt_irq() receives the wire report length in `len`
but never consults it before parsing. After the report-id gate it
unconditionally calls wacom_intuos_pro2_bt_pen() and then, selected by
features.type, a fixed chain of sub-parsers, none of which receive
`len`:
wacom_intuos_pro2_bt_pen(wacom);
if (type == INTUOSP2_BT || type == INTUOSP2S_BT) {
wacom_intuos_pro2_bt_touch(wacom);
wacom_intuos_pro2_bt_pad(wacom);
wacom_intuos_pro2_bt_battery(wacom);
} else {
wacom_intuos_gen3_bt_pad(wacom);
wacom_intuos_gen3_bt_battery(wacom);
}
Each sub-parser dereferences wacom->data at fixed offsets. The furthest
byte touched on each branch is:
INTUOSP2_BT / INTUOSP2S_BT: wacom_intuos_pro2_bt_pad() reads data[285]
(the touchring byte), so the report must be at least 286 bytes;
INTUOSHT3_BT ("gen3"): wacom_intuos_gen3_bt_battery() reads data[45],
so the report must be at least 46 bytes.
features.type is selected from the VID/PID id_table entry and
wacom_setup_device_quirks() force-registers the pen/pad/touch inputs
for that type independent of the report descriptor, so a malicious or
malfunctioning paired/spoofed Bluetooth peripheral can advertise that
VID/PID and send an undersized report that still satisfies the
data[0] == 0x80/0x81 gate. The driver then reads past the received
report and forwards the bytes to userspace via evdev (MSC_SERIAL /
ABS_MISC / ABS_WHEEL on the pen and pad input nodes), an out-of-bounds
read with a concrete userspace read-back channel, and a true
out-of-bounds read on transports whose backing buffer is sized to the
(small) report descriptor rather than a fixed-size staging buffer.
This is the same class of bug commit 2f1763f62909 ("HID: wacom: fix
out-of-bounds read in wacom_intuos_bt_irq") already hardened in the
sibling wacom_intuos_bt_irq(), which guards each report id against its
minimum length before parsing.
Guard wacom_intuos_pro2_bt_irq() the same way: before parsing, reject
reports shorter than the furthest offset the selected branch actually
dereferences, warn, and bail out. Because the whole pen/touch/pad/
battery chain runs unconditionally per branch, a single up-front check
against the maximum offset (286 bytes for INTUOSP2_BT/INTUOSP2S_BT,
46 bytes for the gen3 branch) bounds every sub-parser. Returning 0 on
a short report also skips those calls for the same malformed report,
which is the safe, conservative behavior.
Fixes: 4922cd26f03c ("HID: wacom: Support 2nd-gen Intuos Pro's Bluetooth classic interface")
Cc: stable@vger.kernel.org
Signed-off-by: Ibrahim Hashimov <security@auditcode.ai>
Assisted-by: AuditCode-AI:2026.07
---
v2: the v1 check (len < 109 / len < 43) only bounded
wacom_intuos_pro2_bt_pen(). As sashiko-bot pointed out, the
unconditional touch/pad/battery calls read much further --
wacom_intuos_pro2_bt_pad() up to data[285] and
wacom_intuos_gen3_bt_battery() up to data[45] -- so a report in the
gap (109..285 / 43..45) passed the guard yet still over-read. Raise
the minimums to the furthest offset each branch dereferences
(286 / 46) so the guard actually bounds the whole call chain.
drivers/hid/wacom_wac.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index da1f0ea85625..89a191cf1924 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1548,6 +1548,19 @@ static int wacom_intuos_pro2_bt_irq(struct wacom_wac *wacom, size_t len)
return 0;
}
+ if (wacom->features.type == INTUOSP2_BT ||
+ wacom->features.type == INTUOSP2S_BT) {
+ if (len < 286) {
+ dev_warn(wacom->pen_input->dev.parent,
+ "Pro2 BT report too short: %zu bytes\n", len);
+ return 0;
+ }
+ } else if (len < 46) {
+ dev_warn(wacom->pen_input->dev.parent,
+ "Pro2 BT report too short: %zu bytes\n", len);
+ return 0;
+ }
+
wacom_intuos_pro2_bt_pen(wacom);
if (wacom->features.type == INTUOSP2_BT ||
wacom->features.type == INTUOSP2S_BT) {
--
2.50.1 (Apple Git-155)
^ permalink raw reply related
* Re: [PATCH v2] HID: wacom: validate report length in wacom_intuos_pro2_bt_irq
From: sashiko-bot @ 2026-07-13 10:11 UTC (permalink / raw)
To: Ibrahim Hashimov; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260713093414.94337-1-security@auditcode.ai>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The newly added length validation uses `dev_warn()` without ratelimiting, allowing a malicious device to spam the kernel log.
--
--- Patch [1]: [PATCH v2] HID: wacom: validate report length in wacom_intuos_pro2_bt_irq ---
commit d2626ddb2110b90160eb60887108918a58cb9412
Author: Ibrahim Hashimov <security@auditcode.ai>
HID: wacom: validate report length in wacom_intuos_pro2_bt_irq
This commit adds length validation to wacom_intuos_pro2_bt_irq to prevent
out-of-bounds reads when parsing Bluetooth reports. It drops undersized
reports and logs a warning before returning.
> diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
> index da1f0ea85625d..af76e49fd0f25 100644
> --- a/drivers/hid/wacom_wac.c
> +++ b/drivers/hid/wacom_wac.c
> @@ -1548,6 +1548,19 @@ static int wacom_intuos_pro2_bt_irq(struct wacom_wac *wacom, size_t len)
> return 0;
> }
>
> + if (wacom->features.type == INTUOSP2_BT ||
> + wacom->features.type == INTUOSP2S_BT) {
> + if (len < 286) {
> + dev_warn(wacom->pen_input->dev.parent,
> + "Pro2 BT report too short: %zu bytes\n", len);
[Severity: Medium]
Since this error path is triggered by external Bluetooth input, can a
malicious or malfunctioning device flood the kernel logs by sending many
undersized reports in rapid succession?
Would it be better to use dev_warn_ratelimited() here to prevent potential
log spam and CPU/IO overhead?
> + return 0;
> + }
> + } else if (len < 46) {
> + dev_warn(wacom->pen_input->dev.parent,
> + "Pro2 BT report too short: %zu bytes\n", len);
[Severity: Medium]
Similarly, could this branch also benefit from dev_warn_ratelimited() to
protect against log flooding from undersized reports?
> + return 0;
> + }
> +
> wacom_intuos_pro2_bt_pen(wacom);
> if (wacom->features.type == INTUOSP2_BT ||
> wacom->features.type == INTUOSP2S_BT) {
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260713093414.94337-1-security@auditcode.ai?part=1
^ permalink raw reply
* Re: [PATCH] HID: playstation: validate num_touch_reports in DualShock 4 reports
From: Lee Jones @ 2026-07-13 11:22 UTC (permalink / raw)
To: FirstName LastName
Cc: Roderick Colenbrander, Jiri Kosina, Benjamin Tissoires,
linux-input, linux-kernel
In-Reply-To: <20260323124737.3223129-1-bsevens@google.com>
Stable Team,
> From: Benoît Sevens <bsevens@google.com>
>
> The DualShock 4 HID driver fails to validate the num_touch_reports field
> received from the device in both USB and Bluetooth input reports.
> A malicious device could set this field to a value larger than the
> allocated size of the touch_reports array (3 for USB, 4 for Bluetooth),
> leading to an out-of-bounds read in dualshock4_parse_report().
>
> This can result in kernel memory disclosure when processing malicious
> HID reports.
>
> Validate num_touch_reports against the array size for the respective
> connection types before processing the touch data.
>
> Signed-off-by: Benoît Sevens <bsevens@google.com>
> ---
> drivers/hid/hid-playstation.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
Could we have this in all branches up to and including linux-6.6.y please?
Upstream commit:
Fixes: 82a4fc463309 ("HID: playstation: validate num_touch_reports in DualShock 4 reports")
--
Lee Jones
^ permalink raw reply
* Re: [PATCH] HID: playstation: validate num_touch_reports in DualShock 4 reports
From: Lee Jones @ 2026-07-13 11:24 UTC (permalink / raw)
To: FirstName LastName, stable
Cc: Roderick Colenbrander, Jiri Kosina, Benjamin Tissoires,
linux-input, linux-kernel
In-Reply-To: <20260713112252.GA3774971@google.com>
[This time with the Stable Team included #fail]
> Stable Team,
>
> > From: Benoît Sevens <bsevens@google.com>
> >
> > The DualShock 4 HID driver fails to validate the num_touch_reports field
> > received from the device in both USB and Bluetooth input reports.
> > A malicious device could set this field to a value larger than the
> > allocated size of the touch_reports array (3 for USB, 4 for Bluetooth),
> > leading to an out-of-bounds read in dualshock4_parse_report().
> >
> > This can result in kernel memory disclosure when processing malicious
> > HID reports.
> >
> > Validate num_touch_reports against the array size for the respective
> > connection types before processing the touch data.
> >
> > Signed-off-by: Benoît Sevens <bsevens@google.com>
> > ---
> > drivers/hid/hid-playstation.c | 12 ++++++++++++
> > 1 file changed, 12 insertions(+)
>
> Could we have this in all branches up to and including linux-6.6.y please?
>
> Upstream commit:
>
> Fixes: 82a4fc463309 ("HID: playstation: validate num_touch_reports in DualShock 4 reports")
--
Lee Jones
^ permalink raw reply
* Re: [PATCH v5 0/3] Input/SPI: fixes for MacBook8,1 DMA timeout, UAF, and NULL pointer dereference
From: Mark Brown @ 2026-07-13 11:36 UTC (permalink / raw)
To: Shih-Yuan Lee; +Cc: Dmitry Torokhov, linux-input, linux-spi, linux-kernel
In-Reply-To: <20260711131140.18777-1-fourdollars@debian.org>
[-- Attachment #1: Type: text/plain, Size: 484 bytes --]
On Sat, Jul 11, 2026 at 09:11:37PM +0800, Shih-Yuan Lee wrote:
> Hi Dmitry, Mark, and the linux-input/linux-spi community,
>
> This patch series addresses a long-standing DMA initialization timeout on the
> early 2015 12" MacBook (MacBook8,1) on any boot (including cold boot), as well
> as two pre-existing, high-severity UAF/NULL-pointer bugs in the applespi driver.
Are there any dependencies between the SPI and input parts of the
series? There's nothing visible...
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* [PATCH] HID: uclogic: fix use-after-free of inrange_timer on remove
From: Ibrahim Hashimov @ 2026-07-13 12:10 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires; +Cc: linux-input, linux-kernel, stable
uclogic_remove() tears down in the wrong order:
timer_delete_sync(&drvdata->inrange_timer);
hid_hw_stop(hdev);
hid_hw_stop() is what actually quiesces the device: it calls
hid_disconnect() (which frees hid->inputs via hidinput_disconnect())
and only then stops the underlying transport, which is what finally
kills the still-submitted interrupt-IN URB. Until hid_hw_stop()
returns, the device can still deliver pen reports, and every pen
report with pen->inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE runs:
mod_timer(&drvdata->inrange_timer, jiffies + msecs_to_jiffies(100));
from uclogic_raw_event_pen(). Calling timer_delete_sync() *before*
hid_hw_stop() only guarantees the timer is idle at that instant - it
does not guarantee it stays idle, because the report path that can
re-arm it is not shut off until hid_hw_stop() returns, several lines
later. A report landing in that window re-arms inrange_timer after
it was supposedly cancelled; uclogic_remove() then returns,
devm_kzalloc() frees drvdata (and hidinput_disconnect() has already
freed the input device drvdata->pen_input points at), and roughly
100 ms later uclogic_inrange_timeout() fires on that freed memory -
a use-after-free in timer-softirq context.
Reaching that window needs nothing exotic: a malicious or
malfunctioning UC-Logic/Huion USB device (or a manual sysfs unbind
racing in-flight reports from a legitimate one) delivering a single
pen report while uclogic_remove() is running is enough to retrigger
mod_timer() after the old timer_delete_sync() call.
Fix this the same way several other HID drivers whose timers are
re-armed from the report path already do it (e.g. hid-appleir.c's
key_up_timer, hid-nvidia-shield.c's psy_stats_timer,
hid-wiimote-core.c's timer, wacom_sys.c's idleprox_timer): quiesce
the hardware with hid_hw_stop() first, then delete the timer.
Once hid_hw_stop() has returned, uclogic_raw_event_pen() cannot run
again for this device, so the subsequent timer_delete_sync() is
guaranteed to be the last write to inrange_timer - there is no
window left in which a report can re-arm it.
This has been verified at runtime on a v6.19 KASAN-instrumented
kernel: a synthesized malicious USB UC-Logic device flooding pen
reports across uclogic_remove() reliably trips a KASAN use-after-free
on the freed hid->inputs list before this fix, in usbhid's
hid_check_keys_pressed()/hid_irq_in() report-delivery path rather
than in uclogic_inrange_timeout() itself, because that synchronous
fault preempts the ~100 ms timer callback. This reorder closes the
inrange_timer race by construction (timer_delete_sync() is now
provably the last write to it), but that captured report-path fault
is a separate, core-level race in usbhid and is not fixed by this
driver-local change.
Fixes: 01309e29eb95 ("HID: uclogic: Support in-range reporting emulation")
Cc: stable@vger.kernel.org
</content>
Signed-off-by: Ibrahim Hashimov <security@auditcode.ai>
Assisted-by: AuditCode-AI:2026.07
---
drivers/hid/hid-uclogic-core.c | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c
index b73f09d26688..925178d8feb4 100644
--- a/drivers/hid/hid-uclogic-core.c
+++ b/drivers/hid/hid-uclogic-core.c
@@ -548,8 +548,35 @@ static void uclogic_remove(struct hid_device *hdev)
{
struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
- timer_delete_sync(&drvdata->inrange_timer);
+ /*
+ * Quiesce the device, and the report-delivery path it feeds, before
+ * tearing down anything the report path can still touch.
+ *
+ * hid_hw_stop() disconnects hid->inputs (hid_disconnect() ->
+ * hidinput_disconnect()) and stops the underlying transport. Only
+ * once it has returned is uclogic_raw_event_pen() guaranteed unable
+ * to run again, since that is the only place inrange_timer gets
+ * re-armed (mod_timer() on every report while pen->inrange ==
+ * UCLOGIC_PARAMS_PEN_INRANGE_NONE).
+ *
+ * Calling timer_delete_sync() first, as the old order did, cancels
+ * the timer while the device can still deliver reports: a report
+ * processed between the timer_delete_sync() call and the eventual
+ * URB shutdown inside hid_hw_stop() re-arms inrange_timer, which is
+ * now left pending across the devm_kzalloc()'d drvdata (and
+ * drvdata->pen_input) being freed. uclogic_inrange_timeout() then
+ * fires ~100 ms later on freed memory.
+ *
+ * Stopping the hardware first and only then deleting the timer
+ * closes that window: hid_hw_stop() will not return until the
+ * device can no longer feed uclogic_raw_event_pen(), so the
+ * timer_delete_sync() call below is guaranteed to be the last write
+ * to inrange_timer. This also matches the ordering already used by
+ * other HID drivers whose timers are re-armed from the report path,
+ * e.g. hid-appleir.c's key_up_timer.
+ */
hid_hw_stop(hdev);
+ timer_delete_sync(&drvdata->inrange_timer);
kfree(drvdata->desc_ptr);
uclogic_params_cleanup(&drvdata->params);
}
--
2.50.1 (Apple Git-155)
^ permalink raw reply related
* Re: [PATCH] HID: uclogic: fix use-after-free of inrange_timer on remove
From: sashiko-bot @ 2026-07-13 12:23 UTC (permalink / raw)
To: Ibrahim Hashimov; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260713121042.2321-1-security@auditcode.ai>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Reordering hid_hw_stop() before timer_delete_sync() introduces a Use-After-Free on the input_dev structure.
--
--- Patch [1]: [PATCH] HID: uclogic: fix use-after-free of inrange_timer on remove ---
commit 43bb5d633bc4358be3fe68adce4de35e0008e236
Author: Ibrahim Hashimov <security@auditcode.ai>
HID: uclogic: fix use-after-free of inrange_timer on remove
This commit attempts to fix a timer re-arming race condition during driver
removal by stopping the hardware with hid_hw_stop() before calling
timer_delete_sync() on the inrange_timer.
> diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c
> index b73f09d26688a..925178d8feb40 100644
> --- a/drivers/hid/hid-uclogic-core.c
> +++ b/drivers/hid/hid-uclogic-core.c
> @@ -548,8 +548,35 @@ static void uclogic_remove(struct hid_device *hdev)
> {
> struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
>
> - timer_delete_sync(&drvdata->inrange_timer);
> + /*
[ ... ]
> + * Stopping the hardware first and only then deleting the timer
> + * closes that window: hid_hw_stop() will not return until the
> + * device can no longer feed uclogic_raw_event_pen(), so the
> + * timer_delete_sync() call below is guaranteed to be the last write
> + * to inrange_timer. This also matches the ordering already used by
> + * other HID drivers whose timers are re-armed from the report path,
> + * e.g. hid-appleir.c's key_up_timer.
> + */
> hid_hw_stop(hdev);
> + timer_delete_sync(&drvdata->inrange_timer);
[Severity: High]
Does this reordering introduce a use-after-free on the input device memory?
When hid_hw_stop() returns, it has already disconnected and freed the input
devices, including the one pointed to by drvdata->pen_input. If the 100ms
timer fires after the input devices are freed but before timer_delete_sync()
completes, uclogic_inrange_timeout() will run and dereference the dangling
drvdata->pen_input pointer:
drivers/hid/hid-uclogic-core.c:uclogic_inrange_timeout()
...
input_report_abs(input, ABS_PRESSURE, 0);
To prevent the timer from being re-armed without violating the safe teardown
order, would it be better to keep the timer cancellation before hid_hw_stop()
but replace timer_delete_sync() with timer_shutdown_sync()?
> kfree(drvdata->desc_ptr);
> uclogic_params_cleanup(&drvdata->params);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260713121042.2321-1-security@auditcode.ai?part=1
^ permalink raw reply
* [PATCH] HID: hyperx: add driver for the HyperX QuadCast 2 mute button
From: Benjamin Blume @ 2026-07-13 12:42 UTC (permalink / raw)
To: linux-input; +Cc: jikos, bentiss, linux-kernel, Benjamin Blume
The tap-to-mute button of the HyperX QuadCast 2 (03f0:07b4) is handled
entirely in the device firmware. The firmware gates the audio internally
but never sends the Telephony "Phone Mute" usage (0x2f) that its own report
descriptor advertises, and it does not touch the UAC feature unit either.
Consequently neither an evdev key event nor an ALSA mixer change is ever
generated, and userspace has no way to learn that the microphone was muted:
desktops keep showing the microphone as live, and conferencing applications
keep displaying an unmuted microphone while transmitting silence.
The mute state is reported through a vendor-defined collection instead:
06 c0 ff Usage Page (Vendor-Defined 0xFFC0)
a1 01 Collection (Application)
06 c1 ff Usage Page (Vendor-Defined 0xFFC1)
85 77 Report ID (0x77)
09 f0 Usage (0xF0)
75 08 95 3f Report Size (8), Report Count (63)
81 02 Input (Data,Var,Abs)
Pressing the button emits a 64-byte report on that collection:
77 06 00 00 ... microphone unmuted
77 06 01 00 ... microphone muted
where byte 1 identifies the mute event and byte 2 carries the resulting
state. As the payload is an opaque vendor blob carrying no HID usages,
hid-input cannot map it and a hwdb entry cannot express it either.
Add a driver that decodes the report and emits KEY_MICMUTE, which makes the
button behave like any other microphone mute key.
Note that the device reports the resulting absolute state, whereas
KEY_MICMUTE is a momentary key that userspace acts on as a toggle, so the
driver emits one keypress per state change.
Tested on a HyperX QuadCast 2 (03f0:07b4).
Signed-off-by: Benjamin Blume <benjaminblume@posteo.de>
---
Notes for reviewers:
The report descriptor also declares a Telephony collection (usage page 0x0b)
with Phone Mute (0x2f) on report ID 5, which is why the device already
advertises KEY_MICMUTE. The firmware never sends that report; the mute state
only ever arrives on the vendor collection decoded here. The driver therefore
reuses the input device of that telephony collection rather than creating a
second one.
Open question: the device reports an absolute mute state, so SW_MUTE_DEVICE
would model it more faithfully than KEY_MICMUTE. I went with KEY_MICMUTE
because that is what desktop environments actually act on today, at the cost
of turning an absolute state into a toggle. Happy to emit the switch in
addition (or instead) if you prefer.
The device also exposes a host-controllable mute LED
(/sys/class/leds/input*::mute), which is left untouched by this patch: the
firmware already drives it in lockstep with its internal mute state.
MAINTAINERS | 6 ++
drivers/hid/Kconfig | 13 +++++
drivers/hid/Makefile | 1 +
drivers/hid/hid-hyperx.c | 117 +++++++++++++++++++++++++++++++++++++++
drivers/hid/hid-ids.h | 1 +
5 files changed, 138 insertions(+)
create mode 100644 drivers/hid/hid-hyperx.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 806bd2d..542d606 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11530,6 +11530,12 @@ F: include/uapi/linux/hid*
F: samples/hid/
F: tools/testing/selftests/hid/
+HID HYPERX DRIVER
+M: Benjamin Blume <benjaminblume@posteo.de>
+L: linux-input@vger.kernel.org
+S: Maintained
+F: drivers/hid/hid-hyperx.c
+
HID LOGITECH DRIVERS
R: Filipe Laíns <lains@riseup.net>
L: linux-input@vger.kernel.org
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index f9bcaeb..e00bac8 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -433,6 +433,19 @@ config HOLTEK_FF
Say Y here if you have a Holtek On Line Grip based game controller
and want to have force feedback support for it.
+config HID_HYPERX
+ tristate "HyperX microphones"
+ depends on USB_HID
+ help
+ Support for the mute button of HyperX microphones.
+
+ The button is handled in the device firmware and only reports the
+ resulting mute state through a vendor-defined collection, so without
+ this driver userspace never learns that the microphone was muted.
+
+ Supported devices:
+ - HyperX QuadCast 2
+
config HID_VIVALDI_COMMON
tristate
help
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 23e6e3d..4138be7 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-mouse.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o
obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
+obj-$(CONFIG_HID_HYPERX) += hid-hyperx.o
obj-$(CONFIG_HID_ICADE) += hid-icade.o
obj-$(CONFIG_HID_ITE) += hid-ite.o
obj-$(CONFIG_HID_JABRA) += hid-jabra.o
diff --git a/drivers/hid/hid-hyperx.c b/drivers/hid/hid-hyperx.c
new file mode 100644
index 0000000..18d2dc2
--- /dev/null
+++ b/drivers/hid/hid-hyperx.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * HID driver for the HyperX QuadCast 2 microphone
+ *
+ * The tap-to-mute button is handled entirely in the device firmware: it gates
+ * the audio internally and does not send the Telephony "Phone Mute" usage its
+ * own report descriptor advertises. The resulting mute state is only reported
+ * through a vendor-defined collection, which hid-input cannot map, so the
+ * button is invisible to userspace.
+ *
+ * Copyright (c) 2026 Benjamin Blume <benjaminblume@posteo.de>
+ */
+
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define HYPERX_QC2_REPORT_ID 0x77
+#define HYPERX_QC2_EVENT_MUTE 0x06
+#define HYPERX_QC2_MUTE_LEN 3
+
+struct hyperx_drvdata {
+ struct input_dev *input;
+ bool muted;
+ bool have_state;
+};
+
+static int hyperx_input_configured(struct hid_device *hdev,
+ struct hid_input *hi)
+{
+ struct hyperx_drvdata *drvdata = hid_get_drvdata(hdev);
+
+ /*
+ * The device exposes several application collections. Prefer the
+ * telephony one, which already advertises KEY_MICMUTE, and fall back
+ * to the first collection otherwise.
+ */
+ if (!drvdata->input || test_bit(KEY_MICMUTE, hi->input->keybit)) {
+ drvdata->input = hi->input;
+ input_set_capability(drvdata->input, EV_KEY, KEY_MICMUTE);
+ }
+
+ return 0;
+}
+
+static int hyperx_raw_event(struct hid_device *hdev, struct hid_report *report,
+ u8 *data, int size)
+{
+ struct hyperx_drvdata *drvdata = hid_get_drvdata(hdev);
+ bool muted;
+
+ if (!(hdev->claimed & HID_CLAIMED_INPUT) || !drvdata->input)
+ return 0;
+
+ if (size < HYPERX_QC2_MUTE_LEN || data[0] != HYPERX_QC2_REPORT_ID ||
+ data[1] != HYPERX_QC2_EVENT_MUTE)
+ return 0;
+
+ muted = data[2];
+ if (drvdata->have_state && muted == drvdata->muted)
+ return 0;
+
+ drvdata->muted = muted;
+ drvdata->have_state = true;
+
+ /*
+ * The device reports the resulting absolute state, while KEY_MICMUTE is
+ * a momentary key that userspace acts on as a toggle. Emit one
+ * keypress per state change.
+ */
+ input_report_key(drvdata->input, KEY_MICMUTE, 1);
+ input_sync(drvdata->input);
+ input_report_key(drvdata->input, KEY_MICMUTE, 0);
+ input_sync(drvdata->input);
+
+ return 0;
+}
+
+static int hyperx_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ struct hyperx_drvdata *drvdata;
+ int ret;
+
+ drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ hid_set_drvdata(hdev, drvdata);
+
+ ret = hid_parse(hdev);
+ if (ret)
+ return ret;
+
+ return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+}
+
+static const struct hid_device_id hyperx_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_HP,
+ USB_PRODUCT_ID_HP_HYPERX_QUADCAST_2) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, hyperx_devices);
+
+static struct hid_driver hyperx_driver = {
+ .name = "hyperx",
+ .id_table = hyperx_devices,
+ .probe = hyperx_probe,
+ .input_configured = hyperx_input_configured,
+ .raw_event = hyperx_raw_event,
+};
+module_hid_driver(hyperx_driver);
+
+MODULE_DESCRIPTION("HID driver for the HyperX QuadCast 2 microphone");
+MODULE_AUTHOR("Benjamin Blume <benjaminblume@posteo.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 1059922..76674b3 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -688,6 +688,7 @@
#define USB_DEVICE_ID_HORI_WIRELESS_SWITCH_PAD 0x00f6
#define USB_VENDOR_ID_HP 0x03f0
+#define USB_PRODUCT_ID_HP_HYPERX_QUADCAST_2 0x07b4
#define USB_PRODUCT_ID_HP_ELITE_PRESENTER_MOUSE_464A 0x464a
#define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A 0x0a4a
#define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A 0x0b4a
--
2.55.0
^ permalink raw reply related
* [PATCH 0/4] HID: Remove redundant error messages on IRQ request failure
From: Pan Chuang @ 2026-07-13 13:24 UTC (permalink / raw)
To: Basavaraj Natikar, Jiri Kosina, Benjamin Tissoires,
Srinivas Pandruvada, Even Xu, Xinpeng Sun, Zhang Lixu,
Andy Shevchenko, Vineeth Pillai, Pan Chuang, Danny D.,
Abhishek Tamboli, Sakari Ailus,
open list:AMD SENSOR FUSION HUB DRIVER, open list
Commit 55b48e23f5c4 ("genirq/devres: Add error handling in
devm_request_*_irq()") added automatic error logging to
devm_request_threaded_irq() and devm_request_any_context_irq()
via the new devm_request_result() helper, which prints device
name, IRQ number, handler functions, and error code on failure.
Since devm_request_irq() is a static inline wrapper around
devm_request_threaded_irq(), it also benefits from this
automatic logging.
Remove the now-redundant dev_err() and dev_err_probe() calls
in hid drivers that follow these devm_request_*_irq()
functions, as the core now provides more detailed diagnostic
information on failure.
Pan Chuang (4):
HID: amd_sfh: Remove redundant dev_err()
HID: hid-goodix: Remove redundant dev_err()
HID: intel-ish-hid: ipc: Remove redundant dev_err()
HID: Intel-thc-hid: Intel-quickspi: Remove redundant dev_err()
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c | 5 +----
drivers/hid/hid-goodix-spi.c | 5 +----
drivers/hid/intel-ish-hid/ipc/pci-ish.c | 4 +---
drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c | 5 +----
4 files changed, 4 insertions(+), 15 deletions(-)
--
2.34.1
^ permalink raw reply
* [PATCH 1/4] HID: amd_sfh: Remove redundant dev_err()
From: Pan Chuang @ 2026-07-13 13:24 UTC (permalink / raw)
To: Basavaraj Natikar, Jiri Kosina, Benjamin Tissoires,
open list:AMD SENSOR FUSION HUB DRIVER, open list
Cc: Pan Chuang
In-Reply-To: <20260713132439.380121-1-panchuang@vivo.com>
Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in
devm_request_*_irq()"), devm_request_irq() automatically logs
detailed error messages on failure. Remove the now-redundant
driver-specific dev_err() calls.
Signed-off-by: Pan Chuang <panchuang@vivo.com>
---
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
index 4b81cebdc335..a2acd3ca20e2 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
@@ -128,11 +128,8 @@ int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata)
rc = devm_request_irq(&privdata->pdev->dev, privdata->pdev->irq,
amd_sfh_irq_handler, 0, DRIVER_NAME, privdata);
- if (rc) {
- dev_err(&privdata->pdev->dev, "failed to request irq %d err=%d\n",
- privdata->pdev->irq, rc);
+ if (rc)
return rc;
- }
return 0;
}
--
2.34.1
^ permalink raw reply related
* [PATCH 2/4] HID: hid-goodix: Remove redundant dev_err()
From: Pan Chuang @ 2026-07-13 13:24 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires, open list:HID CORE LAYER,
open list
Cc: Pan Chuang
In-Reply-To: <20260713132439.380121-1-panchuang@vivo.com>
Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in
devm_request_*_irq()"), devm_request_threaded_irq() automatically logs
detailed error messages on failure. Remove the now-redundant
driver-specific dev_err() calls.
Signed-off-by: Pan Chuang <panchuang@vivo.com>
---
drivers/hid/hid-goodix-spi.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/hid/hid-goodix-spi.c b/drivers/hid/hid-goodix-spi.c
index 288cb827e9d6..03d549efbdce 100644
--- a/drivers/hid/hid-goodix-spi.c
+++ b/drivers/hid/hid-goodix-spi.c
@@ -722,11 +722,8 @@ static int goodix_spi_probe(struct spi_device *spi)
error = devm_request_threaded_irq(&ts->spi->dev, ts->spi->irq,
NULL, goodix_hid_irq, IRQF_ONESHOT,
"goodix_spi_hid", ts);
- if (error) {
- dev_err(ts->dev, "could not register interrupt, irq = %d, %d",
- ts->spi->irq, error);
+ if (error)
goto err_destroy_hid;
- }
return 0;
--
2.34.1
^ permalink raw reply related
* [PATCH 3/4] HID: intel-ish-hid: ipc: Remove redundant dev_err()
From: Pan Chuang @ 2026-07-13 13:24 UTC (permalink / raw)
To: Srinivas Pandruvada, Jiri Kosina, Benjamin Tissoires, Zhang Lixu,
Andy Shevchenko, Vineeth Pillai, Pan Chuang,
open list:INTEL INTEGRATED SENSOR HUB DRIVER, open list
In-Reply-To: <20260713132439.380121-1-panchuang@vivo.com>
Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in
devm_request_*_irq()"), devm_request_irq() automatically logs
detailed error messages on failure. Remove the now-redundant
driver-specific dev_err() calls.
Signed-off-by: Pan Chuang <panchuang@vivo.com>
---
drivers/hid/intel-ish-hid/ipc/pci-ish.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
index 8d36ae96a3ee..e7196e429c8b 100644
--- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
+++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
@@ -232,10 +232,8 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ret = devm_request_irq(dev, pdev->irq, ish_irq_handler,
irq_flag, KBUILD_MODNAME, ishtp);
- if (ret) {
- dev_err(dev, "ISH: request IRQ %d failed\n", pdev->irq);
+ if (ret)
return ret;
- }
dev_set_drvdata(ishtp->devc, ishtp);
--
2.34.1
^ permalink raw reply related
* [PATCH 4/4] HID: Intel-thc-hid: Intel-quickspi: Remove redundant dev_err()
From: Pan Chuang @ 2026-07-13 13:24 UTC (permalink / raw)
To: Even Xu, Xinpeng Sun, Jiri Kosina, Benjamin Tissoires, Pan Chuang,
Sakari Ailus, Abhishek Tamboli, Danny D.,
open list:HID CORE LAYER, open list
In-Reply-To: <20260713132439.380121-1-panchuang@vivo.com>
Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in
devm_request_*_irq()"), devm_request_threaded_irq() automatically logs
detailed error messages on failure. Remove the now-redundant
driver-specific dev_err() calls.
Signed-off-by: Pan Chuang <panchuang@vivo.com>
---
drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
index 4ae2e1718b30..504ef3c842ab 100644
--- a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
+++ b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
@@ -636,11 +636,8 @@ static int quickspi_probe(struct pci_dev *pdev,
quickspi_irq_thread_handler,
IRQF_ONESHOT, KBUILD_MODNAME,
qsdev);
- if (ret) {
- dev_err(&pdev->dev,
- "Failed to request threaded IRQ, irq = %d.\n", pdev->irq);
+ if (ret)
goto dev_deinit;
- }
ret = reset_tic(qsdev);
if (ret) {
--
2.34.1
^ permalink raw reply related
* [PATCH v2] HID: bpf: Fix signedness bug in hid_bpf_hw_request
From: Guangshuo Li @ 2026-07-13 13:26 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires, Greg Kroah-Hartman,
Alexei Starovoitov, Johan Hovold, Guangshuo Li, Puranjay Mohan,
Kees Cook, linux-input, linux-kernel, bpf
hid_bpf_hw_request() clamps the return value of hid_hw_raw_request() to
the size of the caller-supplied buffer before copying data back to the
BPF buffer.
However, ret is signed while size is unsigned. If hid_hw_raw_request()
returns a negative error code, the comparison promotes ret to size_t.
This makes the negative value look like a very large positive value, so
the error is clamped to size. The following memcpy() then treats the
failed request as a successful transfer and copies stale data back to
the caller.
Handle negative return values before comparing ret with size and jump to
the common cleanup path on error. This preserves negative error codes
while still preventing oversized successful returns from overflowing
the caller-supplied buffer.
Fixes: 2b658c1c442e ("HID: bpf: prevent buffer overflow in hid_hw_request")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
v2:
- Handle negative return values before comparing the return length
with the unsigned buffer size, as suggested by Emil Tsalapatis.
- Use the common cleanup path for negative return values.
drivers/hid/bpf/hid_bpf_dispatch.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
index d0130658091b..520b8f56a514 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.c
+++ b/drivers/hid/bpf/hid_bpf_dispatch.c
@@ -445,12 +445,14 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
reqtype,
(u64)(long)ctx,
true); /* prevent infinite recursions */
-
+ if (ret < 0)
+ goto done;
if (ret > size)
ret = size;
if (ret > 0)
memcpy(buf, dma_data, ret);
+done:
kfree(dma_data);
return ret;
}
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 1/4] HID: amd_sfh: Remove redundant dev_err()
From: sashiko-bot @ 2026-07-13 13:34 UTC (permalink / raw)
To: Pan Chuang; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260713132439.380121-2-panchuang@vivo.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] The driver requests a legacy PCI interrupt without the IRQF_SHARED flag and unconditionally returns IRQ_HANDLED.
--
--- Patch [1]: [PATCH 1/4] HID: amd_sfh: Remove redundant dev_err() ---
commit 545a05506a276434e2b80762c55fb8e2b1f6fc64
Author: Pan Chuang <panchuang@vivo.com>
HID: amd_sfh: Remove redundant dev_err()
This commit removes a driver-specific error logging call after
devm_request_irq() because the core API now automatically logs detailed
error messages on failure.
> diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
> index 4b81cebdc3359..a2acd3ca20e2c 100644
> --- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
> +++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
> @@ -128,11 +128,8 @@ int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata)
>
> rc = devm_request_irq(&privdata->pdev->dev, privdata->pdev->irq,
> amd_sfh_irq_handler, 0, DRIVER_NAME, privdata);
[Severity: High]
This is a pre-existing issue, but does this code need to handle shared
interrupts?
Since this requests a legacy PCI interrupt (INTx) with irqflags=0, it requests
exclusive access to the IRQ. If the interrupt is routed to a shared line with
another device, will devm_request_irq() fail with -EBUSY and prevent the
driver from probing?
Additionally, the interrupt handler unconditionally returns IRQ_HANDLED:
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c:amd_sfh_irq_handler() {
amd_sfh_clear_intr(data);
return IRQ_HANDLED;
}
If this driver successfully claims the IRQ first and the line is shared,
would this unconditional return erroneously suppress the kernel's unhandled
interrupt detection for other devices on the same line?
> - if (rc) {
> - dev_err(&privdata->pdev->dev, "failed to request irq %d err=%d\n",
> - privdata->pdev->irq, rc);
> + if (rc)
> return rc;
> - }
>
> return 0;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260713132439.380121-1-panchuang@vivo.com?part=1
^ permalink raw reply
* Re: [PATCH 4/4] HID: Intel-thc-hid: Intel-quickspi: Remove redundant dev_err()
From: sashiko-bot @ 2026-07-13 13:35 UTC (permalink / raw)
To: Pan Chuang; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260713132439.380121-5-panchuang@vivo.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] This problem wasn't introduced by this patch, but the driver double-decrements the runtime PM usage counter in quickspi_probe, leading to an underflow.
--
--- Patch [4]: [PATCH 4/4] HID: Intel-thc-hid: Intel-quickspi: Remove redundant dev_err() ---
commit 8f8bad90f3cb44d16834df11da9c79f13af5488d
Author: Pan Chuang <panchuang@vivo.com>
HID: Intel-thc-hid: Intel-quickspi: Remove redundant dev_err()
This commit removes a redundant dev_err() call after
devm_request_threaded_irq() in the quickspi_probe function, relying on the
core's built-in error logging to handle failures.
> diff --git a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
> index 4ae2e1718b30c..504ef3c842ab6 100644
> --- a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
> +++ b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
> @@ -636,11 +636,8 @@ static int quickspi_probe(struct pci_dev *pdev,
> quickspi_irq_thread_handler,
> IRQF_ONESHOT, KBUILD_MODNAME,
> qsdev);
> - if (ret) {
> - dev_err(&pdev->dev,
> - "Failed to request threaded IRQ, irq = %d.\n", pdev->irq);
> + if (ret)
> goto dev_deinit;
[Severity: High]
This problem wasn't introduced by this patch, but while reviewing
quickspi_probe(), I noticed the driver appears to double-decrement the
runtime PM usage counter later in the same function:
drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c:quickspi_probe() {
...
/* Enable runtime power management */
pm_runtime_use_autosuspend(qsdev->dev);
pm_runtime_set_autosuspend_delay(qsdev->dev, DEFAULT_AUTO_SUSPEND_DELAY_MS);
pm_runtime_put_noidle(qsdev->dev);
pm_runtime_put_autosuspend(qsdev->dev);
...
}
Will this cause a PM runtime usage count underflow?
During device probe, the PCI core inherently takes a PM runtime reference.
Calling both pm_runtime_put_noidle() and pm_runtime_put_autosuspend() drops
two references while only one was acquired. This could potentially break
runtime power management for the device.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260713132439.380121-1-panchuang@vivo.com?part=4
^ permalink raw reply
* Re: [PATCH v2] HID: bpf: Fix signedness bug in hid_bpf_hw_request
From: sashiko-bot @ 2026-07-13 13:38 UTC (permalink / raw)
To: Guangshuo Li; +Cc: dmitry.torokhov, linux-input, bpf
In-Reply-To: <20260713132608.1265541-1-lgs201920130244@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Dereferencing ZERO_SIZE_PTR in hid_bpf_hw_request() when report length is 0, causing a kernel panic.
--
--- Patch [1]: [PATCH v2] HID: bpf: Fix signedness bug in hid_bpf_hw_request ---
commit 87da4183dd7e20066daec7a3b7c00194ac025c96
Author: Guangshuo Li <lgs201920130244@gmail.com>
HID: bpf: Fix signedness bug in hid_bpf_hw_request
This commit fixes a bug in hid_bpf_hw_request() where a negative return
value from hid_hw_raw_request() was improperly compared to an unsigned size,
causing the function to treat the failure as a successful transfer and
copy stale data back to the caller.
> diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
> index d0130658091b0..520b8f56a5146 100644
> --- a/drivers/hid/bpf/hid_bpf_dispatch.c
> +++ b/drivers/hid/bpf/hid_bpf_dispatch.c
> @@ -445,12 +445,14 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
> reqtype,
> (u64)(long)ctx,
> true); /* prevent infinite recursions */
[Severity: High]
This is a pre-existing issue, but can this dereference ZERO_SIZE_PTR and cause
a kernel panic?
If hid_bpf_hw_request() is called with a buffer of size >= 1 for a HID device
report that has a report_len of 0, __hid_bpf_hw_check_params() will clamp
the size to 0:
drivers/hid/bpf/hid_bpf_dispatch.c:__hid_bpf_hw_check_params() {
...
if (*buf__sz > report_len)
*buf__sz = report_len;
...
}
When size is clamped to 0, kmemdup(buf, 0, GFP_KERNEL) allocates 0 bytes and
returns ZERO_SIZE_PTR (0x10). The check for !dma_data passes because
ZERO_SIZE_PTR is not NULL.
The code then evaluates dma_data[0] to pass the report ID to
hid_hw_raw_request(), which will dereference ZERO_SIZE_PTR at memory address
0x10 and crash the kernel. Should we add a check for size == 0 before calling
kmemdup()?
> -
> + if (ret < 0)
> + goto done;
> if (ret > size)
> ret = size;
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260713132608.1265541-1-lgs201920130244@gmail.com?part=1
^ permalink raw reply
* Re: [PATCH 3/4] HID: intel-ish-hid: ipc: Remove redundant dev_err()
From: sashiko-bot @ 2026-07-13 13:43 UTC (permalink / raw)
To: Pan Chuang; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260713132439.380121-4-panchuang@vivo.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] The `bh_hbm_work_fn` background task lacks a loop to process all pending messages, which can result in bus messages getting permanently stuck in the ring buffer (`rd_msg_fifo`).
--
--- Patch [3]: [PATCH 3/4] HID: intel-ish-hid: ipc: Remove redundant dev_err() ---
commit caab51c18c54958eb317830d35603876995d77e0
Author: Pan Chuang <panchuang@vivo.com>
HID: intel-ish-hid: ipc: Remove redundant dev_err()
The commit removes a redundant dev_err() call from ish_probe() after
devm_request_irq(). The devm_request_irq() function handles its own
logging on failure, making the driver-specific error message unnecessary.
> diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
> index ed3405c05e73c..cef1030643f15 100644
> --- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
> +++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
[ ... ]
> @@ -232,10 +232,8 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>
> ret = devm_request_irq(dev, pdev->irq, ish_irq_handler,
> irq_flag, KBUILD_MODNAME, ishtp);
> - if (ret) {
> - dev_err(dev, "ISH: request IRQ %d failed\n", pdev->irq);
> + if (ret)
> return ret;
> - }
>
> dev_set_drvdata(ishtp->devc, ishtp);
While looking at this subsystem, I noticed a pre-existing issue in the
related HBM processing path.
drivers/hid/intel-ish-hid/ishtp/hbm.c:
> void bh_hbm_work_fn(struct work_struct *work)
> {
[ ... ]
> spin_lock_irqsave(&dev->rd_msg_spinlock, flags);
> if (dev->rd_msg_fifo_head != dev->rd_msg_fifo_tail) {
> memcpy(hbm, dev->rd_msg_fifo + dev->rd_msg_fifo_head,
> IPC_PAYLOAD_SIZE);
> dev->rd_msg_fifo_head =
> (dev->rd_msg_fifo_head + IPC_PAYLOAD_SIZE) %
> (RD_INT_FIFO_SIZE * IPC_PAYLOAD_SIZE);
> spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags);
> ishtp_hbm_dispatch(dev, (struct ishtp_bus_message *)hbm);
> } else {
> spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags);
> }
> }
[Severity: High]
This is a pre-existing issue, but does bh_hbm_work_fn() need a loop to
process all pending messages?
Currently, it pops and processes exactly one message from rd_msg_fifo
before returning. If recv_hbm() adds a second message and calls
queue_work() before this worker thread begins execution, the second
queue_work() is a no-op because the work is already pending.
Could this leave crucial IPC bus messages from the firmware stuck in the
rd_msg_fifo ring buffer indefinitely until another arbitrary interrupt
arrives?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260713132439.380121-1-panchuang@vivo.com?part=3
^ permalink raw reply
* Re: [PATCH 3/4] HID: intel-ish-hid: ipc: Remove redundant dev_err()
From: srinivas pandruvada @ 2026-07-13 15:27 UTC (permalink / raw)
To: Pan Chuang, Jiri Kosina, Benjamin Tissoires, Zhang Lixu,
Andy Shevchenko, Vineeth Pillai,
open list:INTEL INTEGRATED SENSOR HUB DRIVER, open list
In-Reply-To: <20260713132439.380121-4-panchuang@vivo.com>
On Mon, 2026-07-13 at 21:24 +0800, Pan Chuang wrote:
> Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in
> devm_request_*_irq()"), devm_request_irq() automatically logs
> detailed error messages on failure. Remove the now-redundant
> driver-specific dev_err() calls.
>
> Signed-off-by: Pan Chuang <panchuang@vivo.com>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> ---
> drivers/hid/intel-ish-hid/ipc/pci-ish.c | 4 +---
> 1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
> b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
> index 8d36ae96a3ee..e7196e429c8b 100644
> --- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
> +++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
> @@ -232,10 +232,8 @@ static int ish_probe(struct pci_dev *pdev, const
> struct pci_device_id *ent)
>
> ret = devm_request_irq(dev, pdev->irq, ish_irq_handler,
> irq_flag, KBUILD_MODNAME, ishtp);
> - if (ret) {
> - dev_err(dev, "ISH: request IRQ %d failed\n", pdev-
> >irq);
> + if (ret)
> return ret;
> - }
>
> dev_set_drvdata(ishtp->devc, ishtp);
>
^ permalink raw reply
* Re: [PATCH 3/4] HID: intel-ish-hid: ipc: Remove redundant dev_err()
From: Andy Shevchenko @ 2026-07-13 16:08 UTC (permalink / raw)
To: Pan Chuang
Cc: Srinivas Pandruvada, Jiri Kosina, Benjamin Tissoires, Zhang Lixu,
Vineeth Pillai, open list:INTEL INTEGRATED SENSOR HUB DRIVER,
open list
In-Reply-To: <20260713132439.380121-4-panchuang@vivo.com>
On Mon, Jul 13, 2026 at 09:24:32PM +0800, Pan Chuang wrote:
> Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in
> devm_request_*_irq()"), devm_request_irq() automatically logs
> detailed error messages on failure. Remove the now-redundant
> driver-specific dev_err() calls.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
From: Erik Håkansson @ 2026-07-13 20:10 UTC (permalink / raw)
To: k8ie; +Cc: jikos, bentiss, lains, hadess, linux-input, linux-kernel
In-Reply-To: <345f7347-30a8-4568-a7a6-c70f54a52a8d@mcld.eu>
Hi,
Thank you for testing this.
I could not reproduce issue 1 locally with my MX Keys for Business, but
I applied your fix since it also works on my hardware. Either the
different keyboard models behave differently, or something differs
between our setups. I folded it into the existing interface handling to
keep the code smaller.
I also noticed that my older Lightspeed receiver exposes interfaces 0
and 1 as boot keyboard and mouse interfaces too, while only interfaces
>= 3 are treated as generic HID. So Bolt appears to need different
interface handling from the existing Lightspeed receiver path.
Issue 2 was easy to reproduce, and I applied your fix more or less
verbatim.
I will send a v2 patch shortly. I would be very grateful if you could
test it again.
Regards,
Erik
^ permalink raw reply
* [PATCH v2 0/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
From: Erik Håkansson @ 2026-07-13 20:12 UTC (permalink / raw)
To: jikos, bentiss
Cc: lains, hadess, k8ie, linux-input, linux-kernel,
Erik Håkansson
In-Reply-To: <345f7347-30a8-4568-a7a6-c70f54a52a8d@mcld.eu>
This patch adds Logitech Bolt receiver support for Logitech HID++
devices so Bolt-connected HID++ peripherals can expose battery
information through the kernel power_supply path with the correct device
model.
Changes in v2:
- Handle only the Bolt receiver/control interface in hid-logitech-dj and
leave the other Bolt receiver interfaces to generic HID handling.
- Handle Bolt HID++ unpair notifications so child HID devices are removed
after unpairing.
Thanks to Kateřina Medvědová for testing v1 on additional Bolt hardware
and identifying that Bolt interfaces 0 and 1 must remain handled by the
generic HID path, and that Bolt unpair notifications need explicit
handling.
Reported by Kateřina Medvědová.
Tested with:
- Logitech MX Keys for Business via Bolt receiver
Erik Håkansson (1):
HID: logitech: add Bolt receiver support for Logitech HID++ devices
drivers/hid/hid-logitech-dj.c | 48 +++++++++++++++++++++++++++++---
drivers/hid/hid-logitech-hidpp.c | 48 ++++++++++++++++++++++++++++++--
2 files changed, 89 insertions(+), 7 deletions(-)
base-commit: 44696aa3a489d2baf58efa61b37833f100072bee
--
2.55.0
^ permalink raw reply
* [PATCH v2 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
From: Erik Håkansson @ 2026-07-13 20:12 UTC (permalink / raw)
To: jikos, bentiss
Cc: lains, hadess, k8ie, linux-input, linux-kernel,
Erik Håkansson
In-Reply-To: <20260713201201.391538-1-erikhakan@gmail.com>
Add Logitech Bolt receiver support to the Logitech HID receiver and
HID++ drivers.
Handle Bolt receiver notifications in hid-logitech-dj and add a
Bolt-specific initialization path in hid-logitech-hidpp, separate from
the existing Unifying receiver path.
This allows Bolt-connected HID++ devices to expose battery information
through the kernel power_supply path, so userspace tools can report
their battery status with the correct device model.
Tested with:
- Logitech MX Keys for Business via Bolt receiver
Reported-by: Kateřina Medvědová <k8ie@mcld.eu>
Link: https://lore.kernel.org/linux-input/345f7347-30a8-4568-a7a6-c70f54a52a8d@mcld.eu/
Signed-off-by: Erik Håkansson <erikhakan@gmail.com>
---
Changes in v2:
- Handle only the Bolt receiver/control interface in hid-logitech-dj and
leave the other Bolt receiver interfaces to generic HID handling.
- Handle Bolt HID++ unpair notifications so child HID devices are removed
after unpairing.
drivers/hid/hid-logitech-dj.c | 48 +++++++++++++++++++++++++++++---
drivers/hid/hid-logitech-hidpp.c | 48 ++++++++++++++++++++++++++++++--
2 files changed, 89 insertions(+), 7 deletions(-)
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 9c574ab8b60b..571d5caa5bb5 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -121,6 +121,7 @@ enum recvr_type {
recvr_type_27mhz,
recvr_type_bluetooth,
recvr_type_dinovo,
+ recvr_type_bolt,
};
struct dj_report {
@@ -1156,6 +1157,10 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev,
logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
workitem.reports_supported |= STD_KEYBOARD;
break;
+ case 0x10:
+ device_type = "Bolt";
+ logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
+ break;
}
/* custom receiver device (eg. powerplay) */
@@ -1745,6 +1750,24 @@ static int logi_dj_hidpp_event(struct hid_device *hdev,
dj_dev = djrcv_dev->paired_dj_devices[device_index];
+ /*
+ * Bolt receivers send explicit unpair notifications as HID++ events;
+ * queue device removal when we receive one.
+ */
+ if (djrcv_dev->type == recvr_type_bolt &&
+ hidpp_report->report_id == REPORT_ID_HIDPP_SHORT &&
+ hidpp_report->sub_id == REPORT_TYPE_NOTIF_DEVICE_UNPAIRED) {
+ struct dj_workitem workitem = {
+ .device_index = device_index,
+ .type = WORKITEM_TYPE_UNPAIRED,
+ };
+
+ kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
+ schedule_work(&djrcv_dev->work);
+ spin_unlock_irqrestore(&djrcv_dev->lock, flags);
+ return false;
+ }
+
/*
* With 27 MHz receivers, we do not get an explicit unpair event,
* remove the old device if the user has paired a *different* device.
@@ -1884,6 +1907,9 @@ static int logi_dj_probe(struct hid_device *hdev,
* treat these as logitech-dj interfaces then this causes input events
* reported through this extra interface to not be reported correctly.
* To avoid this, we treat these as generic-hid devices.
+ *
+ * Bolt receivers only use LOGITECH_DJ_INTERFACE_NUMBER for receiver
+ * reporting. Treat all other Bolt interfaces as generic-hid devices.
*/
switch (id->driver_data) {
case recvr_type_dj: no_dj_interfaces = 3; break;
@@ -1897,10 +1923,20 @@ static int logi_dj_probe(struct hid_device *hdev,
}
if (hid_is_usb(hdev)) {
intf = to_usb_interface(hdev->dev.parent);
- if (intf && intf->altsetting->desc.bInterfaceNumber >=
- no_dj_interfaces) {
- hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
- return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (intf) {
+ bool generic_hid_interface;
+
+ if (id->driver_data == recvr_type_bolt)
+ generic_hid_interface =
+ intf->altsetting->desc.bInterfaceNumber !=
+ LOGITECH_DJ_INTERFACE_NUMBER;
+ else
+ generic_hid_interface =
+ intf->altsetting->desc.bInterfaceNumber >= no_dj_interfaces;
+ if (generic_hid_interface) {
+ hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
+ return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ }
}
}
@@ -2103,6 +2139,10 @@ static const struct hid_device_id logi_dj_receivers[] = {
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_3),
.driver_data = recvr_type_gaming_hidpp_ls_1_3},
+ { /* Logitech Bolt receiver (0xc548) */
+ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+ USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER),
+ .driver_data = recvr_type_bolt},
{ /* Logitech lightspeed receiver (0xc54d) */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_4),
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 90b0184df777..0b5d0a322ae8 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -4161,8 +4161,50 @@ static int hidpp_initialize_battery(struct hidpp_device *hidpp)
return ret;
}
+static bool hidpp_is_bolt_child(struct hid_device *hdev)
+{
+ struct device *parent = hdev->dev.parent;
+ struct hid_device *receiver_hdev;
+
+ if (!parent)
+ return false;
+
+ receiver_hdev = to_hid_device(parent);
+ return receiver_hdev->vendor == USB_VENDOR_ID_LOGITECH &&
+ receiver_hdev->product == USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER;
+}
+
+static int hidpp_bolt_init(struct hidpp_device *hidpp)
+{
+ struct hid_device *hdev = hidpp->hid_dev;
+ char *name;
+ int ret;
+
+ ret = hidpp_serial_init(hidpp);
+ if (ret)
+ return ret;
+
+ name = hidpp_get_device_name(hidpp);
+ if (!name)
+ return -EIO;
+
+ snprintf(hdev->name, sizeof(hdev->name), "%s", name);
+ dbg_hid("HID++ Bolt: Got name: %s\n", name);
+
+ kfree(name);
+ return 0;
+}
+
+static int hidpp_receiver_init(struct hidpp_device *hidpp)
+{
+ if (hidpp_is_bolt_child(hidpp->hid_dev))
+ return hidpp_bolt_init(hidpp);
+
+ return hidpp_unifying_init(hidpp);
+}
+
/* Get name + serial for USB and Bluetooth HID++ devices */
-static void hidpp_non_unifying_init(struct hidpp_device *hidpp)
+static void hidpp_non_receiver_init(struct hidpp_device *hidpp)
{
struct hid_device *hdev = hidpp->hid_dev;
char *name;
@@ -4510,9 +4552,9 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
/* Get name + serial, store in hdev->name + hdev->uniq */
if (id->group == HID_GROUP_LOGITECH_DJ_DEVICE)
- hidpp_unifying_init(hidpp);
+ hidpp_receiver_init(hidpp);
else
- hidpp_non_unifying_init(hidpp);
+ hidpp_non_receiver_init(hidpp);
if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
connect_mask &= ~HID_CONNECT_HIDINPUT;
--
2.55.0
^ permalink raw reply related
* Re: [PATCH v2 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
From: sashiko-bot @ 2026-07-13 20:24 UTC (permalink / raw)
To: Erik Håkansson; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260713201201.391538-2-erikhakan@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] logi_dj_remove() cancels djrcv_dev->work before disabling hardware interrupts, allowing new work to be scheduled during teardown and causing a Use-After-Free.
--
--- Patch [1]: [PATCH v2 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices ---
commit 971b266887902a1a6dc0bffd56ec903cd5386ed8
Author: Erik Håkansson <erikhakan@gmail.com>
HID: logitech: add Bolt receiver support for Logitech HID++ devices
Add Logitech Bolt receiver support to the Logitech HID receiver and HID++
drivers. This allows Bolt-connected HID++ devices to expose battery
information through the kernel power_supply path.
Link: https://lore.kernel.org/linux-input/345f7347-30a8-4568-a7a6-c70f54a52a8d@mcld.eu/
> diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
> index 381e4dc5aba7a..112ea6a7b2a65 100644
> --- a/drivers/hid/hid-logitech-dj.c
> +++ b/drivers/hid/hid-logitech-dj.c
[ ... ]
> @@ -1745,6 +1750,24 @@ static int logi_dj_hidpp_event(struct hid_device *hdev,
>
> dj_dev = djrcv_dev->paired_dj_devices[device_index];
>
> + /*
> + * Bolt receivers send explicit unpair notifications as HID++ events;
> + * queue device removal when we receive one.
> + */
> + if (djrcv_dev->type == recvr_type_bolt &&
> + hidpp_report->report_id == REPORT_ID_HIDPP_SHORT &&
> + hidpp_report->sub_id == REPORT_TYPE_NOTIF_DEVICE_UNPAIRED) {
> + struct dj_workitem workitem = {
> + .device_index = device_index,
> + .type = WORKITEM_TYPE_UNPAIRED,
> + };
> +
> + kfifo_in(&djrcv_dev->notif_fifo, &workitem, sizeof(workitem));
> + schedule_work(&djrcv_dev->work);
[Severity: High]
This is a pre-existing issue, but can this sequence cause a use-after-free
during device removal?
Looking at logi_dj_remove() in drivers/hid/hid-logitech-dj.c, it cancels
the work queue before stopping the hardware:
drivers/hid/hid-logitech-dj.c:logi_dj_remove() {
...
cancel_work_sync(&djrcv_dev->work);
hid_hw_close(hdev);
hid_hw_stop(hdev);
...
}
If a user unplugs the USB receiver, and a Bolt unpair notification arrives
right after cancel_work_sync() finishes but before hid_hw_stop() disables
hardware events, will this schedule_work() call queue a new work item on a
djrcv_dev structure that is about to be freed?
> + spin_unlock_irqrestore(&djrcv_dev->lock, flags);
> + return false;
> + }
> +
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260713201201.391538-2-erikhakan@gmail.com?part=1
^ permalink raw reply
* Re: [PATCH v2 1/1] HID: logitech: add Bolt receiver support for Logitech HID++ devices
From: Kateřina Medvědová @ 2026-07-13 21:09 UTC (permalink / raw)
To: erikhakan; +Cc: bentiss, hadess, jikos, k8ie, lains, linux-input, linux-kernel
In-Reply-To: <20260713201201.391538-2-erikhakan@gmail.com>
Hi,
I tested your V2 and both issues were resolved.
Not sure what caused issue number 1 on my system. I can try to dig
deeper if it would help.
I have 3 Bolt receivers on hand. Two of them have much newer firmware
(5.3.20, revision 3). The other one is on 5.0.9. Unfortunately I'm not
sure which of them I was testing on.
AFAIK the only way to get this information is through Options+.
I'm so glad you're taking this on! I'll keep this on my system for daily
driving, I love that the battery reporting works!
Thanks,
Kateřina Medvědová
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox