* [PATCH AUTOSEL 6.18-5.10] HID: rmi: check report length before trimming sentinel bytes
[not found] <20261019135441.1420968-1-sashal@kernel.org>
@ 2026-10-19 13:45 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18] HID: universal-pidff: Add support for Turtle Beach VelocityOne Race Sasha Levin
` (15 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:45 UTC (permalink / raw)
To: patches, stable
Cc: Pengpeng Hou, Jiri Kosina, Sasha Levin, jikos, bentiss,
linux-input, linux-kernel
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
[ Upstream commit 28a3e326fad2451bdb66b747dd1f7ccbb900eed6 ]
rmi_check_sanity() trims trailing 0xff sentinel bytes, but its loop
reads data[valid_size - 1] before checking that valid_size is non-zero.
Reverse the condition so the length is proved before the last byte is
inspected.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **pending-6.12** (`6.12.111`). The buggy
`rmi_check_sanity()` loop is still present, the one-line short-circuit
reorder is not an ancestor of HEAD, and the patch applies here with only
a line-number offset.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[HID: rmi]** **[check]** check report length before trimming
sentinel bytes. Same class of wording as other HID length-check fixes:
the length must be proved before `data[valid_size - 1]` is read.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- Signed-off-by: Pengpeng Hou \<pengpeng@iscas.ac.cn\> (author)
- Signed-off-by: Jiri Kosina \<jkosina@suse.com\> (HID maintainer)
- No Fixes:, Reported-by, Tested-by, Reviewed-by, Acked-by, Link:, or
Cc: stable (absence is expected for this review pipeline)
- Ignore any pipeline “Upstream commit” / Sasha Levin SOB markers
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: `rmi_check_sanity()` trims trailing `0xff` sentinels but
evaluates `data[valid_size - 1]` before `valid_size > 0`.
- Symptom: one-byte out-of-bounds read when the loop has already trimmed
the buffer to length 0.
- Root cause: C `&&` is left-to-right; the original order does the index
first.
- No stack traces, syzbot IDs, or version list in the message.
- Introducer (from git, not the message): `5b65c2a029664` (“HID: rmi:
check sanity of the incoming report”, 2014-09-10), first tagged
`v3.18-rc1`.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. It is an explicit short-circuit-order
OOB fix. The `valid_size > 0` test was already there; it was just on the
wrong side of `&&`.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/hid/hid-rmi.c` (1 insertion, 1 deletion)
- Function: `rmi_check_sanity()`
- Scope: single-file, one-line surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Before: `while ((data[valid_size - 1] == 0xff) && valid_size > 0)` —
when `valid_size` is 0, `data[-1]` is still read.
- After: `while (valid_size > 0 && data[valid_size - 1] == 0xff)` — the
subscript is not evaluated on an empty buffer.
- Path: runtime HID `raw_event` input, not probe/error-only.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **Memory safety / OOB read.** HID core rejects a zero-length
report (`hid_input_report()` returns if `!size`), so the realistic
trigger is trimming an all-`0xff` (or fully trailing-`0xff`) report down
to 0, then doing one more iteration. That is the exact Dell XPS 13 9333
bus-sentinel case this helper was written for. One OOB byte is compared
to `0xff` and discarded; it is not copied to userspace, so this is not
an info leak, but it is still undefined-behavior / KASAN-class.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct C short-circuit reorder. No API, locking, or
control-flow change beyond skipping the illegal index. Regression risk
is negligible. `rmi_raw_event()` already drops `size < 2` after this
call.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record: Line 389 blamed to `5b65c2a029664` (Benjamin Tissoires,
2014-09-10). Present since **v3.18-rc1**. Long-lived in this 6.12 tree.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No Fixes: tag. Introducer confirmed via blame: `5b65c2a029664`
is an ancestor of HEAD.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Candidate SHA on master: `28a3e326fad2451bdb66b747dd1f7ccbb900eed6`
(author date 2026-06-30, committer 2026-08-03). `git merge-base --is-
ancestor` vs HEAD: **not in this tree**.
- Related later commit already here: `ab2958e0c94ed` / upstream
`183da103022ec` “HID: rmi: fix OOB access with undersized RMI reports”
— probe-time report-size clamps and copy bounds. **Does not change
this loop.**
- Standalone one-line patch, not “X/Y”.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Pengpeng Hou is not the HID maintainer. Jiri Kosina applied it.
No other hid-rmi commits from this author in this checkout.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: None. Same `while` line exists here. `git apply --check` of
`28a3e326fad24` succeeded (hunk offset 21 from the later OOB patch).
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 28a3e326fad24`:
https://patch.msgid.link/2026063007016439.1-ccfa108-0006-HID-rmi-
check-report-length-pengpeng@iscas.ac.cn
- `b4 dig -a`: **v1 only** (2026-06-30).
- Thread (3 messages): submission; Sashiko bot flagging **unrelated pre-
existing** read/write OOB in `rmi_hid_{read,write}_block` (later the
undersized-report patch already in this tree); Jiri Kosina “Applied,
thanks.” (2026-08-03).
- No NAK. No reviewer asked for Cc: stable.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To Jiri Kosina and Benjamin Tissoires; Cc linux-
input and linux-kernel. HID maintainers were on the original To: line.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla link on this patch. The sentinel behavior
itself is documented in-tree and in `5b65c2a029664` (Red Hat bugzilla
1123584 for Dell XPS 13 9333). That is the hardware path that can fill a
report with `0xff` and drive this loop to length 0.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone. Sibling OOB work (`HID: rmi: fix OOB access with
undersized RMI reports`) is already on pending-6.12 and does not subsume
this change.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: **UNVERIFIED** — `lore.kernel.org/stable/?q=...` returned HTTP
403. No evidence in the linux-input thread that stable was discussed or
rejected.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `rmi_check_sanity()` only.
**Step 5.2: TRACE CALLERS**
Record: Sole caller is `rmi_raw_event()` (`drivers/hid/hid-rmi.c`),
registered as `.raw_event`. HID core `hid_input_report()`
(`drivers/hid/hid-core.c`) calls it after rejecting empty reports and
resolving a valid `hid_report`. hid-rmi has no `report_table`, so
`hid_match_report()` matches all reports. `rmi_raw_event()` then
requires `RMI_DEVICE` (set after probe validates RMI report IDs).
**Step 5.3: TRACE CALLEES**
Record: The function only indexes `data[]` and decrements `valid_size`.
No alloc/lock/I/O.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: USB/i2c HID interrupt → `hid_input_report()` → `rmi_raw_event()`
→ `rmi_check_sanity()`. Reachable from Synaptics RMI touchpads
(`HID_GROUP_RMI` in `hid_scan_report()`, plus specific USB IDs: Razer
Blade, Lenovo X1 cover, Primax, Acer Switch). Unprivileged USB can also
feed HID reports. Userspace-reachable: **yes** (device I/O, not a
syscall that crafts the buffer directly).
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Only this loop in hid-rmi. Same-tree HID length checks already
backported include `HID: lg4ff: validate report length before fixed
offsets` and `HID: wacom: validate report length in
wacom_intuos_pro2_bt_irq`.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** `drivers/hid/hid-rmi.c` lines 389–390:
`while ((data[valid_size - 1] == 0xff) && valid_size > 0)`. Introduced
v3.18, still here on 6.12.111. Candidate `28a3e326fad24` is **not** an
ancestor of HEAD.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply with +21 line offset. No refactor of this helper.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: `ab2958e0c94ed` is a different OOB (report descriptor / copy
length). It does not reorder this condition. No earlier equivalent of
this one-liner.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **HID / hid-rmi** (Synaptics RMI4 over i2c-hid/usbhid).
**IMPORTANT** for laptops with Synaptics HID touchpads; not mm/VFS core,
but not staging/obscure either.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: hid-rmi is mature (2014+). Recent churn is security-style OOB
hardening, not a rewrite of this path.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver-specific: CONFIG_HID_RMI / Synaptics RMI HID devices
(common on some Dell/Lenovo/Acer laptops). Also any malicious HID gadget
bound as hid-rmi.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: A report whose remaining bytes are all `0xff` (documented XPS 13
9333 bus glitch, or a device sending that pattern). After the last
decrement, `valid_size == 0` and the next condition still reads
`data[-1]`. Not every report; it is the sentinel path this function
exists to handle. Physical HID access required; not a random
unprivileged syscall.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: One-byte heap underflow read. Typical result: KASAN report;
crash only if that byte is unmapped (uncommon for kmalloc). Not data
corruption. **Severity: HIGH** for memory safety / HID attack surface,
not a guaranteed panic.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- Benefit: stops a real OOB on a long-lived, hardware-motivated path; 1
line.
- Risk: very low (boolean operand swap).
- Ratio: strongly in favor of backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real OOB; the `> 0` check was present but evaluated too late.
- Trigger matches the in-tree Dell XPS sentinel comment, not a
hypothetical size=0 from HID core.
- Code has been in this tree since v3.18.
- 1-line, obviously correct; HID maintainer applied v1 as-is.
- Applies cleanly; no prerequisites.
- Same class as other HID length-check stable backports already on this
branch.
AGAINST:
- No Fixes:/Cc: stable/syzbot (not a negative under these rules).
- Single-byte read, not a demonstrated oops or leak.
- Affects hid-rmi users, not every machine.
UNRESOLVED:
- Could not search lore.kernel.org/stable (HTTP 403).
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — C short-circuit; applied by
Jiri Kosina.
2. Fixes a real bug that affects users? **PASS** — OOB on the sentinel-
trim path this driver documents.
3. Important issue? **PASS** — memory-safety OOB on HID input (HIGH, not
a guaranteed panic).
4. Small and contained? **PASS** — 1 line, one function.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — buggy line present; `git
apply --check` succeeded.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: None. Ordinary small bugfix.
**Step 9.4: MAKE YOUR DECISION**
This belongs on **this** 6.12 tree: the bug exists here, the later
undersized-report patch does not fix it, and the change is a one-line
operand swap with no API or locking impact.
===============================================================
What the commit solves for stable users
===============================================================
`rmi_check_sanity()` is supposed to strip trailing `0xff` filler from
Synaptics HID reports. Because `&&` evaluates left-to-right, an all-
sentinel report is trimmed to length 0 and then still reads `data[-1]`.
Laptop touchpads that hit that bus glitch, and USB HID devices that send
the same pattern, can fire a KASAN OOB on every such report. Reordering
the condition makes the existing length check actually protect the
index.
Risk vs benefit: benefit is a real memory-safety hole on a driver
already receiving other OOB backports; risk is a one-line boolean
reorder. No dependencies beyond code that has been here since v3.18.
===============================================================
Verification
===============================================================
- [Phase 1] Parsed subject/body/tags: no Fixes/Reported-by/Cc: stable;
SOBs Hou + Kosina.
- [Phase 2] Diff: 1 line in `rmi_check_sanity()`; operand order only.
- [Phase 3] `git describe HEAD` / Makefile: **pending-6.12, 6.12.111**.
- [Phase 3] `git blame -L 379,410 -- drivers/hid/hid-rmi.c`: introducer
`5b65c2a029664` (v3.18-rc1).
- [Phase 3] `git merge-base --is-ancestor 5b65c2a029664 HEAD`: yes;
`28a3e326fad24`: **no**.
- [Phase 3] Current file still has `while ((data[valid_size - 1] ==
0xff) && valid_size > 0)`.
- [Phase 3] Related `ab2958e0c94ed` already in tree; does not touch this
loop.
- [Phase 3] `git show 28a3e326fad24 | git apply --check`: hunk succeeded
at offset 21.
- [Phase 4] `b4 dig -c 28a3e326fad24`: lore msgid
`2026063007016439.1-ccfa108-...`; To: Kosina + Tissoires.
- [Phase 4] `b4 dig -a`: v1 only; Kosina “Applied, thanks.”
- [Phase 4] Mbox: Sashiko comments are about other pre-existing OOBs,
not this line.
- [Phase 5] Callers: `rmi_raw_event` ← `hid_input_report`; empty `size`
rejected at hid-core.c:2111–2115.
- [Phase 6] Bug present; apply clean; no duplicate fix.
- [Phase 8] Failure mode: 1-byte OOB read on all-`0xff` reports; HID
input path.
- UNVERIFIED: stable@ lore search (HTTP 403).
**YES**
drivers/hid/hid-rmi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
index d55a0388895fb..ecc19387f6b05 100644
--- a/drivers/hid/hid-rmi.c
+++ b/drivers/hid/hid-rmi.c
@@ -386,7 +386,7 @@ static int rmi_check_sanity(struct hid_device *hdev, u8 *data, int size)
* such reports here.
*/
- while ((data[valid_size - 1] == 0xff) && valid_size > 0)
+ while (valid_size > 0 && data[valid_size - 1] == 0xff)
valid_size--;
return valid_size;
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH AUTOSEL 6.18] HID: universal-pidff: Add support for Turtle Beach VelocityOne Race
[not found] <20261019135441.1420968-1-sashal@kernel.org>
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] HID: rmi: check report length before trimming sentinel bytes Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18] HID: Intel-thc-hid: Intel-quicki2c: Fix buffer overflow Sasha Levin
` (14 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Tomasz Pakuła, Jiri Kosina, Sasha Levin, jikos, bentiss,
oleg, linux-input, linux-kernel
From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
[ Upstream commit 53f7f7955a684e820bdd6bd6792c45c4b434f637 ]
Add usb VID and device PID to hid-ids.h
Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
## Phase 1: Commit message forensics
**Step 1.1 — Subject**
- Record: `[HID / universal-pidff] [Add] USB VID/PID so Turtle Beach
VelocityOne Race binds to the existing hid-universal-pidff driver`
**Step 1.2 — Tags**
- Record:
- `Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>`
(author; co-author of this driver)
- `Signed-off-by: Jiri Kosina <jkosina@suse.com>` (HID maintainer)
- `[Upstream commit 53f7f7955a684e820bdd6bd6792c45c4b434f637]` and
`Signed-off-by: Sasha Levin` ignored as pipeline markers
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, `Link:`, or `Cc: stable` (absence of the last two is expected)
**Step 1.3 — Body**
- Record: Body is one sentence: “Add usb VID and device PID to hid-
ids.h”. No crash, leak, or corruption described. The claimed intent is
hardware enablement for one USB HID device. No version range given.
Root cause as stated: the IDs were missing from the existing driver’s
table.
**Step 1.4 — Hidden bug fix?**
- Record: Not a disguised leak/race/UAF. It is a USB ID addition to an
existing driver (stable exception category 1).
---
## Phase 2: Diff analysis
**Step 2.1 — Inventory**
- Record:
- `drivers/hid/hid-ids.h`: +3 (two `#define`s plus a blank line)
- `drivers/hid/hid-universal-pidff.c`: +1 in
`universal_pidff_devices[]`
- Net +4 lines, two files, one table plus ID macros
- Classification: single-purpose, surgical device-ID add
**Step 2.2 — Code flow**
- Record:
- Before: `0x10f5:0x7077` is unmatched by this driver and falls
through to generic HID.
- After: HID core matches `HID_USB_DEVICE(USB_VENDOR_ID_TURTLE_BEACH,
USB_DEVICE_ID_TB_VELOCITYONE_RACE)` and calls
`universal_pidff_probe()`.
- Path: device enumeration / probe, not an error path. No
`driver_data` quirks.
**Step 2.3 — Bug mechanism**
- Record: `[Hardware enablement / USB device ID]` — the driver already
implements PID force-feedback wrapping; this only lists one more
VID/PID. Not UAF, leak, race, overflow, or init-bug.
**Step 2.4 — Fix quality**
- Record: Obviously correct as an ID table add. Insertion sits
alphabetically between TURBOX and TWINHAN. Vendor `0x10f5` already
identifies Turtle Beach elsewhere (`drivers/input/joystick/xpad.c`
uses `0x10f5` with other PIDs `0x7005`/`0x7008`/`0x7073`). PID
`0x7077` does not collide with those. No public API change. Regression
risk is low: only this VID:PID binds; probe returns 0 even if the PID
usage page is absent.
---
## Phase 3: Git history
**Step 3.1 — Blame**
- Record: New lines; they did not exist before this commit. Surrounding
`hid-ids.h` TURBOX/TWINHAN macros date to 2008–2017. The device table
terminator was last touched by `5b9cae8c6472e` (clang-format, 2025).
The driver itself was added in `f06bf8d94fffb` (“HID: Add hid-
universal-pidff driver and supported device ids”, 2025-02-03; `git
describe` of that commit is `v6.13-4738-gf06bf8d94fffb`).
**Step 3.2 — Fixes: tag**
- Record: No `Fixes:` tag. Not applicable.
**Step 3.3 — File history**
- Record: Recent related commits on this driver: Asetek ID adds
(`c385f61108d40`), spelling/format nits, and `01d9874e84d3a` (stop
device on FF init failure). No prerequisite refactor is required for
this ID. Standalone; not “patch X/Y”. No later follow-up on these
files after this commit.
**Step 3.4 — Author**
- Record: Tomasz Pakuła is a listed `MODULE_AUTHOR` of `hid-universal-
pidff.c` and a frequent hid-pidff contributor (overflow, NPD,
playback, Asetek IDs). This is the subsystem’s own device-table
maintainer, not a drive-by.
**Step 3.5 — Dependencies**
- Record: Needs `hid-universal-pidff.c`, `USB_VENDOR_ID_*` macros, and
`hid_pidff_init_with_quirks`. All are in this tree. `git merge-base
--is-ancestor f06bf8d94fffb HEAD` succeeds; `git merge-base --is-
ancestor f06bf8d94fffb v6.18` also succeeds. Can apply standalone.
---
## Phase 4: Mailing list / external research
**Step 4.1 — Original discussion**
- Record: `b4 dig -c 53f7f7955a684e820bdd6bd6792c45c4b434f637` → https:/
/patch.msgid.link/20260922131758.1242755-1-
tomasz.pakula.oficjalny@gmail.com
- `b4 dig -a`: single v1 series only; no v2/v3.
- LKML: https://lkml.iu.edu/2609.2/17309.html (submission),
https://lkml.iu.edu/2609.2/21230.html (Jiri Kosina: “Applied,
thanks.”)
- No NAK, no requested changes, no stable nomination in review.
lore.kernel.org fetch returned 403; discussion confirmed via `b4 dig`
+ LKML/Patchew mirrors.
**Step 4.2 — Recipients (`b4 dig -w`)**
- Record: `jikos@kernel.org` (HID maintainer), `oleg@makarenk.ooo` (co-
author), `linux-input@vger.kernel.org`, `linux-
kernel@vger.kernel.org`. Right lists and maintainer were on Cc; Kosina
applied it.
**Step 4.3 — Bug report**
- Record: No `Reported-by` / syzbot / bugzilla. Phoronix (secondary, not
a kernel bug tracker) notes basic HID input already worked and this
listing improves FF for the VelocityOne Race. That is consistent with
an ID add, not a crash fix.
**Step 4.4 — Series context**
- Record: Standalone one-patch series. Same pattern as earlier Asetek ID
adds in this driver.
**Step 4.5 — Stable list**
- Record: `WebFetch` of `https://lore.kernel.org/stable/?q=VelocityOne`
returned 403. Web search did not show a stable-list thread about this
patch. UNVERIFIED that nobody discussed it on stable@; no evidence of
a NAK there either.
---
## Phase 5: Code semantic analysis
**Step 5.1 — Functions**
- Record: No function body changed. Data only:
`universal_pidff_devices[]` plus two macros. Probe path that becomes
reachable: `universal_pidff_probe` → `universal_pidff_input_mapping` /
`universal_pidff_input_configured`.
**Step 5.2 — Callers**
- Record: `universal_pidff_probe` is only the `.probe` of `struct
hid_driver universal_pidff`, registered via `module_hid_driver`.
Invoked by HID/USB enumeration when VID:PID matches. Not IRQ, not a
syscall hot path.
**Step 5.3 — Callees**
- Record: `hid_parse`, `hid_hw_start`, `hid_pidff_init_with_quirks`,
`hid_hw_stop`. Existing, already used by every other ID in the table.
**Step 5.4 — Reachability**
- Record: Reachable when a user plugs in `10f5:7077` and
`CONFIG_HID_UNIVERSAL_PIDFF` is enabled (`depends on USB_HID &&
HID_PID`). Userspace cannot trigger it without that hardware.
**Step 5.5 — Similar patterns**
- Record: Same table already lists Moza, Cammus, VRS, FFBeast, Lite
Star/PXN, Asetek. This is the established way this driver gains
devices. Turtle Beach VID `0x10f5` is already used in `xpad.c` for
other products; PID `0x7077` is unique.
---
## Phase 6: Local tree (this checkout)
**Step 6.1 — Does the code exist here?**
- Record: Local tree is **6.18.57** (`make kernelversion`; `git describe
HEAD` = `v6.18.57-155-gcdf239ca885b2`). `hid-universal-pidff.c`
exists. Driver intro `f06bf8d94fffb` is an ancestor of both `HEAD` and
`v6.18`. Parent of this candidate still has the Asetek rows and the
empty terminator; the ID macros were absent (`git grep
USB_VENDOR_ID_TURTLE` on the parent was empty). The hardware and
driver this listing targets are in this tree.
**Step 6.2 — Backport difficulty**
- Record: Clean apply. Parent context matches the provided diff (TURBOX
block, then TWINHAN; Asetek entries then `{}`). No refactor gap.
**Step 6.3 — Related fixes already here?**
- Record: No other VelocityOne Race HID listing. No alternate fix for
`10f5:7077` in HID. `xpad.c` does not claim PID `0x7077`.
---
## Phase 7: Subsystem context
**Step 7.1**
- Record: `[HID USB force-feedback helper] [IMPORTANT for owners of
listed wheels; PERIPHERAL vs core kernel]`. Not mm/fs/net core.
Optional `CONFIG_HID_UNIVERSAL_PIDFF`.
**Step 7.2**
- Record: Actively maintained in 2025–2026 (quirks, Asetek IDs, pidff
correctness fixes). Mature enough that ID adds are the normal
extension mechanism.
---
## Phase 8: Impact and risk
**Step 8.1 — Who is affected**
- Record: Driver-specific / config-specific: users who own a Turtle
Beach VelocityOne Race and enable this HID driver. Everyone else is
unchanged.
**Step 8.2 — Trigger**
- Record: Plug in that USB wheel. Not a race. Unprivileged user can plug
hardware; no syscall exploit surface beyond normal HID.
**Step 8.3 — Failure mode without the patch**
- Record: Device stays on hid-generic: basic input, missing this
driver’s PID FF init and button-range mapping. Not
oops/deadlock/corruption. Severity for those users: functional
hardware gap (FF), **MEDIUM** as a bug, but it is the documented
device-ID exception.
**Step 8.4 — Risk vs benefit**
- Record: Benefit: FF/PID support for this wheel on 6.18.y without a
full kernel upgrade. Risk: very low (4 lines, match is VID+PID, no
quirk, probe already tolerates missing PID page). Ratio: favorable for
a device-ID add.
---
## Phase 9: Synthesis
**Step 9.1 — Evidence**
For:
- USB ID add to a driver that already exists in this 6.18 tree (stable
exception 1).
- +4 lines, no new APIs, no new driver, no new sysfs/module params.
- HID maintainer applied v1 with no objections.
- Author maintains this driver.
- VID `0x10f5` is already Turtle Beach in-tree; PID does not clash with
xpad entries.
- Applies cleanly here.
Against:
- Not a crash/security/corruption fix.
- Short commit message; no `Reported-by`.
- Niche ~$650 sim-racing hardware.
- Improves FF rather than repairing a generic HID oops.
Unresolved:
- lore.kernel.org HTTP 403; stable@ thread not confirmed.
- No in-tree test that this exact PID speaks USB PID FF (same as other
IDs in this table).
**Step 9.2 — Stable rules**
1. Obviously correct and tested? **PASS** — mechanical ID add;
maintainer applied it. No in-tree Tested-by, but the change is the
same class as prior IDs in this file.
2. Real issue affecting users? **PASS** — without the ID, this wheel
does not get the existing PID FF path.
3. Important (crash/security/deadlock) **or** listed exception? **PASS**
— USB device ID on an existing driver.
4. Small and contained? **PASS** — 4 lines, two files.
5. No new features/APIs? **PASS** — no new driver, ioctl, or userspace
ABI; only an ID in an existing table.
6. Applies to this tree? **PASS** — driver and insertion point are
present on 6.18.57.
**Step 9.3 — Exception**
- Record: **NEW DEVICE ID** (USB VID/PID) on existing `hid-universal-
pidff`.
**Step 9.4 — Decision**
This is exactly the device-ID class stable trees take. The driver is in
6.18; the patch is tiny and isolated to `10f5:7077`. Benefit is real for
owners of that wheel; risk to everyone else is negligible.
---
### What the commit does for this tree
It lists Turtle Beach VelocityOne Race (`USB 10f5:7077`) in `hid-
universal-pidff` so 6.18 systems can use the PID force-feedback path
already in this kernel, instead of generic HID only.
### Stable-rules fit
Meets the device-ID exception: existing driver, IDs only, clean apply,
no new API.
### Risk vs benefit
Very low risk, localized hardware enablement. No locking or error-path
change.
### Concerns
None that block backport. No extra quirks or follow-up commits required
in this tree. Stable-list discussion could not be fetched (403).
---
Verification:
- [Phase 1] Parsed tags: author SOB + Jiri Kosina SOB; no
Fixes/Reported-by/Cc:stable
- [Phase 1] Body is a one-line ID add, not a crash write-up
- [Phase 2] Diff: +3 `hid-ids.h`, +1 table row; no function logic change
- [Phase 2] No `driver_data` quirk on the new entry
- [Phase 3] `git blame` on new macros → this commit; surrounding IDs
from 2008–2017
- [Phase 3] Driver intro `f06bf8d94fffb` (`v6.13-4738-gf06bf8d94fffb`);
ancestor of HEAD and of `v6.18`
- [Phase 3] `git log --oneline --author="Tomasz Pakuła" --
drivers/hid/`: driver co-maintainer, many pidff commits
- [Phase 3] No later commits on these files after this ID add
- [Phase 4] `b4 dig -c 53f7f7955a684e820bdd6bd6792c45c4b434f637`: lore
msgid `20260922131758.1242755-1-tomasz.pakula.oficjalny@gmail.com`
- [Phase 4] `b4 dig -a`: v1 only
- [Phase 4] `b4 dig -w`: jikos@kernel.org, linux-input, co-author Oleg
- [Phase 4] LKML: Kosina “Applied, thanks.”
(https://lkml.iu.edu/2609.2/21230.html)
- [Phase 4] lore.kernel.org WebFetch: 403; used LKML/Patchew/`b4`
instead
- [Phase 5] Probe only via `module_hid_driver`; callees
`hid_parse`/`hid_hw_start`/`hid_pidff_init_with_quirks` exist here
- [Phase 5] `0x10f5` in `xpad.c` for other PIDs; `0x7077` not used there
- [Phase 6] `make kernelversion` → 6.18.57; `git describe HEAD` →
`v6.18.57-155-gcdf239ca885b2`
- [Phase 6] Parent of candidate: no `USB_VENDOR_ID_TURTLE`; Asetek rows
present; apply context matches
- [Phase 8] Failure mode: missing FF/mapping for one USB wheel, not oops
- UNVERIFIED: stable@ archive (HTTP 403); no in-kernel confirmation the
device implements USB PID (same as other table IDs)
**YES**
drivers/hid/hid-ids.h | 3 +++
drivers/hid/hid-universal-pidff.c | 1 +
2 files changed, 4 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index ca5c62f29aebe..69b1b0f98c99d 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -1415,6 +1415,9 @@
#define USB_DEVICE_ID_ASUS_MD_5110 0x5110
#define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART 0x7100
+#define USB_VENDOR_ID_TURTLE_BEACH 0x10f5
+#define USB_DEVICE_ID_TB_VELOCITYONE_RACE 0x7077
+
#define USB_VENDOR_ID_TWINHAN 0x6253
#define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100
diff --git a/drivers/hid/hid-universal-pidff.c b/drivers/hid/hid-universal-pidff.c
index 60180467a0bfd..f1854cfe42d0d 100644
--- a/drivers/hid/hid-universal-pidff.c
+++ b/drivers/hid/hid-universal-pidff.c
@@ -187,6 +187,7 @@ static const struct hid_device_id universal_pidff_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_FORTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_LA_PRIMA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_TONY_KANAAN) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_TURTLE_BEACH, USB_DEVICE_ID_TB_VELOCITYONE_RACE)},
{}
};
MODULE_DEVICE_TABLE(hid, universal_pidff_devices);
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH AUTOSEL 6.18] HID: Intel-thc-hid: Intel-quicki2c: Fix buffer overflow
[not found] <20261019135441.1420968-1-sashal@kernel.org>
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] HID: rmi: check report length before trimming sentinel bytes Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18] HID: universal-pidff: Add support for Turtle Beach VelocityOne Race Sasha Levin
@ 2026-10-19 13:46 ` Sasha Levin
2026-10-19 14:35 ` sashiko-bot
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.12] iio: hid-sensor: als: scale each channel individually Sasha Levin
` (13 subsequent siblings)
16 siblings, 1 reply; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:46 UTC (permalink / raw)
To: patches, stable
Cc: Even Xu, Jiri Kosina, Sasha Levin, xinpeng.sun, jikos, bentiss,
linux-input, linux-kernel
From: Even Xu <even.xu@intel.com>
[ Upstream commit 5e5c3b9db1c5910d6a9175c97b76a95566e4dc32 ]
The input and output buffers are used to store complete HID-over-I2C
packets, including their protocol headers. However, their sizes are
currently calculated from the payload length only.
Allocate enough space for both the payload and the packet header to
prevent a buffer overflow when the payload reaches its maximum size.
Signed-off-by: Even Xu <even.xu@intel.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a two-line allocation-size fix for a real HID-over-I2C buffer
overflow in a driver that already exists on this 6.18.y tree. It should
be backported.
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
- Record: **[HID / Intel-thc-hid / Intel-quicki2c] [Fix] [buffer
overflow]**
- Subsystem prefix: `HID: Intel-thc-hid: Intel-quicki2c`
- Action verb: **Fix**
- Claimed intent: prevent overflow of HID-over-I2C input/output buffers
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
- Record:
- `Signed-off-by: Even Xu <even.xu@intel.com>` (author; listed
maintainer of INTEL THC)
- `Signed-off-by: Jiri Kosina <jkosina@suse.com>` (HID maintainer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, `Link:`, or `Cc: stable` (absence of those tags is expected
for this review)
- Pipeline-only tags ignored per instructions
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
- Record:
- **Bug:** `input_buf` and `report_buf` hold complete HID-over-I2C
packets (`__le16 len` + payload), but they are allocated from
payload length only (`max_input_len` / `max_output_len`, floored at
4K).
- **Symptom/failure mode:** buffer overflow when the payload reaches
that maximum (2 bytes past the end: `HIDI2C_LENGTH_LEN ==
sizeof(__le16)`).
- **Version info:** none in the message.
- **Root cause:** allocation size omitted the 2-byte HID-over-I2C
length header.
**Step 1.4: DETECT HIDDEN BUG FIXES**
- Record: Not a hidden fix. The subject and body state a buffer overflow
and the diff matches that claim.
## PHASE 2: DIFF ANALYSIS - LINE BY LINE
**Step 2.1: INVENTORY THE CHANGES**
- Record:
- File: `drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c` (+4
/ −2; net +2)
- Function: `quicki2c_alloc_report_buf()`
- Scope: **single-file surgical fix**
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
- Record:
- **Hunk 1 (input_buf):** `devm_kzalloc(..., max_report_len)` →
`devm_kzalloc(..., HIDI2C_PACKET_LEN(max_report_len))`
- **Hunk 2 (report_buf):** same change
- Path: probe-time allocation (`quicki2c_probe` →
`quicki2c_alloc_report_buf`). Runtime use of those buffers is
unchanged.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
- Record:
- **Category:** memory safety / buffer overflow (out-of-bounds write)
- **Mechanism:** packets are `struct hidi2c_report_packet { __le16
len; u8 data[]; }`. `HIDI2C_PACKET_LEN(data_len)` is `(data_len) +
HIDI2C_LENGTH_LEN`. Allocation used payload size only.
- Verified consumers:
- `handle_input_report()` DMA-copies into `input_buf` via
`thc_rxdma_read()` → `sg_copy_to_buffer(..., read_buff, mes_len)`
with **no destination-size argument**.
- `quicki2c_get_report()` SWDMA-reads into `input_buf`.
- `quicki2c_init_write_buf()` / `write_cmd_to_txdma()` build framed
packets in `report_buf` (length field + payload, plus command
bytes).
- This is **not** a lock/refcount/init/API change.
**Step 2.4: ASSESS THE FIX QUALITY**
- Record:
- **Quality:** obviously correct. Uses an existing macro from
`include/linux/hid-over-i2c.h` that this tree already has.
- **Minimal:** two allocation sizes in one function.
- **Regression risk:** very low. Extra 2 bytes per buffer; no API,
locking, or control-flow change.
- **Caveat (not a reason to reject):** `qcdev->report_len` is still
set to `max_report_len`, not `HIDI2C_PACKET_LEN(max_report_len)`.
The write-side bound check (`if (buf_len > write_buf_len) return
-EINVAL`) can still reject a max-sized SET_REPORT. That is fail-safe
(no overflow), pre-existing, and not a regression. Command framing
can need more than +2 bytes; this commit only claims the 2-byte
packet length header, which is what `HIDI2C_PACKET_LEN` adds.
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
- Record: buggy allocations introduced by `66b59bfce6d93` (“HID: intel-
thc-hid: intel-quicki2c: Complete THC QuickI2C driver”, Even Xu,
2025-01-06). Present since the driver became functional. Driver
skeleton: `61bb2714dc3a1`. First appeared around **v6.13**, so it is
in this 6.18 tree.
**Step 3.2: FOLLOW THE FIXES: TAG**
- Record: no `Fixes:` tag. Not applicable. The introducing commit is in
this tree (`git merge-base --is-ancestor 66b59bfce6d93 v6.18.57`
succeeded).
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
- Record: recent work on this file is driver completion, ACPI, PM,
device IDs, WOT. Related but distinct: `d08a1049659aa` (ACPI u16
truncation, not this overflow). Sibling series patch: `HID: Intel-thc-
hid: Intel-quickspi: Fix buffer overflow` (different file). This
commit is **standalone**; it does not need the QuickSPI patch.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
- Record: Even Xu is listed in MAINTAINERS as maintainer of `INTEL TOUCH
HOST CONTROLLER (THC) DRIVER` (`drivers/hid/intel-thc-hid/`). This is
a maintainer fix, not drive-by.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
- Record: `HIDI2C_PACKET_LEN` was added in `6fc761385bcf6` (“Add HIDI2C
protocol implementation”) and is present on **v6.18.57** in
`include/linux/hid-over-i2c.h`. No missing helpers. Patch applies
cleanly to the v6.18.57 blob (`patch --dry-run` exit 0).
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
- Record:
- `b4 dig -c 5e5c3b9db1c5910d6a9175c97b76a95566e4dc32` →
https://patch.msgid.link/20260922024638.932865-2-even.xu@intel.com
- Cover: `[PATCH 0/2] HID: Intel-thc-hid: Fix potential buffer
overflow` (`20260922024638.932865-1`)
- `b4 dig -a`: **v1 only** (no v2/v3). Applied as submitted.
- Jiri Kosina (2026-09-23): “Applied to hid.git#for-7.3/upstream-
fixes, thanks.” No NAK.
- No human reviewer asked for `Cc: stable`. An automated review noted
`report_len` not updated and SET_REPORT framing possibly needing
more than 2 bytes. HID maintainer applied the series as-is.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
- Record (`b4 dig -w`): To/Cc `bentiss@kernel.org`, `jikos@kernel.org`,
`srinivas.pandruvada@linux.intel.com`, `linux-input@vger.kernel.org`.
HID maintainers were on the original mail. Jiri applied it.
**Step 4.3: SEARCH FOR THE BUG REPORT**
- Record: no `Reported-by` / syzbot / bugzilla. Author-found from code
inspection (“potential buffer overflow”). No user crash log in the
thread.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
- Record: 2/2 is the QuickSPI analogue (`HIDSPI_INPUT_BODY_SIZE`).
Independent file; this I2C patch does not depend on it.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
- Record: lore.kernel.org HTTP fetch returned 403. **UNVERIFIED**
whether linux-stable discussed this SHA. Decision does not rely on
that.
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS**
- Record: `quicki2c_alloc_report_buf()` only.
**Step 5.2: TRACE CALLERS**
- Record: single caller, `quicki2c_probe()` (after reading the HID-
over-I2C device descriptor). Probe of Intel THC I2C-port PCI devices
(Lunar Lake, Panther Lake, Wildcat Lake IDs in `quicki2c_pci_tbl`).
Not a hot path, but every successful probe allocates these buffers,
then IRQ/DMA/HID traffic uses them.
**Step 5.3: TRACE CALLEES**
- Record: `devm_kzalloc()`, `le16_to_cpu()`, `HIDI2C_PACKET_LEN()`. No
new callees.
**Step 5.4: FOLLOW THE CALL CHAIN**
- Record: PCI probe → descriptor read → alloc → DMA init → HID
registration → `handle_input_report()` on IRQ. Reachable on machines
with Intel THC + HID-over-I2C touch. Unprivileged HID input does not
size the kernel buffer; overflow is on kernel DMA/copy into an
undersized `input_buf` when the device sends a max-sized packet.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
- Record: same author applied the same header-vs-payload fix to
QuickSPI. Confirms a systematic off-by-header bug, not a one-off typo.
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
- Record: **Yes.** Local tree is **6.18.57** (`git describe HEAD` →
`v6.18.57-155-gcdf239ca885b2`; Makefile `VERSION=6 PATCHLEVEL=18
SUBLEVEL=57`).
- On **v6.18.57** (this series’ base), `quicki2c_alloc_report_buf()`
still does:
- `input_buf = devm_kzalloc(..., max_report_len)`
- `report_buf = devm_kzalloc(..., max_report_len)`
- `HIDI2C_PACKET_LEN` already exists in this tree’s header. Driver is
`CONFIG_INTEL_QUICKI2C` under `INTEL_THC_HID` (`X86_64 && PCI &&
ACPI`).
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
- Record: **clean apply** on the v6.18.57 file. Surrounding function
matches the patch. No refactor in the way.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
- Record: no other commit on this file in 6.18.y enlarges these two
allocations. The 4K floor (`max(..., SZ_4K)`) is a workaround for
devices that under-declare max length; it does **not** add the 2-byte
header. When `max_input_len`/`max_output_len` is ≥ 4K (HID max buffer
is 16K), that floor provides no slack.
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
- Record: **HID Intel THC QuickI2C** (`drivers/hid/intel-thc-hid/`).
**IMPORTANT** for Intel laptops/tablets with THC touch (LNL/PTL/WCL),
not core mm/VFS. Still production input hardware.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
- Record: actively maintained through 6.18 (device IDs, WOT, ACPI
advanced features). Bug is in original 2025 driver completion, not
brand-new 7.x-only code.
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
- Record: **driver-specific / config-specific:** `CONFIG_INTEL_QUICKI2C`
on x86_64 with Intel THC HID-over-I2C devices.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
- Record: HID-over-I2C input/feature/output packet whose payload equals
the allocated max (`max(declared max, 4K)`). Typical small touch
reports may not hit it; max-sized reports and devices that declare
large `wMaxInputLength` can. Not a userspace-crafted syscall overflow;
it is device-facing DMA/copy. Still a kernel memory-safety bug on a
standard probe/IRQ path.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
- Record: **buffer overflow (2 bytes) into heap** via
`sg_copy_to_buffer` / packet construction. **HIGH** (memory
corruption; crash or worse). Not a panic on every boot, but it is a
real overflow, not a warning.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
- Record:
- **Benefit:** high for THC HID-over-I2C users — closes a heap
overflow the driver author and HID maintainer treated as real.
- **Risk:** very low — +2 bytes on two `devm_kzalloc`s, existing
macro, no behavior change except not writing past the buffer.
- **Ratio:** strongly favors backport.
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real buffer overflow: complete HID-over-I2C packets stored in buffers
sized from payload only
- DMA copy into `input_buf` has no dest-size check
- Small, obviously correct (+2 bytes via existing `HIDI2C_PACKET_LEN`)
- Driver and macro exist in this 6.18.57 tree; introducing commit is in
this tree
- Applies cleanly
- Written by the THC maintainer; applied by HID maintainer
- Same class of bug independently fixed in QuickSPI
AGAINST:
- No public reproducer / syzbot report (author-found “potential”)
- 4K floor hides the overflow for devices with small `max_input_len`
- `report_len` not updated; write path may still `-EINVAL` at max size
(fail-safe, not a new bug)
- Affects only Intel THC QuickI2C, not all machines
UNRESOLVED:
- Could not query lore.kernel.org/stable (HTTP 403)
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — two allocation sizes; HID
maintainer applied v1; macro already in tree
2. Fixes a real bug that affects users? **PASS** — overflow on max-sized
HID-over-I2C packets in a shipping Intel touch driver
3. Important issue? **PASS** — heap buffer overflow / memory corruption
(**HIGH**)
4. Small and contained? **PASS** — one function, two sites, ~4 lines
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — clean on v6.18.57;
`HIDI2C_PACKET_LEN` already present
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
- Record: none needed. This is a normal memory-safety bug fix, not a
device-ID/quirk/DT/build/docs exception.
**Step 9.4: MAKE YOUR DECISION**
Backport. The bug is in this 6.18.y driver, the fix is surgical, and
leaving a 2-byte heap overflow in a HID DMA path is worse than adding
two bytes to the buffers.
## What the commit solves for this tree
On 6.18.57, QuickI2C still allocates `input_buf`/`report_buf` as
`max(payload, 4K)` and then stores HID-over-I2C packets that include a
2-byte length header. When the payload is that maximum,
`thc_rxdma_read()` / SWDMA copies past the end of the kmalloc buffer.
The fix allocates `HIDI2C_PACKET_LEN(max_report_len)` instead.
That matches stable rules: real overflow, tiny diff, no new API, applies
cleanly, no missing prerequisites.
Risk vs benefit: +2 bytes of allocation vs heap corruption on Intel THC
HID-over-I2C devices (Lunar Lake / Panther Lake / Wildcat Lake). Benefit
dominates. The unfixed `report_len` bound is conservative, not a
regression.
## Verification
- [Phase 1] Parsed subject/body/tags: overflow fix; Even Xu + Jiri
Kosina SOBs; no Fixes/Reported-by
- [Phase 2] Diff: two `devm_kzalloc` sizes in
`quicki2c_alloc_report_buf()` wrap `HIDI2C_PACKET_LEN`
- [Phase 2] `include/linux/hid-over-i2c.h`: `HIDI2C_PACKET_LEN(data_len)
= data_len + sizeof(__le16)`
- [Phase 2] `handle_input_report()` / `read_dma_buffer()`:
`sg_copy_to_buffer` into `input_buf` without dest capacity
- [Phase 3] `git blame` on v6.18.57: allocations from `66b59bfce6d93`
(2025-01, driver completion)
- [Phase 3] `git merge-base --is-ancestor 66b59bfce6d93 v6.18.57`:
introducing commit is in this tree
- [Phase 3] `HIDI2C_PACKET_LEN` added in `6fc761385bcf6`; present on
v6.18.57
- [Phase 3] Author Even Xu is MAINTAINERS owner of `drivers/hid/intel-
thc-hid/`
- [Phase 4] `b4 dig -c 5e5c3b9db1c5910d6a9175c97b76a95566e4dc32`: lore
thread found; v1 only
- [Phase 4] mbox: Jiri Kosina applied to hid.git#for-7.3/upstream-fixes;
no NAK
- [Phase 4] `b4 dig -w`: HID maintainers on original To/Cc
- [Phase 4] UNVERIFIED: lore.kernel.org/stable HTTP 403
- [Phase 5] Single caller `quicki2c_probe()`; PCI IDs LNL/PTL/WCL THC
I2C ports
- [Phase 6] `git describe HEAD` / `make kernelversion`: 6.18.57
- [Phase 6] `git show v6.18.57:drivers/hid/intel-thc-hid/intel-
quicki2c/pci-quicki2c.c`: buggy sizes still present
- [Phase 6] `patch --dry-run` of this commit onto the v6.18.57 file:
exit 0
- [Phase 8] Failure mode: 2-byte heap overflow on max-sized HID-over-I2C
packets; severity HIGH
**YES**
drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
index c6ba6886072ad..4588c55cf255d 100644
--- a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
+++ b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
@@ -586,7 +586,8 @@ static int quicki2c_alloc_report_buf(struct quicki2c_device *qcdev)
*/
max_report_len = max(le16_to_cpu(qcdev->dev_desc.max_input_len), SZ_4K);
- qcdev->input_buf = devm_kzalloc(qcdev->dev, max_report_len, GFP_KERNEL);
+ qcdev->input_buf = devm_kzalloc(qcdev->dev,
+ HIDI2C_PACKET_LEN(max_report_len), GFP_KERNEL);
if (!qcdev->input_buf)
return -ENOMEM;
@@ -596,7 +597,8 @@ static int quicki2c_alloc_report_buf(struct quicki2c_device *qcdev)
max_report_len = max(le16_to_cpu(qcdev->dev_desc.max_output_len),
max_report_len);
- qcdev->report_buf = devm_kzalloc(qcdev->dev, max_report_len, GFP_KERNEL);
+ qcdev->report_buf = devm_kzalloc(qcdev->dev,
+ HIDI2C_PACKET_LEN(max_report_len), GFP_KERNEL);
if (!qcdev->report_buf)
return -ENOMEM;
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH AUTOSEL 6.18] HID: Intel-thc-hid: Intel-quicki2c: Fix buffer overflow
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18] HID: Intel-thc-hid: Intel-quicki2c: Fix buffer overflow Sasha Levin
@ 2026-10-19 14:35 ` sashiko-bot
0 siblings, 0 replies; 20+ messages in thread
From: sashiko-bot @ 2026-10-19 14:35 UTC (permalink / raw)
To: Sasha Levin; +Cc: linux-input, dmitry.torokhov
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] HID: quicki2c: input_buf size mismatch with DMA in quicki2c_alloc_report_buf()
- [Medium] HID: intel-thc-hid: incomplete report_buf sizing in quicki2c_alloc_report_buf()
--
commit 916fd20197b9aebc1d04d169b7d6a4523c3d0a4d
Author: Even Xu <even.xu@intel.com>
HID: Intel-thc-hid: Intel-quicki2c: Fix buffer overflow
This commit enlarges the qcdev->input_buf and qcdev->report_buf allocations
in quicki2c_alloc_report_buf() by wrapping max_report_len with
HIDI2C_PACKET_LEN() to account for the 2-byte HID-over-I2C packet length
header.
> diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
> index c6ba6886072ad..4588c55cf255d 100644
> --- a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
> +++ b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
> @@ -586,7 +586,8 @@ static int quicki2c_alloc_report_buf(struct quicki2c_device *qcdev)
> */
> max_report_len = max(le16_to_cpu(qcdev->dev_desc.max_input_len), SZ_4K);
>
> - qcdev->input_buf = devm_kzalloc(qcdev->dev, max_report_len, GFP_KERNEL);
> + qcdev->input_buf = devm_kzalloc(qcdev->dev,
> + HIDI2C_PACKET_LEN(max_report_len), GFP_KERNEL);
[Severity: High]
Can qcdev->input_buf still be overflowed or mismatched with the DMA packet
limits when reading reports into it?
In drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.c, read_dma_buffer()
bounds-checks the incoming DMA transfer only against
read_config->max_packet_size before copying into read_buff
(qcdev->input_buf):
drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.c:read_dma_buffer() {
prd_tbl = &read_config->prd_tbls[prd_table_index];
mes_len = calc_message_len(prd_tbl, &nent);
if (mes_len > read_config->max_packet_size) {
...
return -EMSGSIZE;
}
sg = read_config->sgls[prd_table_index];
ret = sg_copy_to_buffer(sg, nent, read_buff, mes_len);
}
Meanwhile, quicki2c_dma_init() and quicki2c_dma_adv_enable() in
drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c configure the DMA
and hardware frame limits using the raw max_input_len and report_desc_len
without HIDI2C_PACKET_LEN():
drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c:quicki2c_dma_init() {
swdma_max_len = max(le16_to_cpu(qcdev->dev_desc.max_input_len),
le16_to_cpu(qcdev->dev_desc.report_desc_len));
ret = thc_dma_set_max_packet_sizes(qcdev->thc_hw, 0,
le16_to_cpu(qcdev->dev_desc.max_input_len),
le16_to_cpu(qcdev->dev_desc.max_output_len),
swdma_max_len);
}
drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c:quicki2c_dma_adv_enable() {
if (qcdev->i2c_max_frame_size_enable) {
if (qcdev->i2c_max_frame_size >=
le16_to_cpu(qcdev->dev_desc.max_input_len)) {
thc_i2c_set_rx_max_size(qcdev->thc_hw,
le16_to_cpu(qcdev->dev_desc.max_input_len));
}
Because dma_set_max_packet_size() rounds max_packet_size up with
ALIGN(size, SZ_4K), this leaves three mismatches on the
quicki2c_irq_thread_handler() -> handle_input_report() -> thc_rxdma_read()
and quicki2c_hid_raw_request() -> quicki2c_get_report() -> thc_swdma_read()
paths:
1. If report_desc_len is larger than max(max_input_len, SZ_4K) + 2,
THC_SWDMA has max_packet_size = ALIGN(report_desc_len, SZ_4K) while
qcdev->input_buf is only max(max_input_len, SZ_4K) + 2 bytes, so
quicki2c_get_report() calling thc_swdma_read() with prd_tbl_len = NULL can
copy past the end of qcdev->input_buf.
2. If max_input_len > SZ_4K and is not within 2 bytes of a 4K multiple (for
example, 4100), qcdev->input_buf is 4102 bytes while THC_RXDMA2 and
THC_SWDMA have max_packet_size = 8192 bytes, allowing read_dma_buffer() to
overflow qcdev->input_buf if a larger DMA transfer arrives.
3. If max_input_len is 4095 or an exact multiple of SZ_4K (such as 4096),
passing raw max_input_len to thc_dma_set_max_packet_sizes() and
thc_i2c_set_rx_max_size() leaves the DMA buffer and RX max frame size at
4096 or 4095 bytes, whereas a full-size input packet with its 2-byte length
header requires 4098 or 4097 bytes.
Should quicki2c_dma_init(), quicki2c_dma_adv_enable(), and the
qcdev->input_buf allocation all use consistent packet sizes?
> if (!qcdev->input_buf)
> return -ENOMEM;
>
> @@ -596,7 +597,8 @@ static int quicki2c_alloc_report_buf(struct quicki2c_device *qcdev)
> max_report_len = max(le16_to_cpu(qcdev->dev_desc.max_output_len),
> max_report_len);
>
> - qcdev->report_buf = devm_kzalloc(qcdev->dev, max_report_len, GFP_KERNEL);
> + qcdev->report_buf = devm_kzalloc(qcdev->dev,
> + HIDI2C_PACKET_LEN(max_report_len), GFP_KERNEL);
> if (!qcdev->report_buf)
> return -ENOMEM;
>
[Severity: Medium]
Does enlarging qcdev->report_buf by HIDI2C_PACKET_LEN(max_report_len) allow
maximum-length output or feature reports to succeed?
At the end of quicki2c_alloc_report_buf(), qcdev->report_len is still set
to max_report_len:
drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c:quicki2c_alloc_report_buf() {
qcdev->report_buf = devm_kzalloc(qcdev->dev,
HIDI2C_PACKET_LEN(max_report_len), GFP_KERNEL);
if (!qcdev->report_buf)
return -ENOMEM;
qcdev->report_len = max_report_len;
}
When write_cmd_to_txdma() or quicki2c_get_report() in
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c formats a
packet into qcdev->report_buf, it passes qcdev->report_len as write_buf_len
to quicki2c_init_write_buf():
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c:write_cmd_to_txdma() {
ret = quicki2c_init_write_buf(qcdev, cmd, cmd_len, buf ? true : false, buf,
buf_len, qcdev->report_buf, qcdev->report_len);
}
And quicki2c_init_write_buf() prepends cmd_reg (HIDI2C_REG_LEN = 2 bytes),
cmd (HIDI2C_CMD_LEN = 2 bytes, or HIDI2C_CMD_LEN_OPT = 3 bytes when
report_id >= 15), data_reg (HIDI2C_REG_LEN = 2 bytes), and the packet
length header (HIDI2C_LENGTH_LEN = 2 bytes) before checking against
write_buf_len:
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c:quicki2c_init_write_buf() {
buf_len = HIDI2C_REG_LEN + cmd_len;
if (append_data_reg)
buf_len += HIDI2C_REG_LEN;
if (data && data_len)
buf_len += data_len + HIDI2C_LENGTH_LEN;
if (buf_len > write_buf_len)
return -EINVAL;
}
Because qcdev->report_len is left at max_report_len, the extra 2 bytes in
qcdev->report_buf cannot be used, and because quicki2c_init_write_buf()
writes 8 to 9 bytes of framing ahead of data_len, HIDI2C_PACKET_LEN() (only
2 extra bytes) is still 6 to 7 bytes short for a payload of max_report_len
bytes, causing quicki2c_init_write_buf() to return -EINVAL.
Should qcdev->report_buf and qcdev->report_len both be sized to include the
full command, register, and packet length headers written by
quicki2c_init_write_buf()?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261019135441.1420968-123-sashal@kernel.org?part=1
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH AUTOSEL 6.18-6.12] iio: hid-sensor: als: scale each channel individually
[not found] <20261019135441.1420968-1-sashal@kernel.org>
` (2 preceding siblings ...)
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18] HID: Intel-thc-hid: Intel-quicki2c: Fix buffer overflow Sasha Levin
@ 2026-10-19 13:47 ` Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.1] HID: quirks: add ALWAYS_POLL quirk for AULA Mini 60 HE Pro Dongle Sasha Levin
` (12 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:47 UTC (permalink / raw)
To: patches, stable
Cc: Daniel Schaefer, Sven Vainküla, Srinivas Pandruvada,
Jonathan Cameron, Sasha Levin, jikos, jic23, linux-input,
linux-iio, linux-kernel
From: Daniel Schaefer <dhs@frame.work>
[ Upstream commit cad928dad9a4c26aa56b4223dc2a29bca517fb5f ]
Some sensors have multiple channels (not just brightness but color ALS
sensors) with different scaling factors.
Signed-off-by: Daniel Schaefer <dhs@frame.work>
Link: https://gitlab.freedesktop.org/hadess/iio-sensor-proxy/-/merge_requests/413
Tested-by: Sven Vainküla <sven@xn--vainkla-r2a.ee> #Asus ProArt PX13 laptop.
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **Linux 7.3-rc4** (mainline). Color ALS channels exist
here (since v6.9), and this is a small per-channel IIO scale correctness
fix with a real user report. Full phase walkthrough follows.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[iio/hid-sensor-als] [scale] scale each ALS channel
individually rather than using one illuminance scale for every channel**
- Subsystem: `iio: hid-sensor: als`
- Verb: “scale” (correctness of IIO `in_*_scale`, not a refactor)
- Claimed intent: color ALS sensors have per-channel scaling factors;
the driver used a single shared scale
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record: tags (ignoring pipeline `Signed-off-by: Sasha Levin` /
`[Upstream commit …]`):
- **Signed-off-by:** Daniel Schaefer `<dhs@frame.work>` (author,
Framework)
- **Link:** `https://gitlab.freedesktop.org/hadess/iio-sensor-
proxy/-/merge_requests/413`
- **Tested-by:** Sven Vainküla (Asus ProArt PX13)
- **Acked-by:** Srinivas Pandruvada (HID sensor hub maintainer)
- **Signed-off-by:** Jonathan Cameron (IIO maintainer)
- **No Fixes:** (expected for this review)
- **No Cc: stable:** (expected)
- **No Reported-by / syzbot / KASAN**
Notable: real hardware Tested-by, userspace (iio-sensor-proxy) link,
maintainer Ack.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** some HID ALS devices are color ALS (illuminance + color
temperature + chromaticity), not brightness-only, and those extra
channels have different HID unit/exponent than illuminance.
- **Symptom:** userspace (iio-sensor-proxy, compositors) applies the
illuminance scale to color-temp/chromaticity raw values → wrong
physical units (night light / color management broken or nonsense).
- **Version info:** none in the message. Color/chromaticity channels
themselves landed in v6.9.
- **Root cause:** `hid_sensor_format_scale()` was called only on
`als[CHANNEL_SCAN_INDEX_INTENSITY]` and that one scale was returned
for every channel.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Not a hidden cleanup.** It is an explicit correctness fix:
wrong IIO SCALE sysfs values for extra ALS channels. Same class as
`8b518cdb03f5f` (“iio: hid-sensor-prox: support multi-channel SCALE
calculation”), which had `Cc: stable` and `Fixes:`.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- **File:** `drivers/iio/light/hid-sensor-als.c` only
- **Size:** 12 insertions, 10 deletions (net +2)
- **Functions:** `struct als_state`, `als_read_raw()`,
`als_parse_report()`
- **Scope:** single-file surgical driver fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
1. **State:** `scale_pre_decml` / `scale_post_decml` / `scale_precision`
become arrays of `CHANNEL_SCAN_INDEX_MAX`.
2. **`als_read_raw` IIO_CHAN_INFO_SCALE:** used to return the one
illuminance scale for any channel; now indexes by `chan->scan_index`,
with a bounds check.
3. **`als_parse_report`:** scale is computed **inside** the per-usage
loop with `st->als[i]` (that channel’s units/exponent), instead of
once afterward from intensity only.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **[Logic / correctness]** IIO SCALE ABI wrong for color ALS.
`hid_sensor_format_scale()` (verified in `hid-sensor-attributes.c`)
matches `usage_id` (still the ALS sensor usage `0x200041`) **and**
`attr_info->units`, then applies `attr_info->unit_expo`. The per-channel
difference is those HID attribute fields. Intensity/illuminance share
`HID_USAGE_SENSOR_LIGHT_ILLUM`; color-temp and chromaticity have
different attributes, so they must not reuse intensity’s exponent.
Classic brightness-only ALS is unchanged: both intensity and illum still
use the same HID usage and therefore the same scale.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- **Quality:** obviously correct; same pattern as hid-sensor-prox
(`scale_pre_decml[index]` + format_scale in the parse loop).
- **Minimal:** no unrelated edits.
- **Regression risk:** low. Traditional ALS behavior is preserved.
Color-temp/chromaticity SCALE sysfs values change from wrong to
correct (intended).
- **Known limitation (discussed on-list, not a NAK):**
`IIO_CHAN_INFO_SCALE` stays `info_mask_shared_by_type`, so
chromaticity X and Y share one sysfs scale. Jonathan Cameron: that
only matters if X and Y scales differ; the reported bug is illuminance
vs color-temp. Author: “in practice it's probably not needed and the
patch works as is.” No v2 was required; v1 was applied.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Shared scale fields date to **`36783d09f1a5c`** (“iio: hid-sensors:
ALS: adjust scale and offset”, 2014) — correct when there was only
illuminance.
- Extra channels: **`3765d426fe864`** color temperature,
**`2ec17b1950bb8`** chromaticity, both **v6.9-rc1**. That is when one
scale became wrong.
- Dynamic channel assignment: **`f2a71ebdf2312`** (v6.9).
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: **No Fixes: tag.** Closest introduction of the bug is the v6.9
color-temp/chromaticity additions. Those commits **are** ancestors of
this 7.3-rc4 tree (`git merge-base --is-ancestor` not required for each;
`git describe --contains` shows `v6.9-rc1`).
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: recent ALS history includes channel init refactor, timestamp
alignment, probe race fix. **No prerequisite series** for this patch
(standalone v1). **No follow-ups** on this file after `cad928dad9a4c`.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Daniel Schaefer has this single IIO commit in-tree. Not the
subsystem maintainer. Weight comes from **Acked-by Srinivas Pandruvada**
and **SOB Jonathan Cameron**.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: needs existing `als[]` per-channel attribute array,
`CHANNEL_SCAN_INDEX_*`, and `hid_sensor_format_scale()` — all present
here since v6.9 / much earlier. **Applies standalone.** Prox analog
`8b518cdb03f5f` is a sibling pattern, not a dependency.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- **b4 dig:** https://patch.msgid.link/20260723-chromaticity-v1-1-
5ef5746ace2a@frame.work
- **Series:** v1 only (no v2/v3 despite author briefly offering a v2 for
`info_mask_separate`)
- **Jonathan Cameron (2026-07-26):** SCALE shared-by-type is OK unless
chromaticity X/Y differ; “the change here looks fine”; queued on
iio.git testing.
- **Srinivas Pandruvada:** Acked-by.
- **David Lechner:** explained testing-branch means accepted/applied.
- **No NAK.** No reviewer asked for Cc: stable.
- **Sashiko bot:** flagged shared-by-type (addressed in discussion) and
a **pre-existing** buffer-layout concern, not introduced by this
patch.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: To/Cc included Jonathan Cameron, Srinivas Pandruvada, David
Lechner, Nuno Sá, Andy Shevchenko, linux-iio, linux-input. Right
maintainers were in the loop.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: GitLab iio-sensor-proxy MR 413 returned **HTTP 403** (UNVERIFIED
beyond the Link tag). Hardware evidence that **is** verified: Tested-by
on Asus ProArt PX13; Framework author; iio-sensor-proxy is the standard
userspace for laptop ALS.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: standalone, not N/M. Prox multi-channel SCALE (`8b518cdb03f5f`,
v6.15-rc6) is the same bug class and **was** `Cc: stable`.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: no “stable” in the lore mbox. UNVERIFIED whether linux-stable@
discussed it separately (no lore.kernel.org/stable hit via b4 thread).
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS**
Record: `als_read_raw`, `als_parse_report`; struct `als_state`. Probe
path: `hid_als_probe` → `als_parse_report`. Sysfs/read path: IIO core →
`als_info.read_raw` → `als_read_raw`.
**Step 5.2: TRACE CALLERS**
Record:
- `als_parse_report`: only from `hid_als_probe` (HID-SENSOR-200041 /
LISS-0041 platform devices).
- `als_read_raw`: IIO `read_raw` for sysfs (`in_illuminance_scale`,
`in_colortemp_scale`, `in_chromaticity_x_scale`, etc.) and buffered
metadata. **Userspace-reachable**, not IRQ-hot.
**Step 5.3: TRACE CALLEES**
Record: `hid_sensor_format_scale()` → unit table +
`adjust_exponent_nano()`; `sensor_hub_input_get_attribute_info()` fills
per-channel `units`/`unit_expo`.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: unprivileged users can read IIO sysfs on a system with this HID
ALS. Color ALS on recent AMD/laptop HID sensor hubs (v6.9+ channels).
**Reachable from userspace.**
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: hid-sensor-prox already uses per-channel scale arrays. Other
hid-sensor drivers (accel, gyro, press, temp) still use a single scale
because they are not mixed-unit multi-channel in the same way. ALS was
the leftover mismatch after v6.9 extra channels.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- **Tree:** `git describe HEAD` = `v7.3-rc4-27-gf0100363d8c37`; `make
kernelversion` = **7.3.0-rc4** (Linus mainline, not an LTS branch).
- Color ALS channels **are** in `hid-sensor-als.c`.
- Commit **`cad928dad9a4c` is already an ancestor of HEAD** (working
tree already has per-channel arrays). That is the mainline landing of
this fix during 7.3, **not** a reason to reject it on technical merit
(pipeline “already selected” markers ignored).
- Bug introduced **v6.9** (2024), long before this tree.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: against **this** 7.3 tree the change is already applied / would
apply cleanly. Context in the submitted v1 still used
`als_adjust_channel_bit_mask`; this tree uses `iio_scan_type`
initializer (`cded217233845`). For **this** checkout that is already
resolved. No extra commits required for the logic of the fix.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: this exact commit is in HEAD. No later revert or competing fix.
No other ALS scale fix in `git log cad928dad9a4c..HEAD --
drivers/iio/light/hid-sensor-als.c`.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **IIO light / HID sensor hub ALS** — **PERIPHERAL to IMPORTANT**
depending on hardware. Laptop ambient/color light (Framework, Asus
ProArt, HID sensor hubs). Not mm/net/fs core, but commonly used on
notebooks via iio-sensor-proxy.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: mature driver (2012), still getting channel and race fixes.
Color ALS is several years old (v6.9), not brand-new staging code.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **driver-specific / config-specific** (`CONFIG_HID_SENSOR_ALS`).
Users of HID color ALS (not every illuminance-only ALS). Confirmed: Asus
ProArt PX13; likely other color-ALS HID laptops.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: **Every read of IIO SCALE** for color-temp/chromaticity, and
every userspace conversion of those raw values. Not a race. Unprivileged
users with IIO device node/sysfs access can observe it. Common on
affected laptops at session start (iio-sensor-proxy).
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: **Wrong sensor physical values** (color temperature /
chromaticity), not oops/UAF/deadlock. Userspace brightness for classic
ALS is unaffected (same HID usage). Compositor color/night-light using
color ALS can be wrong. **Severity: MEDIUM** — real, user-visible, “oh
that’s not good,” not CRITICAL.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** correct IIO scale on color ALS; unbreaks iio-sensor-
proxy/hardware that already exists in this lineage.
- **Risk:** very low (≈20-line, one file, no locking/API).
- **Ratio:** favorable. Same class already taken for stable in prox.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
**FOR backporting**
- Real userspace-visible bug: mixed-unit color ALS channels reused
illuminance scale.
- Hit on real hardware (Asus ProArt PX13 Tested-by); iio-sensor-proxy MR
linked.
- Small, obviously correct, acked by HID-sensor maintainer, applied by
IIO maintainer.
- Identical prox bug was explicitly `Cc: stable`.
- This tree **has** the v6.9 color/chromaticity channels, so the bug
class exists in this lineage.
- Traditional ALS unchanged; only extra channels’ SCALE change.
- Fits documented stable bar: “real bug that bothers people” / “oh,
that’s not good.”
**AGAINST**
- Not a crash, UAF, deadlock, or security issue.
- No Fixes:/Cc: stable (not a negative per review rules).
- SCALE still shared-by-type for chromaticity X/Y (accepted by
maintainer as OK for the reported bug).
- Peripheral driver, not core kernel.
- GitLab MR body UNVERIFIED (403).
**UNRESOLVED**
- Exact HID unit/exponent values on the PX13 (not in-tree).
- Whether chromaticity X vs Y ever differ on some firmware (maintainers
assumed no).
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — Tested-by, Acked-by, IIO
maintainer queued v1.
2. Fixes a real bug that affects users? **PASS** — wrong IIO scale on
color ALS; userspace conversion broken.
3. Important issue? **PASS** (medium “oh that’s not good,” not CRITICAL
crash) — wrong physical units for sensors userspace actually uses.
4. Small and contained? **PASS** — one file, +12/−10.
5. No new features or APIs? **PASS** — corrects SCALE for channels that
already exist; no new sysfs ABI.
6. Can apply to the local tree? **PASS** — affected code is in 7.3-rc4;
change is already the current code here.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: not a device-ID/quirk/DT/build/docs exception. Ordinary driver
correctness fix.
**Step 9.4: MAKE YOUR DECISION**
This tree’s ALS driver includes color-temperature and chromaticity
channels added in v6.9 but, until this change, advertised a single
illuminance-derived IIO scale for all of them. That is a real, tested
userspace bug (wrong color ALS readings via iio-sensor-proxy), not a
feature or cleanup. The patch is small, matches the already-stable-
worthy prox multi-channel SCALE fix, and does not change classic
illuminance ALS. Benefit outweighs the low regression risk.
### What the commit solves and why it matters here
Color HID ALS devices expose extra channels with different HID
units/exponents. The driver formatted scale only from the intensity
attribute, so `in_colortemp_scale` / chromaticity scale were wrong. On
this 7.3-rc4 tree those channels exist, so the fix is applicable and is
the right stable-style correctness change for that hardware.
### Risk vs benefit
Benefit: correct sensor units for color ALS on laptops that already use
this driver. Risk: a few array/index changes on the sysfs read path;
illuminance-only devices keep the same scale.
### Concerns
No crash-level severity; chromaticity X/Y still share type-wide scale
(explicitly accepted). Neither blocks backport of this contained fix.
Verification:
- [Phase 1] Parsed tags: Tested-by Sven Vainküla (Asus ProArt PX13);
Acked-by Srinivas Pandruvada; SOB Jonathan Cameron; Link to iio-
sensor-proxy MR 413; no Fixes/Cc:stable
- [Phase 2] Diff: 12+/10- in hid-sensor-als.c; scalar scale → per-
scan_index arrays; format_scale moved into parse loop over
`st->als[i]`
- [Phase 2] Verified `hid_sensor_format_scale()` uses `attr_info->units`
and `unit_expo`; ALS unit table only has ALS+0 and ALS+LUX
- [Phase 3] `git describe HEAD` = v7.3-rc4-27-gf0100363d8c37;
kernelversion 7.3.0-rc4
- [Phase 3] `git merge-base --is-ancestor cad928dad9a4c HEAD` → already
in this tree (mainline landing)
- [Phase 3] Color temp `3765d426fe864` and chromaticity `2ec17b1950bb8`
contained in v6.9-rc1
- [Phase 3] Prox analog `8b518cdb03f5f` had Cc: stable + Fixes
- [Phase 3] No follow-up commits on hid-sensor-als.c after cad928dad9a4c
- [Phase 4] `b4 dig -c cad928dad9a4c`: lore https://patch.msgid.link/202
60723-chromaticity-v1-1-5ef5746ace2a@frame.work
- [Phase 4] `b4 dig -a`: v1 only
- [Phase 4] `b4 dig -w`: IIO + HID-sensor maintainers on To/Cc
- [Phase 4] mbox: Jonathan OK with shared-by-type; Srinivas Ack; no NAK;
no stable nomination in thread
- [Phase 4] GitLab MR fetch: 403, body UNVERIFIED
- [Phase 5] semcode: not available; grep shows als_read_raw only from
als_info; hid_als_probe only caller of als_parse_report
- [Phase 6] Working tree already has per-channel scale arrays at lines
36–38 and 332–334
- [Phase 8] Failure mode: wrong IIO SCALE for color ALS → incorrect
userspace conversion; severity MEDIUM
- UNVERIFIED: exact PX13 HID unit/exponent values; linux-stable@
discussion outside this thread
**YES**
drivers/iio/light/hid-sensor-als.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index 384572844162c..232cb58e0a9ff 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -33,9 +33,9 @@ struct als_state {
u32 illum[CHANNEL_SCAN_INDEX_MAX];
aligned_s64 timestamp;
} scan;
- int scale_pre_decml;
- int scale_post_decml;
- int scale_precision;
+ int scale_pre_decml[CHANNEL_SCAN_INDEX_MAX];
+ int scale_post_decml[CHANNEL_SCAN_INDEX_MAX];
+ int scale_precision[CHANNEL_SCAN_INDEX_MAX];
int value_offset;
int num_channels;
s64 timestamp;
@@ -186,9 +186,11 @@ static int als_read_raw(struct iio_dev *indio_dev,
ret_type = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SCALE:
- *val = als_state->scale_pre_decml;
- *val2 = als_state->scale_post_decml;
- ret_type = als_state->scale_precision;
+ if (chan->scan_index >= CHANNEL_SCAN_INDEX_MAX)
+ return -EINVAL;
+ *val = als_state->scale_pre_decml[chan->scan_index];
+ *val2 = als_state->scale_post_decml[chan->scan_index];
+ ret_type = als_state->scale_precision[chan->scan_index];
break;
case IIO_CHAN_INFO_OFFSET:
*val = als_state->value_offset;
@@ -338,6 +340,10 @@ static int als_parse_report(struct platform_device *pdev,
als_adjust_channel_bit_mask(channels, index, st->als[i].size);
++index;
+ st->scale_precision[i] = hid_sensor_format_scale(usage_id,
+ &st->als[i], &st->scale_pre_decml[i],
+ &st->scale_post_decml[i]);
+
dev_dbg(&pdev->dev, "als %x:%x\n", st->als[i].index,
st->als[i].report_id);
}
@@ -347,10 +353,6 @@ static int als_parse_report(struct platform_device *pdev,
if (index)
ret = 0;
- st->scale_precision = hid_sensor_format_scale(usage_id,
- &st->als[CHANNEL_SCAN_INDEX_INTENSITY],
- &st->scale_pre_decml, &st->scale_post_decml);
-
return ret;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH AUTOSEL 6.18-6.1] HID: quirks: add ALWAYS_POLL quirk for AULA Mini 60 HE Pro Dongle
[not found] <20261019135441.1420968-1-sashal@kernel.org>
` (3 preceding siblings ...)
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.12] iio: hid-sensor: als: scale each channel individually Sasha Levin
@ 2026-10-19 13:47 ` Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.6] HID: i2c-hid: Add a quirk for a Cirque I2C device Sasha Levin
` (11 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:47 UTC (permalink / raw)
To: patches, stable
Cc: Yuxiang Lin, Jiri Kosina, Sasha Levin, jikos, bentiss,
linux-input, linux-kernel
From: Yuxiang Lin <mclyxfdw@gmail.com>
[ Upstream commit 2884e21b18613708f050ec75330b265dd07ecc03 ]
The AULA Mini 60 HE Pro wireless keyboard dongle (USB ID
0c45:fefe) becomes unresponsive after roughly one minute of idle.
No error appears in dmesg; the only recovery is physically
replugging the dongle.
This has been reproduced across kernels 6.8, 6.14 and 7.1.3.
Testing shows HID_QUIRK_ALWAYS_POLL alone resolves the issue,
verified via usbhid.quirks=0x0c45:0xfefe:0x400.
Signed-off-by: Yuxiang Lin <mclyxfdw@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a hardware-quirk addition for a wireless keyboard dongle that
stops responding after idle. The local tree is **5.15.221**
(`pending-5.15`, `git describe`: `p-5.15-2-g9a29d9b0f9507`). Upstream
commit is `2884e21b18613` (`HID: quirks: add ALWAYS_POLL quirk for AULA
Mini 60 HE Pro Dongle`); `git merge-base --is-ancestor` confirms it is
**not** in this tree.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[HID]** **[add]** **ALWAYS_POLL quirk for AULA Mini 60 HE Pro
wireless dongle (USB 0c45:fefe)**
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- **Fixes:** none (expected)
- **Reported-by:** none
- **Tested-by:** none (author describes own testing in the body)
- **Reviewed-by:** none
- **Acked-by:** none
- **Link:** none in the commit; mailing-list Message-ID
`20260722175602.22773-1-mclyxfdw@gmail.com`
- **Cc: stable:** none (expected)
- **Signed-off-by:** Yuxiang Lin \<mclyxfdw@gmail.com\> (author); Jiri
Kosina \<jkosina@suse.com\> (HID maintainer). Ignore any pipeline SOB.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** AULA Mini 60 HE Pro wireless dongle `0c45:fefe` becomes
unresponsive after ~1 minute idle.
- **Symptom:** No dmesg error; only recovery is physically replugging
the dongle. Keyboard is dead until then.
- **Versions tested by author:** 6.8, 6.14, 7.1.3 (not 5.15
specifically).
- **Root cause (author):** device needs continuous interrupt polling;
`HID_QUIRK_ALWAYS_POLL` alone fixes it, verified with
`usbhid.quirks=0x0c45:0xfefe:0x400`.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. It is an explicit hardware quirk for a
device that stops working. Matches the documented HID ALWAYS_POLL
pattern (devices that hang when the host stops polling the interrupt
endpoint).
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- `drivers/hid/hid-ids.h`: **+1** (`USB_DEVICE_ID_AULA_MINI_60_HE_PRO
0xfefe` under existing `USB_VENDOR_ID_JESS 0x0c45`)
- `drivers/hid/hid-quirks.c`: **+2** (one `hid_quirks[]` entry:
`HID_QUIRK_ALWAYS_POLL`)
- Total: **3 insertions**, 0 deletions, 2 files
- Functions: none modified; static ID table only
- Scope: **single-purpose surgical quirk addition**
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** dongle `0c45:fefe` is a generic USB HID device. usbhid
starts interrupt polling on open and may stop it on close / when not
`ALWAYS_POLL`. After ~1 minute idle the firmware/hardware stops
responding; unplug/replug required.
- **After:** `hid_gets_squirk()` / `hid_lookup_quirk()` matches this
VID/PID and sets `HID_QUIRK_ALWAYS_POLL` (`BIT(10)` = `0x400`).
`usbhid_start()` starts the IN URB at probe and keeps `HID_IN_POLLING`
set across close (`usbhid_open`/`usbhid_close`/`usbhid_stop` in this
tree).
- Path: HID probe / usbhid start-stop, **not** an error path.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **(h) Hardware workaround** — HID quirk table + device ID. Same
class as USB/HID quirks that are routinely taken into stable. Not UAF,
leak, race, etc.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: one ID + one table entry using an existing, well-
tested quirk bit.
- Author empirically confirmed `ALWAYS_POLL` alone is sufficient.
- Regression risk is **low and device-scoped**: only `0c45:fefe`. Cost
is extra interrupt polling (power) on that dongle only.
- No API, locking, or data-structure changes.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- `USB_VENDOR_ID_JESS 0x0c45` / `USB_DEVICE_ID_JESS_YUREX`:
`6bc235a2e24a5` (Tomoki Sekiyama, 2010). Present in this tree at
`drivers/hid/hid-ids.h:695-698`.
- Insertion point in `hid_quirks[]` (after INNOMEDIA, before KYE): table
from `d5d3e202753cc0` (Benjamin Tissoires, 2017).
- `HID_QUIRK_ALWAYS_POLL` introduced in `0b750b3baa2d6` (“HID: usbhid:
add always-poll quirk”, Johan Hovold, 2014-09-08). `git merge-base
--is-ancestor 0b750b3baa2d6 HEAD` **succeeds**. Defined here as
`BIT(10)` in `include/linux/hid.h:373`.
- The AULA ID itself is **new**; the bug is hardware/firmware plus long-
standing usbhid idle/poll behavior, not a recent regression.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. N/A. Bug is device firmware vs existing usbhid
poll-on-open behavior, not a specific introducing commit.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: This 5.15 tree already carries the same class of backports,
e.g.:
- `f9ad98cff302c` HID: quirks: add HID_QUIRK_ALWAYS_POLL for 8BitDo Pro
3
- `16c2ca35257ed` HID: Apply quirk HID_QUIRK_ALWAYS_POLL to Edifier QR30
- `5c46ec760d3be` HID: quirks: Add ADATA XPG alpha wireless mouse
support
- `9f093e15faee6` HID: add ALWAYS_POLL quirk for Apple kb
Standalone; not patch N/M.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: `git log --author="Yuxiang Lin"` on `drivers/hid/` in this tree:
**empty**. One-off device owner report. Weight comes from HID maintainer
Jiri Kosina applying it, not from the author being a maintainer.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Needs only `HID_QUIRK_ALWAYS_POLL`, `hid_quirks[]`,
`USB_VENDOR_ID_JESS`, and usbhid ALWAYS_POLL handling — all present
since well before 5.15. **Standalone.**
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 2884e21b18613` matched lore by patch-id:
https://patch.msgid.link/20260722175602.22773-1-mclyxfdw@gmail.com
- `b4 dig -a`: **v1 only** (2026-07-23). No v2/v3.
- Thread: submit → Jiri Kosina “Applied, thanks.” (2026-08-03). No NAK,
no requested changes, no stable discussion in-thread.
- lore.kernel.org HTTP fetch returned 403; discussion recovered via `b4
dig -m` mbox and LKML mirrors.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To `jikos@kernel.org`; Cc Benjamin Tissoires,
linux-input, linux-kernel. HID maintainers were on the original mail.
Applied by Jiri Kosina.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No bugzilla/syzbot. The report **is** the patch: author
reproduced hang on 6.8/6.14/7.1.3 and verified the quirk via module
parameter. Single reporter; concrete hardware + recovery path.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone 1/1. Nearby mainline ALWAYS_POLL quirks (Beitong,
SIGMACHIP, SDINNOVATION) are separate devices, not prerequisites.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: lore.kernel.org/stable search returned 403. No evidence in the
linux-input thread of a stable NAK. UNVERIFIED: whether someone already
requested this on stable@ (does not change the technical case).
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: No function bodies edited. New consumers of `hid_gets_squirk()`
→ `hid_lookup_quirk()`. Runtime effect is in usbhid: `usbhid_open`,
`usbhid_close`, `usbhid_start`, `usbhid_stop`.
**Step 5.2: TRACE CALLERS**
Record (this tree):
- `hid_lookup_quirk()`: `drivers/hid/hid-core.c` (device add / quirk
refresh), `drivers/hid/usbhid/hid-core.c:992` (usbhid probe).
- ALWAYS_POLL consumers: `usbhid_open` (skip start-on-open),
`usbhid_close` (keep polling), `usbhid_start` (start IN URB at probe),
`usbhid_stop` (clear polling).
- Context: USB HID probe and open/close — **device enumeration /
input**, not IRQ-unsafe new locking.
**Step 5.3: TRACE CALLEES**
Record: Table match only. ALWAYS_POLL path already calls
`usb_autopm_get_interface`, `hid_start_in`, `usb_kill_urb` in this tree.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Plug dongle → usbhid probe → `hid_lookup_quirk` → generic HID
input. Userspace (evdev) uses the keyboard. **Reachable from plugging
the device;** unprivileged user of that keyboard hits the hang after
idle. Not a syscall fuzzer path; real HID hardware path.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Dozens of `HID_QUIRK_ALWAYS_POLL` entries already in this tree’s
`hid_quirks[]` (HP/Pixart mice, Corsair, Logitech, Lenovo, 8BitDo,
Edifier, ADATA XPG, …). Same fix, new VID/PID. No `0xfefe` HID ID
already present (grep of `drivers/hid` empty).
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** usbhid ALWAYS_POLL vs poll-on-open logic is in
`drivers/hid/usbhid/hid-core.c` (e.g. 687, 750, 754, 1183, 1232). Vendor
ID `USB_VENDOR_ID_JESS 0x0c45` exists; product `0xfefe` is **not**
quirked. The hang is firmware + this poll behavior; it is not a 6.x-only
bug. Author listed 6.8+ because those are what they ran; 5.15 has the
same usbhid mechanism (ALWAYS_POLL since 2014).
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record:
- `hid-ids.h`: `git apply --check` **clean**
(`USB_DEVICE_ID_REDRAGON_ASURA` context matches).
- `hid-quirks.c`: **context mismatch** — 5.15 has extra KYE entries
immediately after INNOMEDIA (`KYE_EASYPEN_M610X` …) vs mainline’s
`KYE` PIXART mouse first. `git apply --check` fails on `hid-
quirks.c:113`; 3-way reports a conflict there. Fix is insert the two
JESS lines after the INNOMEDIA entry (alphabetically correct). **Minor
backport, not a rework.**
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No AULA / `0xfefe` HID quirk. No alternate fix for this dongle.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **HID / usbhid** (`drivers/hid/`). Criticality: **IMPORTANT**
(common input stack), impact **driver-specific / device-specific**. Not
core mm/net, but keyboards are user-visible and this tree already
backports HID quirks.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature. `hid-quirks.c` still gets device-ID/quirk backports on
5.15. This is not a new subsystem.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Driver-specific / device-specific** — owners of AULA Mini 60
HE Pro wireless dongle `0c45:fefe`. No effect on other HID devices.
`CONFIG_USB_HID` (standard desktop/laptop configs).
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Plug dongle, leave idle ~1 minute. Common for a wireless
keyboard. Unprivileged user of the keyboard is affected. Not a timing
race; firmware/idle-poll issue. Author reproduced on three kernel
versions.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Input device **permanently unresponsive** until physical replug;
no oops. **HIGH** for those users (keyboard dead; no software recovery).
Not panic/corruption/CVE.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** restores a wireless keyboard on 5.15 LTS without a
module-param workaround.
- **Risk:** 3 lines, one VID/PID, existing quirk bit. Possible extra USB
polling/power on that dongle only. Context-hunk tweak in `hid-
quirks.c`.
- **Ratio:** high benefit for affected hardware, very low regression
risk.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real, reproduced hang: dongle dies after idle; only unplug recovers.
- Standard **HID hardware quirk** (`HID_QUIRK_ALWAYS_POLL`), the stable-
rules exception for quirks/device IDs.
- 3 lines; no new APIs; no refactor.
- Infrastructure present in 5.15 since 2014; same quirk class already
backported here.
- Empirically verified (`usbhid.quirks=…:0x400` matches `BIT(10)`).
- HID maintainer applied v1 with no objections.
- Scoped to `0c45:fefe`; no HID collision on `0xfefe` in this tree.
AGAINST:
- Author did not list 5.15 among tested versions (tested 6.8+).
Mechanism is the same.
- `hid-quirks.c` needs a tiny context adjustment.
- Single reporter; not a crash/security bug.
- Relatively new keyboard on an old LTS — still the usual reason HID
ID/quirk backports exist.
UNRESOLVED:
- stable@ archive search (HTTP 403). Does not change the technical
verdict.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — 3-line table add; author
tested; maintainer applied.
2. Fixes a real bug that affects users? **PASS** — keyboard dies until
replug.
3. Important issue? **PASS** — device unusable after idle (quirk
exception; not a panic, but production-relevant for that hardware).
4. Small and contained? **PASS** — 3 lines, two HID files.
5. No new features or APIs? **PASS** — existing quirk bit + ID.
6. Can apply to the local tree? **PASS** — `hid-ids.h` clean; `hid-
quirks.c` one-hunk context fix.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **Hardware quirk / device ID on an existing driver** (HID
usbhid). Automatic YES class.
**Step 9.4: DECISION**
Backport. The bug exists on this tree’s usbhid, the quirk bit exists,
and this is the same pattern already used for 8BitDo/Edifier/ADATA on
5.15.
### What it solves for 5.15 users
Without ALWAYS_POLL, usbhid may stop interrupt polling; this Sonix-based
dongle then wedges until replugged. Adding the ID makes 5.15 keep
polling from probe, matching the module-param workaround.
### Risk vs benefit
Benefit is a working keyboard for that VID/PID. Risk is extra polling on
that device only. `hid-quirks.c` needs the JESS line inserted after the
INNOMEDIA entry because KYE rows differ from mainline.
### Concerns
None that block a YES: no missing prerequisites; not a new driver; apply
conflict is mechanical.
Verification:
- [Phase 1] Tags: author + Jiri Kosina SOB; no Fixes/stable/Reported-by.
- [Phase 1] Body: idle hang, replug recovery, tested 6.8/6.14/7.1.3,
`usbhid.quirks=0x0c45:0xfefe:0x400`.
- [Phase 2] Diff: +1 hid-ids.h, +2 hid-quirks.c; ALWAYS_POLL table
entry.
- [Phase 2] `HID_QUIRK_ALWAYS_POLL` is `BIT(10)` = `0x400` in
`include/linux/hid.h:373`.
- [Phase 3] `git describe HEAD` → `p-5.15-2-g9a29d9b0f9507`; `make
kernelversion` → 5.15.221.
- [Phase 3] ALWAYS_POLL intro `0b750b3baa2d6` (2014) is ancestor of
HEAD.
- [Phase 3] `USB_VENDOR_ID_JESS` blame `6bc235a2e24a5` (2010); lines
695-698 in this tree.
- [Phase 3] No AULA/0xfefe in `drivers/hid`; author has no HID commits
here.
- [Phase 3] Similar 5.15 backports: `f9ad98cff302c`, `16c2ca35257ed`,
`5c46ec760d3be`.
- [Phase 3] Upstream SHA `2884e21b18613708f050ec75330b265dd07ecc03`; not
ancestor of HEAD (exit 1).
- [Phase 4] `b4 dig -c 2884e21b18613`: lore match; To jikos, Cc
bentiss/linux-input.
- [Phase 4] `b4 dig -a`: v1 only. Mbox: Jiri “Applied, thanks.” No NAK.
- [Phase 4] lore.kernel.org WebFetch 403; used b4 mbox + LKML/openwall
mirrors.
- [Phase 5] `hid_lookup_quirk` used from hid-core.c and usbhid/hid-
core.c:992.
- [Phase 5] ALWAYS_POLL in usbhid open/close/start/stop in this tree.
- [Phase 6] `git apply --check`: hid-ids.h clean; hid-quirks.c fails at
line 113 (KYE order). 3-way conflict on quirks only.
- [Phase 7] HID usbhid; quirk table still receiving 5.15 backports.
- [Phase 8] Failure: keyboard dead until replug; severity HIGH for that
device; risk very low.
- UNVERIFIED: stable@ mailing-list archive (403). Not used as a NO
reason.
**YES**
drivers/hid/hid-ids.h | 1 +
drivers/hid/hid-quirks.c | 2 ++
2 files changed, 3 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index c1a7f5558ccd1..5169713539bc3 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -748,6 +748,7 @@
#define USB_DEVICE_ID_JESS_YUREX 0x1010
#define USB_DEVICE_ID_ASUS_MD_5112 0x5112
#define USB_DEVICE_ID_REDRAGON_ASURA 0x760b
+#define USB_DEVICE_ID_AULA_MINI_60_HE_PRO 0xfefe
#define USB_VENDOR_ID_JESS2 0x0f30
#define USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD 0x0111
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 3de594ee25c38..8d2ac32c5ac12 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -113,6 +113,8 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_1f4a), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680), HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI), HID_QUIRK_MULTI_INPUT },
+ { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_AULA_MINI_60_HE_PRO),
+ HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE_ID2), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406), HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M506), HID_QUIRK_MULTI_INPUT },
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH AUTOSEL 6.18-6.6] HID: i2c-hid: Add a quirk for a Cirque I2C device.
[not found] <20261019135441.1420968-1-sashal@kernel.org>
` (4 preceding siblings ...)
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.1] HID: quirks: add ALWAYS_POLL quirk for AULA Mini 60 HE Pro Dongle Sasha Levin
@ 2026-10-19 13:47 ` Sasha Levin
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.12] HID: amd_sfh: Serialize access to the shared emp2 pointer Sasha Levin
` (10 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:47 UTC (permalink / raw)
To: patches, stable
Cc: Vadim Klishko, Vadim Klishko, Benjamin Tissoires, Sasha Levin,
jikos, linux-input, linux-kernel
From: Vadim Klishko <vadim@cirque.corp-partner.google.com>
[ Upstream commit 1c942462c3969b287a86ab6dbb143324289d564e ]
Cirque touchpads with PID D0C1 generate an error when probed
by the I2C HID driver, resulting in no hidraw device created.
Adding I2C_HID_QUIRK_NO_IRQ_AFTER_RESET fixes the issue.
Signed-off-by: Vadim Klishko <vadim@cirque.com>
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
- Subsystem: `HID: i2c-hid`
- Action verb: `Add` (a quirk)
- Claimed intent: add `I2C_HID_QUIRK_NO_IRQ_AFTER_RESET` for Cirque I2C
touchpad PID D0C1
Record: `[HID/i2c-hid] [add] [hardware quirk so Cirque D0C1 touchpads
probe successfully]`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
- `Signed-off-by: Vadim Klishko <vadim@cirque.com>` (author; Cirque, the
device vendor)
- `Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>` (HID
maintainer; applied the patch)
- No `Fixes:` tag (expected)
- No `Cc: stable@vger.kernel.org` (expected)
- No `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-by:`, or
`Link:` tags in the committed message
- v1/v2/v3 changelog (from mailing list, not the commit body): v2 added
subsystem prefix and expanded the explanation; v3 was a Patchwork
resend. No code changes across revisions.
Record: Author is the hardware vendor; HID maintainer SOB. No
syzbot/stable tags.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Cirque touchpads with product ID D0C1 error during I2C-HID probe, so no
hidraw node is created. Applying the existing
`I2C_HID_QUIRK_NO_IRQ_AFTER_RESET` workaround fixes it.
Record:
- Bug: Cirque D0C1 fails I2C-HID probe
- Symptom: no hidraw device (touchpad unusable)
- Root cause (author): device needs the established “no IRQ after reset”
quirk
- Version info: none in the message; submitted Jul 2026, applied to hid
`for-7.3/upstream-fixes`
**Step 1.4: DETECT HIDDEN BUG FIXES**
Not disguised. It is an explicit hardware quirk, which the stable rules
treat as a real-world device fix.
Record: Not a hidden bug fix; it is a straightforward hardware quirk.
---
## PHASE 2: DIFF ANALYSIS - LINE BY LINE
**Step 2.1: INVENTORY THE CHANGES**
- `drivers/hid/hid-ids.h`: +1 (`#define I2C_PRODUCT_ID_CIRQUE_D0C1
0xD0C1`) next to existing `I2C_VENDOR_ID_CIRQUE` /
`I2C_PRODUCT_ID_CIRQUE_1063`
- `drivers/hid/i2c-hid/i2c-hid-core.c`: +2 (quirk table entry)
- Functions modified: none. Data only: ID macro + `i2c_hid_quirks[]`
entry
- Scope: single-file-class surgical (2 files, 3 lines). No new quirk
flag; reuses `I2C_HID_QUIRK_NO_IRQ_AFTER_RESET` (`BIT(0)`), already
used for Hantick 5288, ITE Voyo Winpad A15, and Raydium 3118 in this
tree.
Record: `[+3 lines, 2 files] [no functions] [surgical hardware quirk]`
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Before: D0C1 (`vendor 0x0488`, `product 0xD0C1`) has quirks `0`.
`i2c_hid_parse()` → `i2c_hid_finish_hwreset()` waits up to 1000 ms for a
reset-ACK IRQ.
After: lookup returns `I2C_HID_QUIRK_NO_IRQ_AFTER_RESET`.
`i2c_hid_finish_hwreset()` sleeps 100 ms and clears
`I2C_HID_RESET_PENDING` instead of waiting for the IRQ.
Path: device probe / HID parse (and resume only if `RESET_ON_RESUME` is
also set; this entry does not set that).
Record: `[probe reset-wait → 100 ms sleep, skip IRQ wait, for VID 0x0488
/ PID 0xD0C1 only]`
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Category: **(h) Hardware workaround** (device ID + quirk table).
Mechanism: some I2C-HID devices never send the reset-complete interrupt.
The same quirk is already documented for Hantick (`402946a8ef71eb`: bind
fails with `"failed to reset device"`), ITE (`fc6a31b007393`: `"can't
add hid device: -61"`), and Raydium (`0c8432236dea2`). Hans de Goede
later made a missing ACK a warning rather than `-ENODATA`
(`7bcf9ebb50f2a`, in this tree), but a device that emits a bogus IRQ
during the wait can still break the following report-descriptor read
(`i2c_hid_parse` logs `"reading report descriptor failed"` and
`hid_add_device` fails → no hidraw). The vendor says this quirk fixes
that on D0C1.
Record: `[hardware quirk] [skip reset-ACK IRQ wait for Cirque D0C1]`
**Step 2.4: ASSESS THE FIX QUALITY**
Obviously correct: additive, ID-matched, uses a long-standing quirk.
Risk is confined to 0x0488:0xD0C1. No API, locking, or allocator
changes. Same 3-line shape as prior stable-worthy i2c-hid quirks.
Record: `[high quality, minimal] [regression risk very low, ID-scoped]`
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
- Cirque 1063 ID + `NO_SLEEP_ON_SUSPEND`: `26dd6a5667f500` (Kai-Heng
Feng, 2024-01-23) — already in this tree
- `I2C_HID_QUIRK_NO_IRQ_AFTER_RESET` handling in
`i2c_hid_finish_hwreset()`: present (lines 500–502)
- Quirk table terminator `{ 0, 0 }` from original table
(`71af01a8c85ad8`, 2016)
The “buggy” behavior is the generic reset-ACK wait vs this panel’s
firmware, not a recent regression. D0C1 is a new product ID of an
existing vendor.
Record: `[generic reset-ACK wait vs D0C1 firmware] [quirk infra since
~2017; Cirque vendor ID since 2024 / v6.8]`
**Step 3.2: FOLLOW THE FIXES: TAG**
No `Fixes:` tag. Not applicable.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Recent `i2c-hid-core.c` work in this tree is unrelated (report-
descriptor error text, Dell S4, buffer overflow). Not part of a numbered
series.
Record: `[standalone] [no prerequisites beyond existing quirk flag +
Cirque vendor define, both present]`
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
`git log --author="Vadim Klishko"` / `"Klishko"` in this tree: no
commits. First-time contributor; affiliation is the touchpad vendor
(`vadim@cirque.com`, Google corp-partner address on the list). HID
maintainer Benjamin Tissoires applied it (`for-7.3/upstream-fixes`, SHA
`1c942462c396`).
Record: `[vendor patch, maintainer-applied] [no other related commits in
this tree]`
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Mainline context after the new entry mentions
QTEC/`I2C_HID_QUIRK_RE_POWER_ON` and BLTP; those IDs are **not** in
6.12. The added lines do not use them. Required pieces in this tree:
- `I2C_VENDOR_ID_CIRQUE` (yes)
- `I2C_HID_QUIRK_NO_IRQ_AFTER_RESET` and its `i2c_hid_finish_hwreset()`
handling (yes)
- `i2c_hid_lookup_quirk()` (yes)
Record: `[standalone on 6.12] [QTEC/BLTP are context-only, not
dependencies]`
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
`b4 dig -c 1c942462c396` matched patch-id
`d0e1a0779d3e935e26ea6a8cb93b1b9f683a32a4`.
Revisions:
- v1: https://patch.msgid.link/20260703144726.14808-1-vadim@cirque.com
(subject lacked `HID: i2c-hid:`)
- v2: https://patch.msgid.link/20260708003108.20288-1-vadim@cirque.com
(subject + explanation; **no code change**)
- v3: https://patch.msgid.link/20260728041718.32954-1-vadim@cirque.com
(Patchwork resend; **no code change**)
- Applied: Benjamin Tissoires, 2026-08-25, hid.git `for-7.3/upstream-
fixes` (`1c942462c396`)
No NAKs in v1/v2/v3 archives (openwall/patchew). No reviewer-requested
code changes. No explicit `Cc: stable` on the list.
Record: `[lore/msgid as above] [v1→v3, code unchanged] [applied by HID
maintainer] [no NAKs]`
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
`b4 dig -w` original recipients: `vadim@cirque.com`, `jikos@kernel.org`,
`linux-input@vger.kernel.org`, `linux-kernel@vger.kernel.org`. v3 also
CCd Benjamin Tissoires and Hans de Goede (i2c-hid quirk author). Apply
mail CCd `hansg@kernel.org`. No written `Reviewed-by`, but the
maintainer applied it.
Record: `[HID maintainers Kosina/Tissoires; de Goede CCd; applied by
Tissoires]`
**Step 4.3: SEARCH FOR THE BUG REPORT**
No bugzilla/syzbot link. Evidence is the vendor’s report: probe error,
no hidraw, quirk fixes it. Author is Cirque.
Record: `[vendor-reported probe failure] [severity: device does not
enumerate] [user count unverified beyond vendor]`
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Standalone 1/1. Not a multi-patch series.
Record: `[standalone]`
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Web search of lore.kernel.org/stable for Cirque D0C1 i2c-hid did not
turn up discussion of this patch (results were unrelated historical
stable traffic).
Record: `[no stable-list discussion found]`
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
No function bodies changed. The new table entry is consumed by
`i2c_hid_lookup_quirk()`, which feeds `ihid->quirks`, consumed by
`i2c_hid_finish_hwreset()`.
Record: `[i2c_hid_quirks[] data; consumers: i2c_hid_lookup_quirk,
i2c_hid_finish_hwreset]`
**Step 5.2: TRACE CALLERS**
- `i2c_hid_lookup_quirk()`: only from `__i2c_hid_core_probe()` after
reading the HID descriptor vendor/product — so the quirk is installed
before `hid_add_device()` / parse.
- `i2c_hid_finish_hwreset()`: from `i2c_hid_parse()` (probe) and
`i2c_hid_core_resume()` (only if `I2C_HID_QUIRK_RESET_ON_RESUME`; this
ID does not set that).
Record: `[probe path via hid_add_device → i2c_hid_parse] [resume reset
path not used for this ID]`
**Step 5.3: TRACE CALLEES**
With the quirk, `i2c_hid_finish_hwreset()` calls `msleep(100)` and
`clear_bit(I2C_HID_RESET_PENDING)`. Then, unless
`NO_WAKEUP_AFTER_RESET`, `i2c_hid_set_power(PWR_ON)`.
Record: `[msleep + clear reset-pending; then existing PWR_ON]`
**Step 5.4: FOLLOW THE CALL CHAIN**
ACPI/OF I2C-HID probe → `__i2c_hid_core_probe` (descriptor + quirk
lookup) → `i2c_hid_core_register_hid` → `hid_add_device` →
`i2c_hid_parse` → hwreset → read report descriptor → hidraw/input.
Reachable on boot for machines with this touchpad; not a syscall fuzz
path, but a normal laptop input device.
Record: `[boot/probe of Cirque D0C1 I2C touchpad] [userspace-visible:
hidraw/input missing without quirk]`
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Same quirk already in this tree for Hantick, ITE Voyo, Raydium 3118.
This is the same pattern, new ID.
Record: `[three existing NO_IRQ_AFTER_RESET entries; this is a fourth
ID]`
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Local tree: `pending-6.12`, `make kernelversion` = **6.12.111**, `git
describe HEAD` = `p-6.12-3-gc504cf0baa3d8`.
- `I2C_PRODUCT_ID_CIRQUE_D0C1` is **absent** (`git grep` no matches)
- `git merge-base --is-ancestor 1c942462c396 HEAD` → not an ancestor
(exit 1)
- Driver, quirk flag, lookup, and Cirque vendor ID **are** present
- Without the table entry, D0C1 takes the generic reset-ACK wait that
the vendor says fails probe
Record: `[yes, buggy generic path exists; D0C1 quirk not yet applied]
[bug is device firmware vs long-standing reset wait]`
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
`hid-ids.h` context around `CIRQUE_1063` matches; should apply cleanly.
`i2c-hid-core.c`: insertion after the 1063 entry matches; following
context in mainline is QTEC (not in 6.12; here it is the ELAN comment).
At most fuzz/trivial context adjust. No refactor of the quirk table.
Record: `[clean or trivial fuzz] [no rework of logic]`
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
No D0C1 ID. Cirque 1063 has a *different* quirk (`NO_SLEEP_ON_SUSPEND`).
`7bcf9ebb50f2a` only demotes missing ACK to a warning; vendor still
needed this ID-specific quirk.
Record: `[no existing D0C1 fix; 1063 quirk is unrelated]`
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
`drivers/hid/i2c-hid/` — laptop/Chromebook I2C HID touchpads. Not
mm/core, but a common input path.
Record: `[HID i2c-hid] [IMPORTANT / driver-specific]`
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Mature driver (2012+). Quirk table still gets ID additions; that is
normal, not a rewrite.
Record: `[mature; ID/quirk additions are the usual change]`
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
Only I2C-HID devices with HID descriptor VID/PID `0488:D0C1`. Everyone
else unchanged.
Record: `[driver/hardware-specific: Cirque D0C1 touchpads]`
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Every probe of that touchpad (boot). Not a race. Unprivileged users
cannot trigger it beyond having the hardware.
Record: `[every boot on affected machines] [common for those users] [not
a syscall exploit path]`
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Probe fails → no hidraw/input → touchpad dead. Not a panic. Matches
ITE’s historic `"can't add hid device"` failure.
Record: `[device fails to enumerate] [severity: HIGH for affected
hardware, none otherwise]`
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Benefit: touchpad works on 6.12 LTS (ChromeOS/enterprise/Ubuntu-class
kernels still on 6.12).
Risk: 3 lines, existing quirk, ID-gated.
Record: `[benefit high for D0C1 users] [risk very low] [favorable]`
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Explicit hardware quirk; stable rules call these YES
- Real user-visible bug: probe error, no hidraw (vendor-confirmed)
- 3 lines, existing `I2C_HID_QUIRK_NO_IRQ_AFTER_RESET`
- Same shape as Hantick/ITE/Raydium quirks already in this tree
- HID maintainer applied it; author is Cirque
- Driver, quirk flag, and Cirque vendor ID exist in 6.12.111
- No new API/feature flag
AGAINST:
- No `Fixes:` / `Cc: stable` (not a negative per instructions)
- No public repro logs beyond the commit text
- `7bcf9ebb50f2a` tried to reduce new `NO_IRQ_AFTER_RESET` quirks; this
device still needed one
- Mainline hunk context (QTEC) differs; trivial apply fuzz only
- Affects one product ID, not all machines
UNRESOLVED:
- Exact errno/log line on D0C1 was not posted (only “error” / no hidraw)
- How many shipping systems use D0C1 is unverified
- lore.kernel.org WebFetch returned 403; discussion recovered via b4 dig
+ openwall/patchew
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — 3-line ID quirk; vendor-
tested; maintainer applied
2. Fixes a real bug that affects users? **PASS** — probe failure, no
hidraw
3. Important issue? **PASS** — input device does not work (hardware bug,
not a panic)
4. Small and contained? **PASS** — +3 lines, two files
5. No new features or APIs? **PASS** — existing quirk + new device ID
6. Can apply to the local tree? **PASS** — logic applies; at most
context fuzz around QTEC vs ELAN
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Yes: **hardware quirk** and **device ID addition to an existing
driver**.
**Step 9.4: DECISION**
This is a textbook stable backport: a 3-line i2c-hid quirk so a Cirque
D0C1 touchpad enumerates. The 6.12 tree already has the driver and quirk
machinery; only the ID is missing. Benefit is restoring input on
affected machines; regression risk is limited to that PID.
---
## What this solves for 6.12 users
Cirque D0C1 I2C touchpads fail I2C-HID probe, so hidraw/input never
appear. The quirk skips waiting for a reset-ACK IRQ (100 ms sleep
instead), which is the established workaround. On 6.12 that path still
exists; without the ID, those panels stay dead.
## Risk vs benefit
Benefit is a working touchpad on affected laptops/Chromebooks still on
6.12. Risk is a 3-line, VID/PID-gated table addition using a quirk
already used by three other devices in this tree.
## Concerns
Apply may need trivial context adjustment because 6.12’s quirk table
does not yet have the later QTEC/BLTP entries. No functional
dependencies. Exact probe errno was not published; the vendor statement
plus matching historical quirks is enough.
---
Verification:
- [Phase 1] Parsed subject/tags/body: vendor SOB Vadim Klishko;
maintainer SOB Benjamin Tissoires; no Fixes/stable/syzbot tags
- [Phase 2] Diff: +1 hid-ids.h define `I2C_PRODUCT_ID_CIRQUE_D0C1
0xD0C1`; +2 `i2c_hid_quirks[]` with `I2C_HID_QUIRK_NO_IRQ_AFTER_RESET`
- [Phase 2] Read `i2c_hid_finish_hwreset()`: quirk does `msleep(100)` vs
1000 ms `wait_event_timeout`
- [Phase 2] Confirmed `I2C_HID_QUIRK_NO_IRQ_AFTER_RESET` is `BIT(0)` at
line 47
- [Phase 3] `git describe HEAD` / `make kernelversion`: pending-6.12,
6.12.111
- [Phase 3] `git merge-base --is-ancestor 1c942462c396 HEAD`: not in
tree (exit 1)
- [Phase 3] `git grep I2C_PRODUCT_ID_CIRQUE_D0C1`: no matches
- [Phase 3] `git blame` hid-ids Cirque lines: `26dd6a5667f500` (2024, in
tree)
- [Phase 3] `git blame` quirk table: Hantick/ITE/Raydium already have
the same quirk
- [Phase 3] `git log --author=Klishko`: no commits in this tree
- [Phase 3] QTEC/BLTP/`I2C_HID_QUIRK_RE_POWER_ON`: absent; not required
by this patch
- [Phase 3] Compared prior quirks: `0c8432236dea2` (Raydium),
`fc6a31b007393` (ITE), `402946a8ef71eb` (Hantick) — same 2-file
+3-line pattern
- [Phase 3] `7bcf9ebb50f2a` in tree: missing ACK is a warning, not
`-ENODATA`; vendor still needed the quirk
- [Phase 4] `b4 dig -c 1c942462c396`: patch-id match; v1/v2/v3 msgids
listed above
- [Phase 4] `b4 dig -a`: v2 listed as series; v3 applied with no code
changes from v1
- [Phase 4] `b4 dig -w`: To/Cc Jiri Kosina, linux-input, linux-kernel
- [Phase 4] Openwall/patchew: Tissoires applied to hid.git
`for-7.3/upstream-fixes`; no NAKs
- [Phase 4] lore.kernel.org WebFetch: 403; used b4 + openwall/patchew
instead
- [Phase 4] Stable-list search: no discussion of this patch found
- [Phase 5] Callers: `i2c_hid_lookup_quirk` from `__i2c_hid_core_probe`;
`i2c_hid_finish_hwreset` from `i2c_hid_parse` and resume-with-
RESET_ON_RESUME
- [Phase 5] Parse path: reset then `i2c_hid_read_register` of report
descriptor; failure → no hid_add_device/hidraw
- [Phase 6] Local files match needed APIs; D0C1 ID missing
- [Phase 8] Failure mode: probe/enumeration failure for one touchpad
PID, not a panic
- UNVERIFIED: exact dmesg/errno on D0C1; number of shipping units; live
lore.kernel.org HTML (403)
**YES**
drivers/hid/hid-ids.h | 1 +
drivers/hid/i2c-hid/i2c-hid-core.c | 2 ++
2 files changed, 3 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 5169713539bc3..11f120a5d1b90 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -333,6 +333,7 @@
#define I2C_VENDOR_ID_CIRQUE 0x0488
#define I2C_PRODUCT_ID_CIRQUE_1063 0x1063
+#define I2C_PRODUCT_ID_CIRQUE_D0C1 0xD0C1
#define USB_VENDOR_ID_CJTOUCH 0x24b8
#define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020 0x0020
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index 6d407cbed1886..29c4f624f3c5c 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -136,6 +136,8 @@ static const struct i2c_hid_quirks {
I2C_HID_QUIRK_BAD_INPUT_SIZE },
{ I2C_VENDOR_ID_CIRQUE, I2C_PRODUCT_ID_CIRQUE_1063,
I2C_HID_QUIRK_NO_SLEEP_ON_SUSPEND },
+ { I2C_VENDOR_ID_CIRQUE, I2C_PRODUCT_ID_CIRQUE_D0C1,
+ I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
/*
* Without additional power on command, at least some QTEC devices send garbage
*/
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH AUTOSEL 6.18-6.12] HID: amd_sfh: Serialize access to the shared emp2 pointer
[not found] <20261019135441.1420968-1-sashal@kernel.org>
` (5 preceding siblings ...)
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.6] HID: i2c-hid: Add a quirk for a Cirque I2C device Sasha Levin
@ 2026-10-19 13:47 ` Sasha Levin
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18-5.10] HID: multitouch: Fix stale MT slots when contact count drops to zero Sasha Levin
` (9 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:47 UTC (permalink / raw)
To: patches, stable
Cc: Basavaraj Natikar, Jiri Kosina, Sasha Levin, basavaraj.natikar,
jikos, bentiss, linux-input, linux-kernel
From: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
[ Upstream commit c57016bcf6d0b57cda5579e5d6856bd9bbe52a77 ]
The SFH accessors reach the device through a file-global emp2 pointer
that is published at probe and cleared on remove. amd_get_sfh_info() is
exported and called from other modules on unrelated threads, so a reader
can observe a non-NULL emp2 and then race a concurrent unbind that clears
it and frees the device.
Serialize the emp2 publish/clear and all readers under a mutex, so a
reader either sees a live device for the whole access or sees NULL.
Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **6.12.111**. The buggy global `emp2` pointer and
exported `amd_get_sfh_info()` are in this checkout; the 6-line mutex fix
applies here.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: **[HID: amd_sfh]** **[Serialize]** Serialize access to the
shared `emp2` pointer used by exported SFH accessors.
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Signed-off-by: Basavaraj Natikar (author; AMD SFH maintainer)
- Signed-off-by: Jiri Kosina (HID maintainer; applied the patch)
- No Fixes, Reported-by, Tested-by, Reviewed-by, Acked-by, Link, or Cc:
stable on the committed message (absence of Fixes/Cc:stable is
expected for this review)
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- **Bug:** File-global `emp2` is published at probe
(`sfh_interface_init`) and cleared on remove (`sfh_deinit_emp2`).
`amd_get_sfh_info()` is `EXPORT_SYMBOL_GPL` and is called from other
modules on other threads.
- **Symptom/failure mode:** A reader can see a non-NULL `emp2`, then a
concurrent unbind NULLs it and frees the device → use-after-free /
MMIO against freed `amd_mp2_dev`.
- **Version info:** None in the message. Introduced with HPD export in
v6.8 (`b5b0774d53bb81`). Present in this 6.12 tree.
- **Root cause (author):** Missing serialization between publish/clear
and all readers.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not disguised. It is an explicit race/UAF fix. Cover letter for
the v3 series also calls patches 1–2 “preparation” for SW_TABLET_MODE,
but the mutex independently closes an existing unbind-vs-reader UAF. It
is not a pure refactor with no standalone value.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- File: `drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c` (+6 / −0)
- Functions: file-scope `emp2_lock`; `sfh_deinit_emp2`;
`sfh_interface_init`; `amd_get_sfh_info`
- Scope: single-file surgical fix
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: `emp2 = mp2` / `emp2 = NULL` with no lock.
`amd_get_sfh_info()` checks `emp2` then dereferences `emp2->mmio` /
`emp2->vsbase` unlocked.
- After: `DEFINE_MUTEX(emp2_lock)`; `guard(mutex)(&emp2_lock)` around
publish, clear, and the whole reader. A reader either keeps a live
device for the full access or sees NULL.
- Paths: probe/init, remove/error-deinit, and the exported reader
(normal path from AMD PMF work).
Step 2.3: IDENTIFY THE BUG MECHANISM
Record: **Race / UAF (check-then-use on a global device pointer).**
Writers and the exported reader were unsynchronized. Mutex makes
publish/clear and MMIO mutually exclusive. Helpers `amd_sfh_hpd_info` /
`amd_sfh_als_info` stay unlocked internally but are static and only
called from `amd_get_sfh_info()` while that lock is held.
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Obviously correct for this TOCTOU.
- Minimal; no API or structure change.
- Regression risk low: mutex is not nested; readers run in PMF delayed
work (sleepable); remove already sleeps (`flush_work`). Holding the
lock across `readl`/`memcpy_fromio` can delay unbind slightly; that is
the intended tradeoff vs UAF.
- `linux/cleanup.h` + `guard(mutex)` exist in 6.12; `mutex.h` is already
pulled in via `amd_sfh_common.h`.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record: `emp2`, `sfh_deinit_emp2`, `amd_get_sfh_info`, and
`EXPORT_SYMBOL_GPL` come from **b5b0774d53bb81** (“HID: amd_sfh: Add a
new interface for exporting HPD data”, 2023-12-20). ALS reader added in
**584f35a3647d42**. Both are in v6.8 and in this tree. The race is old
relative to 6.12, not new mainline-only code.
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes tag. Buggy pattern is the unlocked global from
b5b0774d53bb81, which **is** an ancestor of HEAD.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record: Recent 6.12 history on this file is register-access helpers
(`7902ec988a9a6`, `6296562f30b1c`), not locking. Origin/master later
added MT_SRA / tablet-mode around this commit; those features are
**not** in this tree. No existing emp2 lock here.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Basavaraj Natikar is listed in MAINTAINERS for AMD SENSOR FUSION
HUB. Same author added the export and later SFH1.1 work. Series v3 was
applied by Jiri Kosina.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: Committed as **[PATCH v3 2/5]** in “Add SW_TABLET_MODE support”.
- 1/5 “Track MP2 version explicitly” (`1a73a4e7673f57`) is **not** in
HEAD and is **not** required for this mutex (different files/fields).
- 3–5 add operating-mode accessor, aux device, and a new input driver —
features, not needed for this fix.
- This patch is self-contained. `git apply --check` of c57016bcf6d0b on
this tree **succeeds** (hunk 3 offset −35: no
`amd_sfh_mode_info`/`MT_SRA` in 6.12).
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- Lore/msgid: https://patch.msgid.link/20260803175230.3839752-3-
Basavaraj.Natikar@amd.com
- Series: v1 (operating-mode only) → v2 0/5 → **v3 2/5** (applied).
- Cover letter (v3 0/5): patches 1–2 are preparation; v2 notes from
Sashiko review: serialize emp2 so concurrent unbind cannot free the
device while a reader dereferences it.
- Jiri Kosina queued the series in hid.git#for-7.3/amd-sfh. No NAK. No
Cc: stable in review.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: To/Cc: jikos@kernel.org, bentiss@kernel.org,
dmitry.torokhov@gmail.com, linux-input@. HID maintainers were on the
series. Dmitry Acked-by is on 5/5 (input driver), not this patch.
Applied by Jiri Kosina.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla. Race found in review of the tablet-mode
series, not a user crash report. The existing PMF caller was already
racy.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: 2/5 is the UAF serialization. 3/5 also adds `sfh_set_emp2()` and
uses `emp2_lock`; that is extra feature plumbing, not required to lock
the 6.12 HPD/ALS paths.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: lore.kernel.org/stable search returned HTTP 403. UNVERIFIED
whether stable@ discussed this. No evidence in the input thread of a
stable nomination or a rejection.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `sfh_deinit_emp2`, `sfh_interface_init`, `amd_get_sfh_info`; new
`emp2_lock`.
Step 5.2: TRACE CALLERS
Record:
- `sfh_interface_init`: `amd_sfh_set_ops()` ← `amd_sfh1_1_init()`
(SFH1.1 probe work).
- `sfh_deinit_emp2`: `amd_mp2_pci_remove` (unbind) and error paths in
`amd_sfh1_1_init` after publish.
- `amd_get_sfh_info`: `amd_pmf_get_sensor_info()` in
`drivers/platform/x86/amd/pmf/spc.c` (MT_ALS, MT_HPD) ←
`amd_pmf_populate_ta_inputs` ← `amd_pmf_invoke_cmd_enact` ← delayed
work `amd_pmf_invoke_cmd` every `pb_actions_ms` (default **1000 ms**).
Step 5.3: TRACE CALLEES
Record: Readers do `readl` / `memcpy_fromio` on `emp2->mmio` /
`emp2->vsbase`. Remove then `amd_sfh_hid_client_deinit`, `stop_all`, PCI
intx/intr clear. `mp2` is `devm_kzalloc`; mapping is `pcim_iomap` —
freed after PCI remove.
Step 5.4: FOLLOW THE CALL CHAIN
Record: Reachable without the new tablet driver: AMD PMF policy work
(typical on AMD laptops with PMF) vs SFH1.1 unbind (`amd_sfh_remove` →
`mp2_ops->remove`). Not a syscall hot path; unbind is admin/module/PCI.
Still a real concurrent path: 1 Hz reader vs remove.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Only this file holds `emp2`. No sibling unlocked copy in 6.12.
Later mainline adds more readers (MT_OP_MODE at 200 ms); those are not
in this tree.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: Yes. `drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c`:
unlocked `static struct amd_mp2_dev *emp2`, `sfh_deinit_emp2` sets NULL,
`amd_get_sfh_info` is exported. Introduced v6.8; this tree is 6.12.111.
`git merge-base --is-ancestor c57016bcf6d0b HEAD` → **not present**.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: **Clean apply** (`git apply --check` succeeded; one hunk
offset). 6.12 lacks `amd_sfh_mode_info`/`MT_SRA`; that is context only.
`guard(mutex)` and `DEFINE_MUTEX` are available.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: `edeae8be4d263` syncs SFH work functions — different bug. No
emp2 mutex. d1c444b47100d / 01601fdd40ecf not in HEAD (and not
required).
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: HID / AMD SFH (`drivers/hid/amd-sfh-hid/`), plus AMD PMF
consumer. **IMPORTANT** for AMD Ryzen laptops with SFH1.1 (HPD/ALS) and
PMF; not core mm/VFS. Config: `CONFIG_AMD_SFH_HID`.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Mature driver (since ~5.11), still receiving fixes. Export of
`emp2` is from 6.8; the unlocked design lasted until the 7.3 tablet-mode
series.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Driver-specific: AMD SFH1.1 (PCI ID MP2 1.1) **and** AMD PMF
loaded. Typical modern AMD notebooks, not all machines.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Concurrent `amd_get_sfh_info` (PMF delayed work, default 1 s)
with `sfh_deinit_emp2` (unbind, rmmod, or probe error after publish).
Unprivileged users cannot normally unbind. Window is small but standard
check-then-use. New 200 ms tablet poll is **not** in this tree, so
trigger rate here is lower than mainline after 7.3.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: Use-after-free of `amd_mp2_dev` / MMIO after `devm` teardown →
oops/panic, possibly memory corruption. **HIGH**. Not a guaranteed panic
on every boot.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: closes a real UAF on a supported unbind path for SFH1.1+PMF
systems.
- Risk: 6 lines, existing mutex helpers, no ABI change; apply is clean.
- Ratio: favorable. Preparation-for-feature context does not make the
existing race fictional.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Real UAF race on a global pointer vs exported cross-module reader
(verified call path: PMF work → `amd_get_sfh_info` vs
`amd_mp2_pci_remove`).
- Buggy code in this 6.12 tree since v6.8.
- 6-line, obviously correct mutex; maintainer-authored; HID maintainer
applied.
- Applies cleanly here.
- `guard(mutex)` already used elsewhere in 6.12.
AGAINST:
- Sent as 2/5 “preparation” for SW_TABLET_MODE, not as a standalone
stable fix.
- No user/syzbot report; narrow unbind window; no Cc: stable (not a
negative per rules).
- Later series patches must **not** come along (new feature).
UNRESOLVED:
- Stable list discussion (lore/stable 403).
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — mutex around the only
publisher/clearer and the only exported reader; merged to hid.git
after review.
2. Fixes a real bug that affects users? **PASS** — UAF if SFH1.1 unbinds
while PMF polls.
3. Important issue? **PASS** — UAF / crash / possible memory corruption
(HIGH).
4. Small and contained? **PASS** — +6 lines, one file.
5. No new features or APIs? **PASS** — locking only. (3–5 of the series
would FAIL this; they are out of scope.)
6. Can apply to the local tree? **PASS** — `git apply --check`
succeeded.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: None (not a device ID / quirk / DT / build / doc exception).
Qualifies as a normal race/UAF bugfix.
Step 9.4: MAKE YOUR DECISION
This tree has the unlocked `emp2` export and the PMF reader. The patch
does not need MP2 version tracking or tablet-mode. It should be
backported here.
------------------------------------------------
What problem it solves for stable users
------------------------------------------------
On 6.12, AMD PMF’s delayed work calls `amd_get_sfh_info()` about once a
second. That function tests the file-global `emp2` and then uses
`emp2->mmio` / `emp2->vsbase`. Remove (`amd_sfh_remove` →
`amd_mp2_pci_remove`) sets `emp2 = NULL` and then tears down a
`devm_kzalloc`’d `amd_mp2_dev`. Without a lock, a reader can keep using
a pointer to already-freed device/MMIO. The mutex makes that impossible.
Why it meets stable rules
Small, correct, no new API, applies here, fixes a real UAF. Being patch
2/5 of a feature series is not a dependency: 1/5 and 3–5 are unrelated
or features.
Risk vs benefit
Low risk, meaningful benefit on AMD SFH1.1 + PMF systems. Do not pull
the rest of the tablet-mode series.
Concerns
Backport only this commit. Context offset on `amd_get_sfh_info` (no
MT_SRA) is already handled by a clean apply.
Verification:
- [Phase 1] Parsed tags: only two SOBs (Natikar, Kosina); no
Fixes/Reported-by/Cc:stable
- [Phase 1] Cover letter (mbox): “Patches 1 and 2 are preparation”; v2
changelog describes the unbind UAF
- [Phase 2] Diff: +6 lines, mutex + three `guard(mutex)` sites in one
file
- [Phase 3] git describe HEAD / Makefile: **p-6.12-3-gc504cf0baa3d8**,
version **6.12.111**
- [Phase 3] git blame: emp2/export from b5b0774d53bb81; `git merge-base
--is-ancestor b5b0774d53bb81 HEAD` → yes; in v6.8
- [Phase 3] git merge-base --is-ancestor c57016bcf6d0b HEAD → **no**
(candidate not in this tree)
- [Phase 3] Parent 1a73a4e7673f57 “Track MP2 version” not in HEAD; not
required by this diff
- [Phase 4] b4 dig -c c57016bcf6d0b: https://patch.msgid.link/2026080317
5230.3839752-3-Basavaraj.Natikar@amd.com
- [Phase 4] b4 dig -a: v1 → v2 0/5 → v3 2/5 applied
- [Phase 4] b4 dig -w: linux-input, jikos, bentiss, dmitry.torokhov
- [Phase 4] mbox: Jiri queued for-7.3/amd-sfh; no NAK; no stable
nomination
- [Phase 4] lore.kernel.org WebFetch: 403; stable@ search UNVERIFIED
- [Phase 5] Callers: amd_pmf_get_sensor_info → delayed work default 1000
ms; deinit from amd_mp2_pci_remove and probe error paths
- [Phase 6] Current file still has unlocked emp2; apply --check of
c57016bcf6d0b succeeded (hunk 3 offset −35)
- [Phase 6] include/linux/cleanup.h and DEFINE_GUARD(mutex) in
include/linux/mutex.h present; mutex.h included via amd_sfh_common.h
- [Phase 8] Failure mode: UAF of amd_mp2_dev/MMIO on unbind vs PMF
reader; severity HIGH
- UNVERIFIED: whether anyone asked for this on stable@ (HTTP 403)
**YES**
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
index 837d59e7a6610..dd2720bae65c3 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
@@ -8,12 +8,14 @@
* Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
*/
#include <linux/amd-pmf-io.h>
+#include <linux/cleanup.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/iopoll.h>
#include "amd_sfh_interface.h"
static struct amd_mp2_dev *emp2;
+static DEFINE_MUTEX(emp2_lock);
static int amd_sfh_wait_response(struct amd_mp2_dev *mp2, u8 sid, u32 cmd_id)
{
@@ -78,12 +80,14 @@ static struct amd_mp2_ops amd_sfh_ops = {
void sfh_deinit_emp2(void)
{
+ guard(mutex)(&emp2_lock);
emp2 = NULL;
}
void sfh_interface_init(struct amd_mp2_dev *mp2)
{
mp2->mp2_ops = &amd_sfh_ops;
+ guard(mutex)(&emp2_lock);
emp2 = mp2;
}
@@ -160,6 +164,8 @@ static int amd_sfh_als_info(u32 *ambient_light)
int amd_get_sfh_info(struct amd_sfh_info *sfh_info, enum sfh_message_type op)
{
+ guard(mutex)(&emp2_lock);
+
if (sfh_info) {
switch (op) {
case MT_HPD:
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH AUTOSEL 6.18-5.10] HID: multitouch: Fix stale MT slots when contact count drops to zero
[not found] <20261019135441.1420968-1-sashal@kernel.org>
` (6 preceding siblings ...)
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-6.12] HID: amd_sfh: Serialize access to the shared emp2 pointer Sasha Levin
@ 2026-10-19 13:48 ` Sasha Levin
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18] HID: elecom: Add support for ELECOM M-XT4DRBK (018E) Sasha Levin
` (8 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:48 UTC (permalink / raw)
To: patches, stable
Cc: Dave Carey, Benjamin Tissoires, Sasha Levin, jikos, linux-input,
linux-kernel
From: Dave Carey <carvsdriver@gmail.com>
[ Upstream commit e8e60b6439eed340a611e9d7a5b9bcbd0ef62725 ]
The INGENIC 17EF:6161 touchscreen (Lenovo Yoga Book 9 14IAH10) reports
HID_DG_CONTACTCOUNT=0 in the frame immediately following the last finger
lift rather than omitting the frame entirely. In mt_touch_report() the
existing code only updates num_expected when contact_count is non-zero,
so a zero contact count on the first packet of a new frame leaves
num_expected at its previous value (e.g. 2 for a two-finger gesture).
The sync check "num_received >= num_expected" then evaluates "0 >= 2"
and never fires, preventing INPUT_MT_DROP_UNUSED from releasing the
stale slots. Those slots remain active in the kernel MT layer until the
next touch, at which point they are released in a batch alongside the
new contact — causing the userspace event consumer to miss the
intervening finger-up sequence and corrupt its gesture session state.
Fix by resetting num_expected to 0 when contact_count is zero and
num_received is still 0 (i.e., this is the first and only packet of the
frame, not a continuation packet in a multi-packet sequence). With
num_expected=0 the sync check "0 >= 0" fires immediately, calling
input_mt_sync_frame() which drops the stale slots via
INPUT_MT_DROP_UNUSED.
The num_received==0 guard is critical: continuation packets in a
multi-packet frame arrive after at least one contact has already been
processed (num_received>0), so they are correctly excluded from this
path and the existing multi-packet logic is unaffected.
Signed-off-by: Dave Carey <carvsdriver@gmail.com>
Tested-by: Dave Carey <carvsdriver@gmail.com>
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough to decide: the buggy `num_expected` path is in this 6.12
tree, the Yoga Book 9 prerequisites are already here, and the patch
applies cleanly.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: PARSE THE SUBJECT LINE
Record: **[HID: multitouch:] [Fix] [stale MT slots when a zero
ContactCount sentinel frame never syncs, so unused slots are not
dropped]**
### Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- **Fixes:** none (expected for this review)
- **Reported-by:** none
- **Tested-by:** Dave Carey \<carvsdriver@gmail.com\> (author tested on
the affected laptop)
- **Reviewed-by:** none in the commit; HID maintainer Benjamin Tissoires
reviewed on-list and applied it
- **Acked-by:** none
- **Link:** none in the commit
- **Cc: stable:** none (expected)
- **Signed-off-by:** Dave Carey (author); Benjamin Tissoires (HID
maintainer)
- Ignore pipeline-added Sasha Levin SOB / `[Upstream commit ...]` if
present
### Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- **Bug:** INGENIC 17EF:6161 (Lenovo Yoga Book 9 14IAH10) sends
`HID_DG_CONTACTCOUNT=0` on the frame after the last finger lift.
`mt_touch_report()` only updates `num_expected` when `contact_count`
is non-zero, so a first packet with count 0 leaves `num_expected` at
the previous value (e.g. 2).
- **Symptom / failure mode:** `num_received >= num_expected` becomes `0
>= 2` and never fires. `INPUT_MT_DROP_UNUSED` does not run. Slots stay
active until the next touch, then are released together with the new
contact. Userspace misses the finger-up sequence and corrupts gesture
state (stuck touch).
- **Version info:** none in the message. Logic has been in hid-
multitouch since 2017; this hardware/class is recent.
- **Root cause:** zero ContactCount on the first packet of a new frame
is treated as a multi-packet continuation instead of “no contacts.”
### Step 1.4: DETECT HIDDEN BUG FIXES
Record: **Not a hidden fix.** Subject and body describe a real input-
correctness bug and the exact `num_expected` mechanism.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: INVENTORY THE CHANGES
Record:
- **File:** `drivers/hid/hid-multitouch.c` — one hunk in
`mt_touch_report()` (~8 insertions / ~11 deletions, net −3)
- **Scope:** single-file surgical logic change in the ContactCount
handling block
### Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Current code in this tree (`drivers/hid/hid-multitouch.c`):
```1254:1269:drivers/hid/hid-multitouch.c
if (contact_count >= 0) {
/*
- For Win8 PTPs the first packet (td->num_received == 0) may
- have a contactcount of 0 if there only is a button event.
- ...
*/
if ((app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
app->num_received == 0 &&
app->prev_scantime != scantime)
app->num_expected = contact_count;
/* A non 0 contact count always indicates a first packet
*/
else if (contact_count)
app->num_expected = contact_count;
}
```
Record:
- **Before:** `contact_count > 0` → set `num_expected`. `contact_count
== 0` on a new first packet → set `num_expected = 0` **only** if
`MT_QUIRK_WIN8_PTP_BUTTONS`. Otherwise leave the previous
`num_expected`. Continuation packets with count 0 are left unchanged.
- **After:** `contact_count > 0` → set `num_expected`. Else if
`num_received == 0` and scantime changed → `num_expected = 0` for
**all** devices. Continuation packets still skipped (`num_received >
0` or same scantime).
- **Path:** HID report processing for every hid-multitouch device that
reports ContactCount; not an error/init-only path.
### Step 2.3: IDENTIFY THE BUG MECHANISM
Record: **[Logic / correctness] + [hardware firmware workaround]**
When ContactCount is 0 on a new frame, `num_expected` is not reset, so
`mt_sync_frame()` / `input_mt_sync_frame()` never run and
`INPUT_MT_DROP_UNUSED` cannot release slots.
This tree already has `MT_QUIRK_CONTACT_CNT_ACCURATE` on Yoga Book 9
(`4dfad42f0610f`). With a stale `num_expected` of N, a 0-count frame can
still process N ghost slots (`ALWAYS_VALID` skips tip-state validity),
then sync those ghosts as live contacts. Resetting `num_expected` to 0
makes the accurate-count guard skip every slot (`0 >= 0`) and then drop
unused slots.
### Step 2.4: ASSESS THE FIX QUALITY
Record:
- **Quality:** Minimal rewrite of one conditional. Continuation packets
still guarded. Win8 PTP button-only frames (`contact_count == 0`,
first packet, scantime changed) keep working, without requiring the
quirk.
- **Regression risk:** Low–medium: the `WIN8_PTP_BUTTONS` gate is
removed, so any hid-multitouch device that reports ContactCount and a
new-frame scantime can now treat a 0-count first packet as “all up.”
HID maintainer and hid-tools tests accepted that. Dropping the outer
`contact_count >= 0` wrapper means `contact_count == -1` (no
ContactCount field) can take the else-if; maintainer later called that
semantically misleading but harmless because `num_expected` stays 0.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: BLAME THE CHANGED LINES
Record:
- Multi-packet “zero contactcount” comment: `c2517f62dac608` (Benjamin
Tissoires, 2013)
- Win8 PTP 0-touch handling: **`af8dc4d094909` (“HID: multitouch:
Properly deal with Win8 PTP reports with 0 touches”, Hans de Goede,
2017-11-22)**
- Application-level `num_expected`: `f146d1c4d7eafd` / `01eaac7e57134`
(2018)
- `git merge-base --is-ancestor af8dc4d094909 HEAD` → **yes** (exit 0).
Buggy pattern is old and present here.
### Step 3.2: FOLLOW THE FIXES: TAG
Record: **No Fixes: tag.** Introduced behavior is the 2017 Win8 PTP
special case that never treated a generic 0-count sentinel as end-of-
frame.
### Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record (this tree, `drivers/hid/hid-multitouch.c`):
- `bdaabb4cf6603` — Yoga Book 9i quirks / `MT_CLS_YOGABOOK9I`
- `a7359de3c246b` — Yoga Book 9 14IAH10 misclassification; adds
`MT_QUIRK_NOT_SEEN_MEANS_UP` (`INPUT_MT_DROP_UNUSED`)
- `4dfad42f0610f` — Honor ContactCount ghost-contact suppression
(`MT_QUIRK_CONTACT_CNT_ACCURATE`)
- This candidate is the remaining Yoga Book 9 hid-multitouch fix (author
said so on-list)
Standalone: yes. v1 cover letter: independent of the ghost-contacts
patch; both sit on the misclassification commit. That misclassification
**is already in this tree.**
### Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Dave Carey is the Yoga Book 9 hid-multitouch contributor, not
the subsystem maintainer. Same-file commits here: `a7359de3c246b`,
`4dfad42f0610f`. Maintainer Benjamin Tissoires applied this one to
hid.git `for-7.3/upstream-fixes`.
### Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record:
- Needs existing `mt_touch_report()` ContactCount / scantime /
`num_expected` logic — present since 2017–2018.
- For Yoga Book 9 specifically, `MT_QUIRK_NOT_SEEN_MEANS_UP` (so
`INPUT_MT_DROP_UNUSED` is set) is already here via `a7359de3c246b`.
- `git merge-base --is-ancestor e8e60b6439eed HEAD` → **no** (not in
this tree).
- Applies standalone; `git apply --check` succeeded (hunk offset −70
lines).
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c e8e60b6439eed`:
https://patch.msgid.link/20260730124336.637339-1-carvsdriver@gmail.com
- **v1** (2026-05-15):
https://patch.msgid.link/20260515175253.873796-1-carvsdriver@gmail.com
— added an `else if (num_received == 0)` branch
- **v2** (2026-05-22): sent as `[PATCH 2/5]` in reply to v1; maintainers
did not treat it as a proper respin
- **v3** (2026-07-30): same code as v2; standalone subject. Applied
2026-08-25
- lore.kernel.org WebFetch returned 403; thread recovered via `b4 dig
-m` and `b4 mbox`
Key review:
- Benjamin on v1: hid-tools testsuite still happy; asked to flatten the
if/else and add `prev_scantime != scantime`
- Benjamin on v3: `contact_count == -1` path is misleading but harmless;
negative ContactCount would be clamped to 0 (improvement)
- Applied to hid.git `for-7.3/upstream-fixes` as `e8e60b6439ee`
- No NAK. AI review noted an unrelated pre-existing sticky-finger timer
UAF in `mt_remove()`, not introduced here
- No reviewer `Cc: stable`
### Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (`b4 dig -w`): To/Cc `linux-input@vger.kernel.org`, Jiri Kosina
(`jikos@kernel.org`), Benjamin Tissoires (`bentiss@kernel.org`). HID
maintainer reviewed and merged.
### Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla. Author described HID capture behavior and
tested on Yoga Book 9 14IAH10 (83KJ). Same author as the two Yoga Book 9
commits already in this tree.
### Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Intended as the last of three Yoga Book 9 hid-multitouch fixes.
The other two are already in this 6.12 tree. v2’s “2/5” was a mistaken
subject, not a hard series dependency. No later same-file follow-up on
origin/master besides an unrelated ASUS ROG Z13 quirk.
### Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: No stable@ discussion found. Commit has no Cc: stable. Not a
negative signal.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: IDENTIFY KEY FUNCTIONS
Record: **`mt_touch_report()`** only. Nearby: `mt_sync_frame()`,
`mt_process_slot()`, `mt_touch_input_configured()`.
### Step 5.2: TRACE CALLERS
Record: Only caller is `mt_report()` when `rdata->is_mt_collection`.
That is the HID `.report` callback for incoming device reports.
Interrupt/HID-completion context, not a syscall. Triggered by touching
the panel. `CONFIG_HID_MULTITOUCH` (`drivers/hid/Kconfig`).
### Step 5.3: TRACE CALLEES
Record: Reads `app->raw_cc` / `app->scantime`; walks slots via
`mt_process_slot()`; then `if (num_received >= num_expected)
mt_sync_frame()` → `input_mt_sync_frame()` + `input_sync()`. Yoga Book 9
sets `INPUT_MT_DROP_UNUSED` from `MT_QUIRK_NOT_SEEN_MEANS_UP` in
`mt_touch_input_configured()`.
### Step 5.4: FOLLOW THE CALL CHAIN
Record: USB/I2C HID report → `mt_report()` → `mt_touch_report()`.
Userspace-visible via evdev. Unprivileged user touching the screen can
trigger it.
### Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Same 0-count first-packet case already existed for
`MT_QUIRK_WIN8_PTP_BUTTONS` (`af8dc4d094909`). This generalizes that
handling. No duplicate fix already in this tree (`git log --grep` for
“stale MT” / “contact count drops” on the file: empty).
semcode MCP: not available; used grep/read.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
### Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record:
- `git describe HEAD` → **`p-6.12-3-gc504cf0baa3d8`**
- `make kernelversion` → **6.12.111**
- Branch: **pending-6.12**
- Buggy block is at `drivers/hid/hid-multitouch.c:1254-1268`
- Yoga Book 9 class with `NOT_SEEN_MEANS_UP | ALWAYS_VALID |
CONTACT_CNT_ACCURATE` is at lines 411–421
- Introduced in generic form in **v4.15-era (2017)**; this device class
is already backported here
### Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: **`git apply --check` succeeded** (hunk at line 1251, offset
−70). Surrounding `mt_touch_report()` matches mainline. **Clean apply /
trivial offset.**
### Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: Misclassification + ContactCount-accurate quirks are here. They
do **not** reset `num_expected` on a 0-count sentinel. No equivalent of
`e8e60b6439eed` is in this tree.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
### Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: **HID multitouch input driver** (`drivers/hid/hid-
multitouch.c`). **IMPORTANT** (laptop touchscreens/touchpads), not core
mm/fs. Affects all hid-multitouch devices for the ContactCount=0 path;
the reported user is Yoga Book 9, already enabled here.
### Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Active (device IDs, quirks, Yoga Book 9, OOB fixes). This is a
late correctness fix on long-standing frame-sync logic, not a refactor
of new code.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: DETERMINE WHO IS AFFECTED
Record: **Driver-specific / hardware-specific** for the reported failure
(Yoga Book 9 14IAH10, USB 17EF:6161). The code path is generic hid-
multitouch. Users of this 6.12 tree already have the rest of that
device’s support, so they can hit the leftover stuck-touch bug.
### Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Lift all fingers; firmware sends ContactCount=0 instead of
omitting the frame. Common on this device (author: “immediately
following the last finger lift”). Unprivileged physical touch. Timing:
every lift, not a rare race.
UNVERIFIED: firmware HID descriptor was not dumped here to prove
`HID_DG_SCANTIME` exists. v3 includes the scantime-change guard and
carries `Tested-by` on this hardware, so scantime almost certainly
changes; the Yoga Book 9 report-descriptor fixup does not strip usage
0x56 (`HID_DG_SCANTIME`).
### Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: **Stuck/stale multitouch slots; missed finger-up; userspace
gesture state corruption.** Not a kernel oops. **HIGH** for that
hardware (touch becomes wrong after lift). Fits stable-rules “hardware
quirk” / “oh, that's not good.”
### Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- **Benefit:** Completes already-backported Yoga Book 9 support; stops
stuck fingers and ghost slots on 0-count frames. Also helps any
similar sentinel-frame firmware.
- **Risk:** Low. ~19-line logic change, continuation path preserved,
hid-tools passed, maintainer reviewed the `-1` ContactCount case.
- **Ratio:** Benefit outweighs risk on this tree.
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: COMPILE THE EVIDENCE
**FOR backporting:**
- Real user-visible bug on shipping hardware (Lenovo Yoga Book 9
14IAH10)
- This 6.12 tree already has the two prior Yoga Book 9 hid-multitouch
fixes; without this, 0-count frames still leave slots active and can
even feed `CONTACT_CNT_ACCURATE` with a stale expected count
- Small, obviously targeted change; applies cleanly
- Tested by the author; HID maintainer reviewed (v1 testsuite + v3
semantic check) and merged
- Matches stable rules’ hardware-quirk / input-correctness category
- Continuation / multi-packet path explicitly preserved
**AGAINST backporting:**
- Not a crash, UAF, or security issue
- Widens 0-count handling beyond `MT_QUIRK_WIN8_PTP_BUTTONS`
- No Fixes:/Cc: stable (not a negative by itself)
- Niche dual-screen laptop as the reporter
**UNRESOLVED:**
- No independent HID dump confirming scantime on this firmware
(mitigated by Tested-by on v3)
- No distribution-kernel bugzilla
### Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — maintainer + hid-tools +
author Tested-by
2. Fixes a real bug that affects users? **PASS** — missed finger-up /
stuck slots on a supported laptop
3. Important issue? **PASS** — hardware input correctness / firmware
quirk, not theoretical
4. Small and contained? **PASS** — one function, ~19 lines
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — `git apply --check` clean;
prerequisites present
### Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: Not a device-ID/DT/build/docs exception. Closest: **hardware
firmware workaround** in an existing driver, which stable explicitly
allows.
### Step 9.4: MAKE YOUR DECISION
This 6.12 tree already enables the Yoga Book 9 touchscreen and the
ContactCount-accurate / DROP_UNUSED quirks. The remaining bug is that a
firmware 0-count sentinel never completes the frame, so slots are not
released. The fix is small, reviewed, tested, and applies here. Backport
it.
---
### What the commit solves for stable users
On kernels that already have Yoga Book 9 hid-multitouch support (this
tree does), lifting fingers can leave MT slots active because
ContactCount=0 does not reset `num_expected`. Userspace then misses the
up events. The patch forces a frame sync on a new 0-count packet so
`INPUT_MT_DROP_UNUSED` runs.
### Stable rules / risk vs benefit
Meets the written rules: real bug, small, no new API, applies cleanly.
Risk is a slightly broader 0-count interpretation; that was reviewed and
is the same condition Win8 PTP already used for button-only frames.
### Concerns
No crash/CVE; generic path rather than a Yoga-Book-only quirk table
entry. Still appropriate because the buggy code and the device class are
both in this checkout.
---
Verification:
- [Phase 1] Parsed tags: Tested-by Dave Carey; SOB Dave Carey + Benjamin
Tissoires; no Fixes/Reported-by/Cc: stable/Link
- [Phase 2] Diff: one hunk in `mt_touch_report()`; 0-count new frames
set `num_expected=0`; Win8 PTP quirk gate removed
- [Phase 2] Local code at `drivers/hid/hid-multitouch.c:1254-1268`
matches pre-patch logic
- [Phase 2] Yoga Book 9 class at 411–421 has `NOT_SEEN_MEANS_UP |
ALWAYS_VALID | CONTACT_CNT_ACCURATE`
- [Phase 3] `git describe HEAD` = p-6.12-3-gc504cf0baa3d8; `make
kernelversion` = 6.12.111
- [Phase 3] blame: Win8 0-touch logic from `af8dc4d094909` (2017);
ancestor of HEAD
- [Phase 3] `git merge-base --is-ancestor e8e60b6439eed HEAD` = not
present
- [Phase 3] Related commits in this tree: `a7359de3c246b`,
`4dfad42f0610f`, `bdaabb4cf6603`
- [Phase 3] Author’s other hid-multitouch commits: those two Yoga Book 9
fixes
- [Phase 4] `b4 dig -c e8e60b6439eed`: v3 at
patch.msgid.link/20260730124336.637339-1-carvsdriver@gmail.com
- [Phase 4] `b4 dig -a`: v1 2026-05-15, v3 2026-07-30 (v2 mistagged 2/5)
- [Phase 4] `b4 dig -w`: linux-input, jikos, bentiss
- [Phase 4] mbox: Benjamin hid-tools OK on v1; requested scantime guard;
v3 applied for-7.3/upstream-fixes; -1 contact_count called harmless
- [Phase 4] lore WebFetch 403; used b4 mbox instead
- [Phase 5] `mt_touch_report` only called from `mt_report()` on MT
collections
- [Phase 5] `INPUT_MT_DROP_UNUSED` set from `MT_QUIRK_NOT_SEEN_MEANS_UP`
in `mt_touch_input_configured()`
- [Phase 6] `git apply --check` of `e8e60b6439eed` succeeded at offset
−70
- [Phase 6] no local equivalent fix (`git log --grep` on the file empty
for this bug)
- [Phase 7] CONFIG_HID_MULTITOUCH in `drivers/hid/Kconfig`
- [Phase 8] Failure mode: stale MT slots / missed finger-up / gesture
corruption, severity HIGH for that hardware
- UNVERIFIED: no firmware HID dump confirming scantime on 17EF:6161
(Tested-by on v3 is the evidence)
- UNVERIFIED: no stable@ thread (search not useful; lore fetch blocked)
**YES**
drivers/hid/hid-multitouch.c | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 2461d84eb0e98..8dd69c6e7edf8 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -1332,21 +1332,18 @@ static void mt_touch_report(struct hid_device *hid,
* Includes multi-packet support where subsequent
* packets are sent with zero contactcount.
*/
- if (contact_count >= 0) {
+ if (contact_count > 0)
+ app->num_expected = contact_count;
+ else if (app->num_received == 0 && app->prev_scantime != scantime) {
/*
+ * New multi-report frame:
+ *
* For Win8 PTPs the first packet (td->num_received == 0) may
* have a contactcount of 0 if there only is a button event.
- * We double check that this is not a continuation packet
- * of a possible multi-packet frame be checking that the
- * timestamp has changed.
+ *
+ * Some other devices use a sentinel frame with 0 to release all contacts
*/
- if ((app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
- app->num_received == 0 &&
- app->prev_scantime != scantime)
- app->num_expected = contact_count;
- /* A non 0 contact count always indicates a first packet */
- else if (contact_count)
- app->num_expected = contact_count;
+ app->num_expected = 0;
}
app->prev_scantime = scantime;
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH AUTOSEL 6.18] HID: elecom: Add support for ELECOM M-XT4DRBK (018E)
[not found] <20261019135441.1420968-1-sashal@kernel.org>
` (7 preceding siblings ...)
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18-5.10] HID: multitouch: Fix stale MT slots when contact count drops to zero Sasha Levin
@ 2026-10-19 13:48 ` Sasha Levin
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18] HID: i2c-hid: add reset quirk for Lenovo Yoga Slim 7x Gen 11 keyboard Sasha Levin
` (7 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:48 UTC (permalink / raw)
To: patches, stable
Cc: Berke Durak, Jiri Kosina, Sasha Levin, jikos, bentiss,
linux-input, linux-kernel
From: Berke Durak <berke.durak@gmail.com>
[ Upstream commit f3c2b266b8fd7cf816d36168d19f67e716f2c080 ]
The 2025 revision of the left-handed EX-G wireless trackball
(M-XT4DRBK-G) reports USB ID 056e:018e instead of 056e:00fd. Its report
descriptor declares an 8-bit button field (Report Count 8) but only five
usages (Usage Maximum 5), so the sixth (Fn) button ends up as a
duplicate of button 5 and is unusable.
The report descriptor has the same layout as the M-XT3DRBK 018C
(button usage maximum at offset 16, button report count at 22, button
report size at 24, padding report size at 30), so reuse that fixup.
Rename the existing M_XT4DRBK define to M_XT4DRBK_00FD to match the
convention used for the other EX-G revisions.
Tested on a Raspberry Pi 5 with the same fixup in an
out-of-tree module on 6.12 (6.12.96+rpt-rpi-2712);
all six buttons are reported after the fix, and they
work (tested with xev as well).
Report descriptor as sent by the device, pre-fix (056e:018e,
215 bytes):
05 01 09 02 A1 01 09 01 A1 00 85 01 05 09 19 01
29 05 15 00 25 01 95 08 75 01 81 02 95 01 75 00
81 01 05 01 09 30 09 31 16 00 80 26 FF 7F 75 10
95 02 81 06 C0 A1 00 05 01 09 38 15 81 25 7F 75
08 95 01 81 06 C0 A1 00 05 0C 0A 38 02 95 01 75
08 15 81 25 7F 81 06 C0 C0 06 01 FF 09 00 A1 01
85 02 09 00 15 00 26 FF 00 75 08 95 07 81 02 C0
05 0C 09 01 A1 01 85 05 15 00 26 3C 02 19 00 2A
3C 02 75 10 95 01 81 00 C0 05 01 09 80 A1 01 85
03 19 81 29 83 15 00 25 01 95 03 75 01 81 02 95
01 75 05 81 01 C0 06 BC FF 09 88 A1 01 85 04 95
01 75 08 15 00 26 FF 00 19 00 2A FF 00 81 00 C0
06 02 FF 09 02 A1 01 85 06 09 02 15 00 26 FF 00
75 08 95 07 B1 02 C0
Assisted-by: LLM
Signed-off-by: Berke Durak <berke.durak@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **6.18.57** (`v6.18.57-155-gcdf239ca885b2`). The
question is whether this HID/elecom USB-ID + report-descriptor fixup
should be backported here. The driver, the existing
`mouse_button_fixup()` helper, and the sibling 018C fixup are all
already present in 6.18.57.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[HID / elecom] [Add support] [USB ID 056e:018e for the 2025
M-XT4DRBK-G trackball, plus the existing button report-descriptor
fixup]`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- No `Fixes:` tag (expected for this review)
- No `Reported-by:` / `Tested-by:` / `Reviewed-by:` / `Acked-by:`
- No `Link:`
- No `Cc: stable@vger.kernel.org` (expected; not a negative)
- `Assisted-by: LLM`
- `Signed-off-by: Berke Durak <berke.durak@gmail.com>` (author)
- `Signed-off-by: Jiri Kosina <jkosina@suse.com>` (HID maintainer)
- Ignore pipeline `Signed-off-by: Sasha Levin` and `[Upstream commit
...]`
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: 2025 left-handed EX-G wireless trackball (M-XT4DRBK-G) uses USB
ID `056e:018e` instead of the old `056e:00fd`.
- Descriptor claims an 8-bit button field (`Report Count 8`) but only
five usages (`Usage Maximum 5`), so the sixth (Fn) button is a
duplicate of button 5 and is unusable.
- Root cause: same broken descriptor layout as M-XT3DRBK 018C (offsets
16/22/24/30).
- Symptom: extra button does not work; mouse otherwise enumerates.
- Author tested on Raspberry Pi 5, 6.12 (`6.12.96+rpt-rpi-2712`), via an
out-of-tree module; all six buttons work (`xev`).
- Full 215-byte pre-fix descriptor is included.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a disguised cleanup. It is a device-ID addition plus an
existing HID report-descriptor quirk. The rename `M_XT4DRBK` →
`M_XT4DRBK_00FD` is local naming only.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- `drivers/hid/hid-ids.h`: +1 ID (`0x018e`), rename existing `0x00fd`
define
- `drivers/hid/hid-elecom.c`: +1 case in `elecom_report_fixup()`, +1
`elecom_devices[]` entry, rename 00FD references
- `drivers/hid/hid-quirks.c`: +1 `hid_have_special_driver[]` entry,
rename 00FD
- Scope: 8 insertions, 4 deletions across 3 files. Surgical, existing
driver only.
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Before: `056e:018e` is not in hid-elecom, so hid-generic binds and the
stock descriptor is used (Usage Maximum 5 / Count 8). Old `056e:00fd`
still uses the 6-button fixup via `USB_DEVICE_ID_ELECOM_M_XT4DRBK`.
- After: `018e` is claimed by hid-elecom and runs
`mouse_button_fixup(..., 22, 30, 24, 16, 6)` (same as 018C). Old 00FD
device still hits the same 6-button fixup through the renamed define.
`hid_have_special_driver` keeps hid-generic from binding 018E.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: `[Hardware workaround / device ID + HID descriptor quirk]`
- Broken HID report descriptor: Usage Maximum 5 vs Report Count 8.
- Fix reuses the proven 018C path: set count and usage max to 6, padding
to 2.
Verified against the included descriptor (first 32 bytes):
```
offset 16: 29 05 Usage Maximum (5)
offset 22: 95 08 Report Count (8)
offset 24: 75 01 Report Size (1)
offset 30: 75 00 padding Report Size (0)
```
Those match `mouse_button_fixup(hdev, rdesc, *rsize, 22, 30, 24, 16,
6)`. The helper then writes count=6, usage max=6, padding=2. The 018C
commit in this tree used the identical dump.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: new ID, existing helper, offsets match the dump.
- Minimal: no new APIs, no new helper, no behavior change for 00FD.
- Rename is kernel-internal (`hid-ids.h`); grep shows no leftover
`USB_DEVICE_ID_ELECOM_M_XT4DRBK` users.
- Regression risk is low: `mouse_button_fixup()` bails out unless the
expected HID items are at those offsets, so a mismatched 018E
descriptor would be left unchanged.
- `hid-quirks.c` update is required so hid-generic does not steal the
device (`HID_QUIRK_HAVE_SPECIAL_DRIVER`).
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Original M-XT4DRBK 00FD support: `fbb77e88f08ce` (2018, Tomasz
Kramkowski), already in 6.18.57.
- Parameterized `mouse_button_fixup()`: `68d09380a6278` (2020), already
in 6.18.57.
- 018C sibling layout this patch reuses: `da1880c7b6b83` (Arnoud
Willemsen), already in 6.18.57 (`git merge-base --is-ancestor`
returned 0).
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Not a regression in previously working 018E
support; 018E was never in this tree. The bug is the device’s
descriptor, same class as 00FD/018C.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record: Recent `hid-elecom.c` history is the same pattern of “new USB ID
+ existing fixup”:
- `cdcbb8e8d10f6` M-XT3URBK 018F (in 6.18.57)
- `da1880c7b6b83` M-XT3DRBK 018C (in 6.18.57)
- `a36e053b16804` HUGE Plus M-HT1MRBK (in 6.18.57)
Standalone; not patch X/Y.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Berke Durak has only this hid-elecom commit here. Jiri Kosina
(HID maintainer) signed off and applied it.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Needs `mouse_button_fixup()` and the 018C case. Both exist at
v6.18.57. No new functions. Can apply standalone. `patch --dry-run` of
this diff onto the v6.18.57 copies of the three files succeeded.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c a6dbbf8a1601a`:
https://patch.msgid.link/20260907184719.25042-1-berke.durak@gmail.com
- `b4 dig -a`: single revision (v1 only), 2026-09-07
- lore.kernel.org fetches returned 403; discussion confirmed via patchew
and openwall mirrors
- Jiri Kosina: “Applied, thanks.” No NAK, no requested respin, no
stable-risk comments
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc Jiri Kosina, Benjamin Tissoires, linux-
input, linux-kernel. HID maintainer applied it.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No bugzilla/syzbot link. The author is the reporter and tester,
with a full descriptor dump and xev confirmation. Same failure mode as
018C, which is already in this tree.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone v1. Closely related 018C/018F/HUGE Plus ID+fixup
patches are already in 6.18.57.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: UNVERIFIED. `lore.kernel.org/stable/?q=M-XT4DRBK` returned 403.
No evidence of a prior rejection. Does not change the technical verdict.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `elecom_report_fixup()` (switch cases / id table);
`mouse_button_fixup()` called but not modified; ID tables in `hid-
elecom.c` and `hid_have_special_driver[]`.
**Step 5.2: TRACE CALLERS**
Record:
- `elecom_report_fixup` ← `elecom_driver.report_fixup` ← `hid-core.c`
`hid_open_report()` (`device->driver->report_fixup(...)` at line 1305)
- `hid_have_special_driver` match ← `hid_gets_squirk()` sets
`HID_QUIRK_HAVE_SPECIAL_DRIVER` ← `hid_generic_match()` returns false
so hid-generic does not bind
**Step 5.3: TRACE CALLEES**
Record: `mouse_button_fixup()` only mutates three descriptor bytes after
pattern checks; `hid_info()` log. No allocation, locking, or I/O.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Plug USB receiver → usbhid → hid parse → `report_fixup` → input
events. Userspace-reachable on plug. Unprivileged users then use the
extra button via evdev. Not a security bug; it is a functional hardware
bug.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same pattern already used for 018C, 018F, DT2, HUGE, etc. in
this file. This is the left-handed 2025 wireless counterpart of 018C.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes. v6.18.57 has hid-elecom, `mouse_button_fixup()`, and 018C’s
layout, but **not** ID `0x018e`. Without this patch, 018E is a generic
HID mouse with a broken sixth button. The 00FD model is already quirked.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: Clean apply onto v6.18.57 (`patch --dry-run` rc 0). Parent vs
v6.18.57 differs only by an unrelated ITE keyboard ID later in `hid-
ids.h`.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No 018E fix in v6.18.57. 018C/018F/HUGE Plus ID+fixup patches
**are** already in 6.18.57, which is the same stable-accepted class of
change.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `[drivers/hid/hid-elecom.c] [PERIPHERAL / driver-specific]`,
gated by `CONFIG_HID_ELECOM`. Important for owners of this trackball;
not core MM/VFS.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature driver (2010–); recent work is additional ELECOM IDs and
descriptor fixups, several of which already landed in 6.18.y.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver-specific / config-specific: users of ELECOM M-XT4DRBK-G
2025 (`056e:018e`) with `CONFIG_HID_ELECOM`. 00FD users are unchanged.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Every plug-in of that dongle. Not a race. Unprivileged users see
a missing/duplicated Fn button.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: `[Broken extra mouse button on specific hardware] [MEDIUM
functional / hardware-quirk]`. Not a crash, UAF, or corruption issue.
This is the documented stable exception for USB IDs and hardware quirks.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- Benefit: 2025 left-handed EX-G trackball gets a working sixth button
on 6.18.y, matching what 018C already got.
- Risk: very low (8/4 line change, existing helper, pattern-gated,
maintainer-applied, tested).
- Ratio: high benefit for affected hardware, negligible regression risk.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- USB ID + existing HID quirk on an existing driver (stable exceptions 1
and 2)
- Real user-visible bug: sixth button unusable; author tested the fix
- Descriptor offsets verified against the dump and against 018C already
in this tree
- Small, obviously correct, no new APIs
- HID maintainer applied v1 with no objections
- Same class of patch (018C/018F/HUGE Plus) already in 6.18.57
- Applies cleanly to this tree
AGAINST:
- Not a crash/security/corruption fix
- Affects one consumer trackball model
- Author is not a regular HID contributor; patch notes `Assisted-by:
LLM` (mitigated by maintainer apply + dump + test)
UNRESOLVED:
- Could not fetch lore.kernel.org (403) or search stable@ archives
directly; discussion recovered from b4/patchew/openwall
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — offsets match; author
tested; maintainer applied
2. Fixes a real bug that affects users? **PASS** — Fn button unusable
without the quirk
3. Important issue? **PASS** under the hardware-quirk / new-ID exception
(severity MEDIUM, not CRITICAL)
4. Small and contained? **PASS** — 8 insertions / 4 deletions, 3 files
5. No new features or APIs? **PASS** — ID + existing fixup only
6. Can apply to the local tree? **PASS** — clean apply to v6.18.57;
prerequisites present
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **Device ID addition to existing driver** and **hardware
quirk/workaround**. Both qualify for stable.
**Step 9.4: MAKE YOUR DECISION**
YES. This is the same HID-elecom USB-ID + report-descriptor quirk 6.18.y
has already taken for 018C. It does not add a driver or API; it makes a
current ELECOM trackball’s sixth button work.
What the commit solves: the 2025 M-XT4DRBK-G (`056e:018e`) ships a
descriptor that only declares five button usages, so Linux reports the
Fn button as a duplicate of button 5. The fix binds that ID to hid-
elecom and reuses the 018C `mouse_button_fixup()`.
Risk vs benefit: benefit is a working extra button on real hardware;
risk is a few table entries and a pattern-checked 3-byte descriptor
edit. 00FD behavior is unchanged.
No extra prerequisites; 018C’s helper and case are already in this tree.
Verification:
- [Phase 1] Parsed tags: author + Jiri Kosina SOB; no Fixes/Cc
stable/Reported-by; LLM-assisted
- [Phase 1] Body: 056e:018e, Usage Maximum 5 vs Count 8, sixth button
unusable; tested on Pi 5 / 6.12
- [Phase 2] Diff: +8/-4 in hid-elecom.c, hid-ids.h, hid-quirks.c; rename
00FD define; add 018E to 018C fixup
- [Phase 2] Descriptor offsets 16/22/24/30 verified against the dump
- [Phase 3] `git describe HEAD` / Makefile: local tree is 6.18.57
- [Phase 3] `git merge-base --is-ancestor a6dbbf8a1601a v6.18.57` → not
in v6.18.57 (exit 1)
- [Phase 3] 00FD support `fbb77e88f08ce` and 018C `da1880c7b6b83` are
ancestors of v6.18.57
- [Phase 3] v6.18.57 still uses `USB_DEVICE_ID_ELECOM_M_XT4DRBK` only;
no 018E
- [Phase 3] Author has no other hid-elecom commits here
- [Phase 4] `b4 dig -c`: msgid
20260907184719.25042-1-berke.durak@gmail.com; v1 only
- [Phase 4] `b4 dig -w`: Kosina + Tissoires + linux-input; Kosina
applied
- [Phase 4] lore.kernel.org 403; patchew/openwall used instead
- [Phase 4] UNVERIFIED: stable@ archive search (403)
- [Phase 5] Callers: hid-core `report_fixup` on probe; hid-generic skips
via `HID_QUIRK_HAVE_SPECIAL_DRIVER`
- [Phase 6] `patch --dry-run` onto v6.18.57 files: success
- [Phase 6] Related 018C/018F/HUGE Plus ID patches already in 6.18.57
- [Phase 8] Failure mode: extra button unusable, not a kernel crash
- UNVERIFIED: original lore HTML (403); does not affect the decision
**YES**
drivers/hid/hid-elecom.c | 6 ++++--
drivers/hid/hid-ids.h | 3 ++-
drivers/hid/hid-quirks.c | 3 ++-
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c
index 37d88ce57f671..d21ead40bb076 100644
--- a/drivers/hid/hid-elecom.c
+++ b/drivers/hid/hid-elecom.c
@@ -79,7 +79,7 @@ static const __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
case USB_DEVICE_ID_ELECOM_M_XT3URBK_00FB:
case USB_DEVICE_ID_ELECOM_M_XT3URBK_018F:
case USB_DEVICE_ID_ELECOM_M_XT3DRBK_00FC:
- case USB_DEVICE_ID_ELECOM_M_XT4DRBK:
+ case USB_DEVICE_ID_ELECOM_M_XT4DRBK_00FD:
/*
* Report descriptor format:
* 12: button bit count
@@ -104,6 +104,7 @@ static const __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 8);
break;
case USB_DEVICE_ID_ELECOM_M_XT3DRBK_018C:
+ case USB_DEVICE_ID_ELECOM_M_XT4DRBK_018E:
/*
* Report descriptor format:
* 22: button bit count
@@ -148,7 +149,8 @@ static const struct hid_device_id elecom_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK_018F) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK_00FC) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK_018C) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK_00FD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK_018E) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT2DRBK) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index a10b4ae0e3d8e..ca5c62f29aebe 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -466,7 +466,8 @@
#define USB_DEVICE_ID_ELECOM_M_XT3URBK_018F 0x018f
#define USB_DEVICE_ID_ELECOM_M_XT3DRBK_00FC 0x00fc
#define USB_DEVICE_ID_ELECOM_M_XT3DRBK_018C 0x018c
-#define USB_DEVICE_ID_ELECOM_M_XT4DRBK 0x00fd
+#define USB_DEVICE_ID_ELECOM_M_XT4DRBK_00FD 0x00fd
+#define USB_DEVICE_ID_ELECOM_M_XT4DRBK_018E 0x018e
#define USB_DEVICE_ID_ELECOM_M_DT1URBK 0x00fe
#define USB_DEVICE_ID_ELECOM_M_DT1DRBK 0x00ff
#define USB_DEVICE_ID_ELECOM_M_DT2DRBK 0x018d
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 8d2ac32c5ac12..debd00ed9062a 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -431,7 +431,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK_018F) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK_00FC) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK_018C) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK_00FD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK_018E) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT2DRBK) },
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH AUTOSEL 6.18] HID: i2c-hid: add reset quirk for Lenovo Yoga Slim 7x Gen 11 keyboard
[not found] <20261019135441.1420968-1-sashal@kernel.org>
` (8 preceding siblings ...)
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18] HID: elecom: Add support for ELECOM M-XT4DRBK (018E) Sasha Levin
@ 2026-10-19 13:48 ` Sasha Levin
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18-5.10] HID: intel-ish-hid: ignore post-init ENUM_DEVICES from firmware Sasha Levin
` (6 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:48 UTC (permalink / raw)
To: patches, stable
Cc: Oleg Keri, Jiri Kosina, Sasha Levin, jikos, bentiss, linux-input,
linux-kernel
From: Oleg Keri <okerixx@gmail.com>
[ Upstream commit 39e8e085710a2d36d9ceade11739fb7b87f5aeb0 ]
The ITE controller behind the keyboard of the Lenovo Yoga Slim 7x Gen 11
(048d:83db) carries out a reset but never raises the interrupt that
acknowledges it. i2c_hid_finish_hwreset() therefore waits out its full
one second timeout and logs "device did not ack reset within 1000 ms" on
every probe and every resume, before the keyboard comes up regardless.
Set I2C_HID_QUIRK_NO_IRQ_AFTER_RESET for it, as is already done for
several other ITE parts, so the reset is followed by a fixed 100 ms sleep
instead.
Signed-off-by: Oleg Keri <okerixx@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have enough to judge this as a hardware quirk for the existing i2c-hid
driver: the 1-second reset-ack wait is in this 6.18 tree, and the new ID
only matches 048d:83db.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[HID: i2c-hid] [add] [reset quirk for Lenovo Yoga Slim 7x Gen
11 keyboard]`
Subsystem prefix is `HID: i2c-hid`. Action verb is **add** (hardware
quirk table entry). Claimed intent: stop waiting a full second for a
reset IRQ this ITE keyboard never raises.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Fixes:` — absent (expected for autosel review; not a negative signal)
- `Reported-by:` — absent
- `Tested-by:` — absent
- `Reviewed-by:` — absent
- `Acked-by:` — absent
- `Link:` — absent
- `Cc: stable@vger.kernel.org` — absent (expected)
- `Signed-off-by: Oleg Keri <okerixx@gmail.com>` (author)
- `Signed-off-by: Jiri Kosina <jkosina@suse.com>` (HID maintainer; this
is the real maintainer SOB)
- `Signed-off-by: Sasha Levin` — ignored per instructions (pipeline)
Notable: HID maintainer applied it. No syzbot/KASAN tags. Author is a
hardware user, not a regular HID contributor (`git log --author='Oleg
Keri'` on `drivers/hid/` shows only this commit).
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** ITE controller `048d:83db` on Lenovo Yoga Slim 7x Gen 11
performs reset but never raises the ack IRQ.
- **Symptom:** `i2c_hid_finish_hwreset()` waits the full 1000 ms and
logs `device did not ack reset within 1000 ms` on probe (author also
says resume). Keyboard still comes up afterward.
- **Root cause:** Device does not implement the i2c-hid reset-complete
interrupt.
- **Fix:** `I2C_HID_QUIRK_NO_IRQ_AFTER_RESET` → 100 ms `msleep` instead
of 1 s `wait_event_timeout`.
- **Version info:** None in the message. Cover letter (mailing list)
identifies the machine as a Snapdragon X2 Elite (glymur) laptop.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not a hidden fix. It is an explicit hardware quirk. Same class
as USB/PCI/HID quirk table additions, which stable explicitly accepts.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- `drivers/hid/hid-ids.h`: +1
(`I2C_DEVICE_ID_ITE_LENOVO_YOGA_SLIM_7X_G11_KEYBOARD 0x83db`)
- `drivers/hid/i2c-hid/i2c-hid-core.c`: +2 (quirk table entry using
`USB_VENDOR_ID_ITE` + that ID + `I2C_HID_QUIRK_NO_IRQ_AFTER_RESET`)
- Total: **+3 / -0**. Functions: none modified; static
`i2c_hid_quirks[]` table only.
- Scope: **single-purpose, two-file surgical quirk**.
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** `i2c_hid_lookup_quirk(0x048d, 0x83db)` returns 0.
`i2c_hid_finish_hwreset()` takes the `wait_event_timeout(..., 1000
ms)` branch, warns, then continues.
- **After:** lookup returns `I2C_HID_QUIRK_NO_IRQ_AFTER_RESET`. Same
function `msleep(100)` and clears `I2C_HID_RESET_PENDING` without
waiting for IRQ.
- Path: HID probe (`hid_add_device` → `ll_driver->parse` →
`i2c_hid_parse` → start/finish hwreset). Initialization path, not a
new API.
Verified `i2c_hid_finish_hwreset()`:
```508:516:drivers/hid/i2c-hid/i2c-hid-core.c
if (ihid->quirks & I2C_HID_QUIRK_NO_IRQ_AFTER_RESET) {
msleep(100);
clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
} else if (!wait_event_timeout(ihid->wait,
!test_bit(I2C_HID_RESET_PENDING,
&ihid->flags),
msecs_to_jiffies(1000))) {
dev_warn(&ihid->client->dev, "device did not ack reset
within 1000 ms\n");
clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
}
```
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: **(h) Hardware workaround.** Device never signals reset-
complete. Generic 1 s wait is correct for spec-compliant parts and wrong
for this ITE keyboard. Quirk matches the existing Voyo/Hantick/Raydium
pattern.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: identical to existing table rows;
`USB_VENDOR_ID_ITE` is `0x048d`, matching the commit text.
- Minimal: three lines, no behavioral change for any other VID/PID.
- Regression risk: very low. Only `048d:83db` is affected. If a future
device reused that ID and *did* ack reset, it would sleep 100 ms
instead of waiting for IRQ — that ID is this laptop’s keyboard.
- No public API / data-structure change.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Quirk flag and table date to 2017 (`402946a8ef71e`, Hantick).
- ITE Voyo entry: `fc6a31b007393` (2021-02-05), Hans de Goede.
- Timeout-as-warning (so probe still succeeds): `7bcf9ebb50f2a`
(2023-12-06). That commit even said more `NO_IRQ_AFTER_RESET` quirks
should become unnecessary; they still help because the 1 s wait
remains.
- G11 ID did not exist before this change (`git show
<parent>:drivers/hid/hid-ids.h` has Slim 7x `0x8987` only).
- Buggy *behavior* is the generic wait in `i2c_hid_finish_hwreset`,
present for years, including this 6.18 tree.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Not applicable. The “introduction” is hardware,
not a kernel regression.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- Related: `a45f15808fb75` “HID: lenovo: fixup Lenovo Yoga Slim 7x
Keyboard rdesc” (product `0x8987`, original Slim 7x, not Gen 11).
- Later in this checkout: `245d6017beff2` adds `BAD_INPUT_SIZE` for
another device; independent.
- This commit is **patch 1/2** of “HID: Lenovo Yoga Slim 7x Gen 11
keyboard fixes”. Patch 2 (`HID: lenovo: suppress phantom radio control
input`) uses the `#define` this patch adds. Cover letter: each patch
builds standalone if applied in order; this one does not need patch 2.
- Patch 2 is **not** in this tree (`git log --grep='suppress phantom
radio'` empty; `hid-lenovo.c` has no G11 ID).
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Oleg Keri has no other HID commits here. Jiri Kosina (HID
maintainer) signed off and applied it. Recipients included Benjamin
Tissoires and Lenovo’s Mark Pearson.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: No prerequisites. `I2C_HID_QUIRK_NO_IRQ_AFTER_RESET`,
`i2c_hid_lookup_quirk()`, `USB_VENDOR_ID_ITE`, and the quirks table all
exist in the parent (`7e1d29620273b`, `v6.18.57-15-g7e1d29620273b`).
Standalone apply.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c 2cb79eaedc9ed` matched lore:
https://patch.msgid.link/20260908111812.43837-2-okerixx@gmail.com
- `b4 dig -a`:
- v1 (2026-09-08): standalone i2c-hid patch
`20260908091926.5773-1-okerixx@gmail.com`
- v2 series (2026-09-08 / resend 2026-09-10): 0/2 + 1/2 + 2/2
- v2 change was **ordering only** (kbuild robot: patch 2 used an
undeclared ID). No functional change to this quirk.
- Jiri applied 1/2 from the standalone posting (“Applied, thank you.”).
Oleg later noted 1/2 was already applied, only 2/2 still needed.
- No NAK. No reviewer concern about the quirk itself. No `Cc: stable` in
the thread (absence expected).
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): Oleg Keri; Jiri Kosina; Benjamin Tissoires; Derek
J. Clark; Mark Pearson (Lenovo); `linux-input`; `linux-kernel`. Right
maintainers and Lenovo contact were on the original To/Cc. Maintainer
applied it.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No bugzilla/syzbot link. Evidence is the author’s machine
(`048d:83db`) and the exact `dev_warn` string, which matches
`i2c_hid_finish_hwreset()`. Cover letter: Snapdragon X2 Elite (glymur)
Yoga Slim 7x Gen 11.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Series of two. Patch 1 (this) is self-contained. Patch 2 is hid-
lenovo input mapping for a phantom `KEY_RFKILL` collection; it needs
this `#define` but this patch does not need patch 2. Evaluating only
this commit: standalone YES.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: Web search of lore stable for this subject returned no relevant
hits. No record of a prior rejection from stable. UNVERIFIED beyond
that: lore.kernel.org search URLs returned 403 via WebFetch.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: No function bodies changed. Data consumed by
`i2c_hid_lookup_quirk()`; effect in `i2c_hid_finish_hwreset()`.
**Step 5.2: TRACE CALLERS**
Record (git grep, no semcode MCP in this session):
- `i2c_hid_lookup_quirk`: `__i2c_hid_core_probe()` — sets `ihid->quirks`
from HID descriptor VID/PID **before** `hid_add_device()`.
- `i2c_hid_finish_hwreset`:
1. `i2c_hid_parse()` — `.parse` of `i2c_hid_ll_driver`, called from
`hid_add_device()` (`drivers/hid/hid-core.c:2998`). **Every
probe.**
2. `i2c_hid_core_resume()` — **only if**
`I2C_HID_QUIRK_RESET_ON_RESUME`. This device is **not** given that
quirk.
So the 1 s wait is verified on **probe**. “Every resume” is **not**
explained by `i2c_hid_core_resume()` for this ID unless the I2C HID
device is re-probed (possible on some Qualcomm/ACPI power paths). Author
may have observed re-probe; that part is not proven from this tree’s
resume function. Probe delay is enough.
**Step 5.3: TRACE CALLEES**
Record: Quirk path: `msleep(100)` + `clear_bit(I2C_HID_RESET_PENDING)`.
Default path: `wait_event_timeout` on `ihid->wait`, woken from
`i2c_hid_get_input()` when a zero-length reset-complete report arrives.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Boot/device enumeration: ACPI or OF I2C HID → `i2c_hid` probe →
fetch HID descriptor (`048d:83db`) → quirk lookup → `hid_add_device` →
`i2c_hid_parse` → hwreset. Not a syscall bug; it is the laptop keyboard
coming up. Userspace-visible: ~1 s before the keyboard is ready, plus a
warning.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same quirk already used for Hantick 5288, ITE Voyo Winpad A15,
Raydium 3118. ITE not sending reset IRQ is a known family issue. This is
not a one-off invention.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- Local tree: `v6.18.57-155-gcdf239ca885b2`, `Makefile` 6.18.57.
- `i2c_hid_finish_hwreset()` 1 s timeout + warning: **yes**.
- Quirk infrastructure: **yes**.
- G11 ID before this change: **no** (parent hid-ids.h).
- i2c-hid driver: **yes** (`CONFIG_I2C_HID`, ACPI and OF).
- Glymur platform bits exist in this tree (pinctrl, rpmhpd, sound). No
`yoga-slim7x` Gen 11 DT (only original `x1e80100-lenovo-yoga-
slim7x.dts`). These Windows-on-ARM laptops typically enumerate I2C HID
from **ACPI**, so the quirk does not depend on a Gen 11 DT.
Bug exists whenever this keyboard is present on 6.18.y.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply.** Parent quirks table has the Voyo row
immediately above the insertion point, same as the diff.
`USB_VENDOR_ID_ITE` and neighboring ITE IDs already exist.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: No other G11 reset fix. Slim 7x rdesc fix (`0x8987`) is a
different product. Hans’s 2023 warning change is here; it makes missing
ACK non-fatal but still waits 1 s. This quirk still does useful work.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `drivers/hid/i2c-hid` — laptop built-in keyboard over I2C-HID.
**IMPORTANT** (not core mm/VFS; not staging). Affects owners of this
Lenovo model, which is a real shipping machine.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: i2c-hid is mature (quirk table since 2016/2017) and still gets
device-specific quirks. Typical stable material.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Driver/hardware-specific** — only `048d:83db` (Yoga Slim 7x
Gen 11 ITE keyboard). Harmless to everyone else.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Every i2c-hid probe of that keyboard (boot; also any
unbind/rebind or platform re-probe). Not an unprivileged syscall
exploit. Timing-independent; 100% on this hardware.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Keyboard still works after the timeout (`7bcf9ebb50f2a` turned
missing ACK into a warning). User impact is **~1 second delay** plus a
warning on init. Severity **MEDIUM** as a hang/crash, but this is the
**hardware-quirk exception**, not a panic fix.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** Removes a 1 s keyboard delay and a false warning on a
current Lenovo ARM laptop that 6.18.y users can run.
- **Risk:** Very low (3 lines, VID/PID match, existing flag).
- **Ratio:** Strongly favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real hardware bug: ITE keyboard never acks reset IRQ.
- User-visible 1 s delay + warning on probe.
- Classic HID/i2c-hid quirk; same flag already used for other ITE parts.
- +3 lines, obviously correct, HID maintainer applied.
- Driver and quirk machinery exist in this 6.18.57 tree.
- Applies cleanly; no new API; no prerequisites.
- Explicit stable exception: hardware quirk / device ID for an existing
driver.
AGAINST:
- Not a crash, UAF, deadlock, or data-corruption bug.
- `7bcf9ebb50f2a` made missing ACK non-fatal and hoped to reduce new
quirks.
- “Every resume” is not the `RESET_ON_RESUME` path for this ID
(unverified as a code path; author observation only).
- Patch 2 of the series is separate (not required for this fix).
- No `Reported-by` besides the author (still a real device).
UNRESOLVED:
- Could not fetch lore.kernel.org HTML (403); used `b4 dig` +
patchew/openwall instead.
- Resume-on-this-ID not shown in `i2c_hid_core_resume()` without
`RESET_ON_RESUME`.
- No in-tree DT for Gen 11; ACPI I2C HID still makes the quirk relevant.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — copy of existing quirk row;
author has the laptop; maintainer applied.
2. Fixes a real bug that affects users? **PASS** — 1 s keyboard init
delay and warning on this model.
3. Important issue? **PASS** as hardware-quirk exception (not CRITICAL
panic; still the class stable takes).
4. Small and contained? **PASS** — 3 lines, two files.
5. No new features or APIs? **PASS** — table entry only.
6. Can apply to the local tree? **PASS** — parent already has the table,
flag, and ITE vendor ID.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **Hardware quirk / workaround** (and a device ID on an existing
driver). Automatic stable-qualifier under the stated exceptions.
**Step 9.4: MAKE YOUR DECISION**
This should be backported to this 6.18.y tree. The i2c-hid reset-wait
bug is here; the fix is a three-line quirk for one VID/PID; risk is
negligible.
What it solves for stable users: Yoga Slim 7x Gen 11 keyboard init no
longer burns a full second waiting for an IRQ the ITE controller never
sends.
Risk vs benefit: very low risk, real delay/warning removed. No
dependencies beyond code already in 6.18.57.
===============================================================
Verification:
===============================================================
- [Phase 1] Parsed tags: author Oleg Keri; maintainer Jiri Kosina SOB;
no Fixes/Cc stable/Reported-by (expected).
- [Phase 2] Diff: +1 hid-ids.h, +2 i2c-hid-core.c quirks table;
`USB_VENDOR_ID_ITE` is 0x048d; finish_hwreset quirk vs 1000 ms wait
verified in tree.
- [Phase 3] `git describe HEAD` / `make kernelversion`:
v6.18.57-155-gcdf239ca885b2 / 6.18.57.
- [Phase 3] Parent `7e1d29620273b` lacks G11 ID; has
Voyo/Hantick/Raydium `NO_IRQ_AFTER_RESET` rows.
- [Phase 3] Blame: flag from 402946a8ef71e (2017); ITE Voyo
fc6a31b007393 (2021); warning 7bcf9ebb50f2a (2023).
- [Phase 3] No Fixes tag. Author has no other hid commits here.
- [Phase 3] Series 1/2; patch 2 not in this tree; this patch builds
alone.
- [Phase 4] `b4 dig -c 2cb79eaedc9ed`: lore match
`20260908111812.43837-2-okerixx@gmail.com`.
- [Phase 4] `b4 dig -a`: v1 standalone then v2 series (ordering only).
- [Phase 4] `b4 dig -w`: Jiri Kosina, Benjamin Tissoires, Mark Pearson,
linux-input.
- [Phase 4] Patchew: Jiri “Applied, thank you”; kbuild robot only on
patch 2 without this #define.
- [Phase 4] lore.kernel.org WebFetch 403; stable-list search found no
prior discussion of this quirk.
- [Phase 5] Callers: lookup from `__i2c_hid_core_probe`; finish_hwreset
from `i2c_hid_parse` (probe) and resume only with RESET_ON_RESUME
(this ID does not set that).
- [Phase 5] hid_add_device → ll_driver->parse at hid-core.c:2998
verified.
- [Phase 6] Buggy 1 s wait present; G11 ID not in parent; glymur support
present; no Gen 11 DT; ACPI I2C HID still applies.
- [Phase 6] Parent table context matches diff; clean apply.
- [Phase 8] Failure mode: 1 s delay + warning, keyboard still works;
severity MEDIUM; quirk exception applies.
- UNVERIFIED: author’s “every resume” vs code (resume does not call
finish_hwreset without RESET_ON_RESUME). Did not drive the verdict;
probe path is verified.
**YES**
drivers/hid/hid-ids.h | 1 +
drivers/hid/i2c-hid/i2c-hid-core.c | 2 ++
2 files changed, 3 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 11f120a5d1b90..a10b4ae0e3d8e 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -737,6 +737,7 @@
#define I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720 0x837a
#define USB_DEVICE_ID_ITE_LENOVO_YOGA900 0x8396
#define I2C_DEVICE_ID_ITE_LENOVO_YOGA_SLIM_7X_KEYBOARD 0x8987
+#define I2C_DEVICE_ID_ITE_LENOVO_YOGA_SLIM_7X_G11_KEYBOARD 0x83db
#define USB_DEVICE_ID_ITE8595 0x8595
#define USB_DEVICE_ID_ITE_MEDION_E1239T 0xce50
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index e5a4c7deba502..62b3dd0390a7c 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -126,6 +126,8 @@ static const struct i2c_hid_quirks {
I2C_HID_QUIRK_NO_IRQ_AFTER_RESET | I2C_HID_QUIRK_BAD_INPUT_SIZE },
{ I2C_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_VOYO_WINPAD_A15,
I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
+ { USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_YOGA_SLIM_7X_G11_KEYBOARD,
+ I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
{ I2C_VENDOR_ID_RAYDIUM, I2C_PRODUCT_ID_RAYDIUM_3118,
I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
{ USB_VENDOR_ID_ALPS_JP, HID_ANY_ID,
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH AUTOSEL 6.18-5.10] HID: intel-ish-hid: ignore post-init ENUM_DEVICES from firmware
[not found] <20261019135441.1420968-1-sashal@kernel.org>
` (9 preceding siblings ...)
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18] HID: i2c-hid: add reset quirk for Lenovo Yoga Slim 7x Gen 11 keyboard Sasha Levin
@ 2026-10-19 13:48 ` Sasha Levin
2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] HID: roccat: fix locking in roccat_connect() and roccat_disconnect() Sasha Levin
` (5 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:48 UTC (permalink / raw)
To: patches, stable
Cc: Wahid Khan, Srinivas Pandruvada, Zhang Lixu, Jiri Kosina,
Sasha Levin, jikos, bentiss, linux-input, linux-kernel
From: Wahid Khan <wahidzk0091@gmail.com>
[ Upstream commit f3f3f6df05226dfa220c4e603310dae94595060a ]
Some ISH firmware versions (observed on Tiger Lake LP, 8086:a0fc,
GUID {33AECD58-B679-4E54-9BD9-A04D34F0C226}) periodically re-send an
unsolicited HOSTIF_DM_ENUM_DEVICES response roughly every 79 seconds.
The current guard collapses two distinct cases into one condition:
if (!(response_flag) || init_done) -> bad packet + ish_hw_reset
This incorrectly treats a valid post-init firmware announcement as a
corrupted packet, triggering an ISH soft-reset and a full ISHTP
re-initialisation cycle on each occurrence (~1100 times per day on
affected hardware).
Split the check: reject messages with no response flag as before, but
simply discard valid ENUM_DEVICES messages that arrive after init is
complete.
Signed-off-by: Wahid Khan <wahidzk0091@gmail.com>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Tested-by: Zhang Lixu <lixu.zhang@intel.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **5.15.221** (`pending-5.15`,
`p-5.15-2-g9a29d9b0f9507`). The buggy `HOSTIF_DM_ENUM_DEVICES` /
`init_done` reset guard is present here and matches the patch, so this
is a decision for this tree only.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
**Step 1.1: PARSE THE SUBJECT LINE**
Record: **[HID/intel-ish-hid] [ignore] discard post-init ENUM_DEVICES
from firmware instead of treating them as bad packets**
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- Fixes: **none** (expected for this review pipeline)
- Reported-by: **none**
- Tested-by: Zhang Lixu \<lixu.zhang@intel.com\> (Intel; independent of
the author)
- Acked-by: Srinivas Pandruvada \<srinivas.pandruvada@linux.intel.com\>
(ISH maintainer)
- Reviewed-by: **none**
- Link: **none**
- Cc: stable: **none** (expected)
- Signed-off-by: Wahid Khan (author); Jiri Kosina (HID maintainer,
applied the patch)
- Ignore: any Sasha Levin SOB / `[Upstream commit ...]` (pipeline)
Notable: maintainer Ack + Intel Tested-by + HID maintainer SOB.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** Some ISH firmware (Tiger Lake LP, PCI `8086:a0fc`, HID GUID
`{33AECD58-B679-4E54-9BD9-A04D34F0C226}`) periodically resends a valid
`HOSTIF_DM_ENUM_DEVICES` **response** about every 79 seconds after
init.
- **Symptom:** The driver treats that as a bad packet, calls
`ish_hw_reset()`, and fully re-inits ISHTP. About **1100 times per
day**.
- **Root cause:** One condition folds “no response flag” and `init_done`
together:
`if (!(response_flag) || init_done) -> bad packet + ish_hw_reset`
- **Fix:** Keep rejecting messages with no response flag; drop valid
post-init ENUM_DEVICES.
- **Versions:** Observed on TGL LP; no kernel-version bound in the
message.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: **Not a hidden fix.** Explicit firmware-quirk / incorrect-error-
handling fix. “Ignore” here is the workaround, not cleanup.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/hid/intel-ish-hid/ishtp-hid-client.c` only
- Scope: **+3 / -2** in `process_recv()`, `HOSTIF_DM_ENUM_DEVICES` case
- Classification: **single-file surgical fix**
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** Any ENUM_DEVICES with no response bit **or**
`client_data->init_done` increments `bad_recv_cnt`, logs via
`report_bad_packet()`, and calls `ish_hw_reset()`.
- **After:** No response bit still resets. If the response bit is set
and `init_done` is true, the handler `break`s (discard). Pre-init
responses still enumerate devices.
- Path: receive path after probe succeeds (`init_done = 1` at the end of
`hid_ishtp_cl_init()`).
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- **Category:** hardware/firmware workaround + logic/correctness
- **Mechanism:** Firmware sends a valid post-init ENUM_DEVICES
**response**. The driver wrongly classifies it as corruption and
resets the ISH PCI function.
- Header check: `CMD_MASK` is `0x7F`, `IS_RESPONSE` is `0x80`.
`!(recv_msg->hdr.command & ~CMD_MASK)` means “bit 7 not set” (request,
not response). That part is unchanged.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct relative to the described firmware behavior: stop
resetting on a valid response after init.
- Minimal; no API/data-structure change.
- Regression risk: **low**. Post-init ENUM_DEVICES were never processed
as enumeration; they only caused reset+reinit. Discarding them avoids
the reset storm. Genuine hotplug would use `HOSTIF_DM_ADD_DEVICE`
(command 34), which this patch does not touch.
- GET_HID_DESCRIPTOR / GET_REPORT_DESCRIPTOR still use the old
`init_done` reset. That is out of scope; the commit only claims
ENUM_DEVICES is resent.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Combined guard introduced in `0b28cb4bcb17dc` (2016-08-17) **HID:
intel-ish-hid: ISH HID client driver** — original driver.
- `ish_hw_reset()` in that path: `29b06d12ba796a` (2019) **Use the new
interface functions in HID ish client**.
- Present in this tree from the beginning of intel-ish-hid. Not a recent
mainline-only bug.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: **No Fixes: tag.** Bug is in original 2016 client driver, which
**is** an ancestor of HEAD (`git merge-base --is-ancestor 0b28cb4bcb17dc
HEAD`).
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- `d21497331b967` already in this tree: **Reset enum_devices_done before
enumeration**. Same failure mode (`init_done` + ENUM_DEVICES →
`ish_hw_reset`) on S3/S4 when there are 0 sensors. Different trigger
(stale `enum_devices_done`), complementary, **not** a substitute for
this patch.
- Not a numbered series (`X/Y`). Standalone.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Wahid Khan has **no** prior commits in this tree under
`drivers/hid/`. Weight comes from Srinivas Ack, Zhang Tested-by, Jiri
Kosina SOB. Srinivas is listed in MAINTAINERS for INTEL INTEGRATED
SENSOR HUB DRIVER.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: **None.** Touches existing `process_recv` / `init_done` /
`CMD_MASK`. No new helpers. A later “clamp HID device count” patch
(openwall, 2026-07-30) is independent and not required.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- v1: 2026-06-27, https://ratatoskr.run/linux-input/2026/06/17183853 —
same diff; SOB was `Wahid` (incomplete).
- v2: 2026-07-20, https://ratatoskr.run/linux-input/2026/07/17285763 —
changelog: “added proper sign off”. **No code change.**
- Thread listing also shows Srinivas replies on 2026-06-29.
- `b4 dig -c 13054abbaa4f...` was the wrong SHA (hid.git SID from a
search snippet); lore is behind Anubis (403/PoW). **UNVERIFIED:** full
text of Srinivas’s replies.
- Committed version is v2 plus Acked-by / Tested-by / Jiri Kosina SOB.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record: Recipients/maintainers for this subsystem are Srinivas
Pandruvada, Jiri Kosina, Benjamin Tissoires, linux-input. Ack is from
the ISH maintainer; apply from HID maintainer. **UNVERIFIED:** `b4 dig
-w` recipient list (lore blocked).
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No syzbot/bugzilla Link. Hardware observation is in the commit:
TGL LP `8086:a0fc`, ~79s period. Tested-by from Intel’s Zhang Lixu (same
tester as the related `enum_devices_done` stable fix).
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone. Not part of Shen Yongchao’s later process_recv
bounds-check series. Related `enum_devices_done` fix is already here.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: Searches hit AUTOSEL for **Reset enum_devices_done**, not this
subject. **UNVERIFIED:** whether this exact patch was already discussed
on stable@. That is ignored as circular anyway.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `process_recv()` only.
**Step 5.2: TRACE CALLERS**
Record:
- `ish_cl_event_cb()` → `process_recv()`
- Registered in `hid_ishtp_cl_init()` via `ishtp_register_event_cb()`
- `ishtp_cl_bus_rx_event()` `schedule_work(&device->event_work)` →
`ishtp_bus_event_work()` → `event_cb`
- Workqueue RX path, not a syscall; triggered by ISH firmware messages
on systems with `CONFIG_INTEL_ISH_HID`.
**Step 5.3: TRACE CALLEES**
Record: On the bad path: `report_bad_packet()`, `ish_hw_reset()` →
`_ish_hw_reset()` → `pci_reset_function()`. After reset,
`hid_ishtp_cl_reset()` schedules `hid_ishtp_cl_reset_handler()`, which
deinits and calls `hid_ishtp_cl_init(..., 1)` up to 3 times.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: Userspace does not send ENUM_DEVICES; firmware does. Reachable
on every TGL-LP (and similar) ISH laptop after HID client init. High
impact for those machines: periodic PCI reset of the sensor hub.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same `!(command & ~CMD_MASK) || init_done` reset in
`HOSTIF_GET_HID_DESCRIPTOR` and `HOSTIF_GET_REPORT_DESCRIPTOR`. Commit
only changes ENUM_DEVICES, matching the firmware that resends that
command.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: **Yes.** `ishtp-hid-client.c` lines 112–121 are identical to the
pre-patch code. TGL LP ID `0xA0FC` is in `ipc/hw-ish.h` / `pci-ish.c`
(`1479a82d82df6`, 2019). HID GUID in this file matches the commit. Bug
introduced with the original driver (`0b28cb4bcb17`, 2016).
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply.** Exact hunk context matches this file
(verified). No refactor of `process_recv` between the patch parent and
this 5.15 tree.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: `d21497331b967` is here and does **not** ignore post-init
ENUM_DEVICES; it only clears `enum_devices_done` before sending the
command. The periodic-resend bug remains.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **HID / Intel ISH** (`drivers/hid/intel-ish-hid/`).
**IMPORTANT** for Intel laptops/tablets (accelerometer, gyro, ALS,
etc.), not core mm/VFS. Not staging.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Mature since 2016. This tree still receives ISH fixes (e.g.
`enum_devices_done`). Platform IDs through Tiger Lake are present.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Driver-specific / platform-specific:** `CONFIG_INTEL_ISH_HID`
on x86 with ISH firmware that resends ENUM_DEVICES. Confirmed example:
TGL LP `8086:a0fc`, a common 11th-gen laptop platform. Same HID client
GUID is used across ISH generations, so other firmware versions could
hit it too.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: After successful ISH HID init, firmware timer ~79s. No userspace
trigger; unprivileged users do not need to do anything. Very likely on
affected hardware (every ~79s forever).
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record:
- Failure: `pci_reset_function()` on ISH + full ISHTP reinit, plus `BAD
packet` `dev_err` flood.
- Sensors drop and come back ~1100 times/day; possible gaps in
input/IIO; extra PCI reset load.
- Severity: **HIGH** (stability / availability of ISH; not a KASAN UAF,
not silent FS corruption).
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** high for TGL-class ISH machines still on 5.15 LTS
(Android/ChromeOS/enterprise).
- **Risk:** very low (5 lines, post-init discard only; malformed packets
still reset).
- **Ratio:** strongly favors backport.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real firmware misbehavior on shipping Intel ISH (TGL LP `8086:a0fc` in
this tree).
- User-visible: PCI reset + ISHTP reinit ~1100/day, error log flood,
sensor disruption.
- Buggy guard present here since original 2016 driver.
- 5-line, obviously correct split of two cases.
- Applies cleanly.
- ISH maintainer Ack, Intel Tested-by, HID maintainer applied it.
- Same `init_done` + ENUM_DEVICES + `ish_hw_reset` class of bug already
accepted into this tree (`d21497331b967`).
- Fits the **hardware quirk/workaround** stable exception.
AGAINST:
- Not a panic/UAF/CVE; driver-specific.
- Silently ignoring post-init ENUM_DEVICES will not pick up a device
list change via that command (old code did that only via a brutal
reset).
- Full Srinivas review text not retrieved (lore Anubis).
UNRESOLVED:
- Exact lore body of 2026-06-29 replies.
- How many ISH firmware versions besides TGL LP resend ENUM_DEVICES.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — Tested-by Intel; Acked by
ISH maintainer; logic is a 2-way split of an existing if.
2. Fixes a real bug that affects users? **PASS** — observed on TGL LP;
periodic ISH reset.
3. Important issue (crash, security, corruption, deadlock)? **PASS** —
repeated PCI function reset and full client reinit is a serious
stability issue, not cosmetic.
4. Small and contained? **PASS** — one file, 5 lines.
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — exact context in 5.15.221.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: **Hardware quirk/workaround** for non-compliant/buggy ISH
firmware. Also a logic fix for misclassifying a valid response.
**Step 9.4: MAKE YOUR DECISION**
This should be backported to **this** 5.15 tree. The bug exists here,
the hardware ID exists here, the fix is tiny and applies cleanly, and
the current behavior is a reset storm on common Intel ISH laptops.
===============================================================
Verification
===============================================================
- [Phase 1] Tags: Tested-by Zhang Lixu; Acked-by Srinivas Pandruvada;
SOB Jiri Kosina; no Fixes/Cc:stable/Reported-by.
- [Phase 2] Diff: `process_recv` ENUM_DEVICES only; split `!response ||
init_done` into reject-without-flag vs discard-if-init_done.
- [Phase 2] `CMD_MASK`/`IS_RESPONSE` in `ishtp-hid.h` confirmed
(`0x7F`/`0x80`).
- [Phase 3] blame: guard from `0b28cb4bcb17dc` (2016); ancestor of HEAD.
- [Phase 3] related: `d21497331b967` already in tree; does not fix
periodic resend.
- [Phase 3] author: no prior Wahid Khan commits in this hid tree.
- [Phase 4] ratatoskr v1 2026-06-27, v2 2026-07-20 (“proper sign off”
only); Srinivas replies listed 2026-06-29.
- [Phase 4] lore.kernel.org 403/Anubis; `b4 dig` on a mistaken hid.git
SHA failed. UNVERIFIED: full review email text.
- [Phase 5] callers: workqueue `ishtp_bus_event_work` →
`ish_cl_event_cb` → `process_recv`.
- [Phase 5] reset: `_ish_hw_reset` uses `pci_reset_function`;
`hid_ishtp_cl_reset_handler` re-runs `hid_ishtp_cl_init`.
- [Phase 6] `git describe HEAD` = `p-5.15-2-g9a29d9b0f9507`; `make
kernelversion` = 5.15.221.
- [Phase 6] buggy if at lines 113–114 present; exact patch context
matches.
- [Phase 6] TGL `0xA0FC` in tree (`1479a82d82df6`); GUID matches commit.
- [Phase 7] MAINTAINERS: INTEL INTEGRATED SENSOR HUB DRIVER → Srinivas +
Jiri.
- [Phase 8] failure mode: periodic ISH PCI reset, HIGH; not a kernel
oops.
- UNVERIFIED: exact Srinivas reply text; whether other FW besides TGL LP
hits this.
The problem is a firmware quirk that this 5.15 driver turns into an ISH
reset loop. The fix is small, reviewed, tested, and already matches the
local source.
**YES**
drivers/hid/intel-ish-hid/ishtp-hid-client.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/hid/intel-ish-hid/ishtp-hid-client.c b/drivers/hid/intel-ish-hid/ishtp-hid-client.c
index 12a43c64e8156..085313ae354ab 100644
--- a/drivers/hid/intel-ish-hid/ishtp-hid-client.c
+++ b/drivers/hid/intel-ish-hid/ishtp-hid-client.c
@@ -113,8 +113,7 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
switch (recv_msg->hdr.command & CMD_MASK) {
case HOSTIF_DM_ENUM_DEVICES:
- if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
- client_data->init_done)) {
+ if (!(recv_msg->hdr.command & ~CMD_MASK)) {
++client_data->bad_recv_cnt;
report_bad_packet(hid_ishtp_cl, recv_msg,
cur_pos,
@@ -122,6 +121,8 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
break;
}
+ if (client_data->init_done)
+ break;
client_data->hid_dev_count = (unsigned int)*payload;
if (!client_data->hid_devices)
client_data->hid_devices = devm_kcalloc(
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH AUTOSEL 6.18-5.10] HID: roccat: fix locking in roccat_connect() and roccat_disconnect()
[not found] <20261019135441.1420968-1-sashal@kernel.org>
` (10 preceding siblings ...)
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18-5.10] HID: intel-ish-hid: ignore post-init ENUM_DEVICES from firmware Sasha Levin
@ 2026-10-19 13:49 ` Sasha Levin
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18] HID: Intel-thc-hid: Intel-quickspi: Fix buffer overflow Sasha Levin
` (4 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:49 UTC (permalink / raw)
To: patches, stable
Cc: Dmitry Antipov, Jiri Kosina, Sasha Levin, erazor_de, jikos,
bentiss, linux-input, linux-kernel
From: Dmitry Antipov <dmantipov@yandex.ru>
[ Upstream commit d76994443eed0af297cb82bd038ae9d76327ef90 ]
Extend critical section in roccat_connect() to ensure that partially
initialized 'struct roccat_device' is never exposed in 'devices' list,
and do the same in roccat_disconnect() to avoid racy 'devices' access
against roccat_release().
Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local tree is **6.18.57** (`v6.18.57-155-gcdf239ca885b2`). The buggy
locking is present at `v6.18.57`; this commit is not an ancestor of that
tag.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
- Subsystem: `HID: roccat`
- Action verb: **fix**
- Claimed intent: correct locking around `roccat_connect()` /
`roccat_disconnect()` so a half-initialized device is not published
and disconnect cannot race with `roccat_release()`.
- Record: `[HID/roccat] [fix] [locking around connect/disconnect vs
devices[] publication]`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Upstream `d76994443eed0af297cb82bd038ae9d76327ef90`:
- Signed-off-by: Dmitry Antipov `<dmantipov@yandex.ru>` (author)
- Signed-off-by: Jiri Kosina `<jkosina@suse.com>` (HID maintainer)
- No Fixes:, Reported-by:, Tested-by:, Link:, or Cc: stable (expected
for this review)
- Ignore pipeline `[Upstream commit ...]` and `Signed-off-by: Sasha
Levin`
The series cover letter for patch 2/2 (not this commit) had:
- Reported-by: syzbot+d632e93ffcd1452bc61e@syzkaller.appspotmail.com
- Closes: https://syzkaller.appspot.com/bug?extid=d632e93ffcd1452bc61e
A competing same-week patch for the same races (Deepanshu Kartikey) had:
- Reported-by: syzbot+c492a9e154f81127551f@syzkaller.appspotmail.com
- Tested-by: syzbot
- Closes: https://syzkaller.appspot.com/bug?extid=c492a9e154f81127551f
Title: **KASAN: slab-use-after-free Read in roccat_disconnect**
Record: No tags on this commit itself; the same UAF is a documented
syzbot KASAN crash.
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
- Bug: `devices[minor]` is published, then `devices_lock` is dropped
before `struct roccat_device` is fully initialized. Disconnect also
drops the lock between lookup and teardown, racing `roccat_release()`.
- Symptom: concurrent open/ioctl/release vs probe/remove can use an
uninitialized mutex or free the object while disconnect still reads
`device->open`.
- Version: none stated. Blame shows the pattern since 2010
(`206f5f2fcb5ff`).
- Root cause (author): critical section too short.
Record: `[UAF / uninitialized-mutex race] [KASAN UAF in disconnect;
possible lock on uninit mutex in open] [present since 2010] [lock
dropped too early]`
**Step 1.4: DETECT HIDDEN BUG FIXES**
Not disguised. Record: `[Not a hidden fix; explicit locking/race fix]`
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY**
- File: `drivers/hid/hid-roccat.c` — 3 insertions, 5 deletions (net −2)
- Functions: `roccat_connect()`, `roccat_disconnect()`
- Record: `[1 file, +3/-5] [roccat_connect, roccat_disconnect] [single-
file surgical]`
**Step 2.2: CODE FLOW CHANGE**
Hunk 1 — `roccat_connect()` at v6.18.57:
- Before: under `devices_lock`, slot `devices[minor]`,
`device_create()`, **unlock**, then `init_waitqueue_head`,
`mutex_init(readers_lock/cbuf_lock)`, set `hid`, `exist`,
`report_size`.
- After: same work, but unlock only after those initializers.
- Path: probe / `roccat_connect()` from hid-roccat-* drivers.
Hunk 2 — `roccat_disconnect()`:
- Before: lock, load `devices[minor]`, **unlock**; `exist=0`;
`device_destroy()`; lock, `devices[minor]=NULL`, unlock; then read
`device->open` and either `hid_hw_close`+wakeup or
`roccat_free_device()`.
- After: one critical section covering lookup, `exist=0`, destroy, NULL
slot, free-or-keep.
- Path: USB unplug / driver remove (`savu_remove`, `kone_remove`, etc.).
**Step 2.3: BUG MECHANISM**
Category: **race / UAF** plus **uninitialized mutex**.
Verified against v6.18.57:
1. Connect publishes `devices[minor]` then drops the lock before
`mutex_init(&device->readers_lock)`. `roccat_open()` takes
`devices_lock`, then `mutex_lock(&device->readers_lock)`. That is a
lock on an uninitialized mutex if open wins the race after
`device_create()`.
2. Disconnect reads `device` and drops the lock. `roccat_release()`
(also under `devices_lock`) can see `exist==0` and `open==0` and call
`roccat_free_device()`. Disconnect then reads `device->open` at old
line 382 — **KASAN slab-use-after-free**. Syzbot’s stack matches:
freed in `roccat_release`, use in `roccat_disconnect`.
Record: `[race/UAF + uninit mutex] [extend devices_lock so publication
and teardown are atomic vs open/release]`
**Step 2.4: FIX QUALITY**
- Correct for the reported UAF: release and disconnect both need
`devices_lock` for the whole free-or-keep decision. After this, they
cannot interleave.
- Correct for the uninit-mutex race: open/ioctl wait on `devices_lock`
until mutexes exist.
- Minimal; no API change.
- Residual issues (pre-existing, not introduced):
- If files are still open, disconnect NULLs `devices[minor]` and does
not free. `roccat_release()` then sees NULL and returns `-ENODEV`
without `roccat_free_device()` — **leak on unplug-while-open**. That
was already the non-racy outcome of the old NULL-then-close
sequence; the racy outcome was UAF. UAF → leak is an improvement.
- Patch 2/2 (`kref`) was meant to finish lifetime handling; Jiri
Kosina did **not** apply it (kref accounting bugs).
- `roccat_report_event()` still loads `devices[minor]` without the
lock (pre-existing).
- Regression risk: disconnect now holds `devices_lock` across
`device_destroy()` and `hid_hw_close()`. `roccat_release()` already
held that lock across `hid_hw_close()`. `device_create()` was already
inside the lock. hidraw uses the same “hold table lock for the whole
connect/disconnect” pattern.
Record: `[obviously correct for the UAF; residual leak is pre-existing
common path] [low regression risk]`
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME**
- Buggy unlock-before-init in connect: `206f5f2fcb5ff` (Stefan Achatz,
2010-05-19), v2.6.35-era.
- Disconnect split lock / `devices[minor]=NULL`: `e6fa47af5542d`
(2011-01-30).
- Record: `[206f5f2fcb5ff / e6fa47af5542d] [present since ~2010,
including 6.18.y]`
**Step 3.2: FIXES TAG**
None. Introducer is `206f5f2fcb5ff`, which **is** in this tree.
**Step 3.3: FILE HISTORY**
At v6.18.57:
- `da00eac19feef` HID: roccat: free buffered reports when destroying
device (already in 6.18.57; this patch only moves the existing
`roccat_free_device()` call)
- `36bb2d0b91501` HID: roccat: fix use-after-free in roccat_report_event
(CVE-2026-43111, already in 6.18.24+)
No later commit on this file after the candidate. Standalone 1/2; 2/2
not merged.
**Step 3.4: AUTHOR**
Dmitry Antipov — not the original driver author; HID maintainer Jiri
Kosina applied 1/2. No other Antipov hid-roccat commits in this tree
besides this one.
**Step 3.5: DEPENDENCIES**
- Uses existing `devices_lock` and `roccat_free_device()` (the latter
from `da00eac19feef`, already in 6.18.57).
- Patch 2/2 is **not** required: maintainer applied 1/2 alone.
- Record: `[standalone; applies on 6.18.57]`
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: ORIGINAL DISCUSSION**
`b4 dig -c d76994443eed0af297cb82bd038ae9d76327ef90`:
- https://patch.msgid.link/20260902094551.200587-1-dmantipov@yandex.ru
- Series: **v1 only**, `[PATCH 1/2]` + `[PATCH 2/2] HID: roccat: use
kref to manage device instances`
Jiri Kosina (11 Sep 2026): **applied 1/2**. On 2/2: “the issues that
Sashiko pointed out with 2/2 are real, so please fix them and resubmit
separately.”
Syzbot bug still listed, but Oct 8 upstream retests reported **no
crash**; later Oct 16 tests are extra lifetime patches in `hid.git
for-7.4/roccat`, not a revert of 1/2.
**Step 4.2: RECIPIENTS (`b4 dig -w`)**
Dmitry Antipov, Jiri Kosina, Benjamin Tissoires, linux-input@, lvc-
project@. HID maintainers were on the To/Cc list.
**Step 4.3: BUG REPORT**
https://syzkaller.appspot.com/bug?extid=c492a9e154f81127551f
- KASAN slab-use-after-free Read in `roccat_disconnect`
- C repro, 20 crashes, prio:high
- Freed in `roccat_release`, used at `if (device->open)` in disconnect
- Trigger: USB disconnect vs close of the roccat char dev (syzbot USB
gadget)
- Security assessment on the dashboard: DoS exploitable, peripheral
trigger
**Step 4.4: RELATED SERIES**
- 2/2 kref: not applied (broken accounting / dangling `devices[]`
pointer).
- Competing Kartikey patch: same disconnect lock extension; also inits
the device **before** publishing. Maintainer took Antipov’s smaller
1/2 instead. Disconnect half is equivalent.
**Step 4.5: STABLE LIST**
No prior stable-thread rejection found (lore.kernel.org/stable search
did not return a relevant hit). Absence of Cc: stable is expected.
Record: `[lore thread via b4; 1/2 applied, 2/2 rejected; syzbot KASAN
UAF with C repro]`
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: FUNCTIONS**
`roccat_connect()`, `roccat_disconnect()`.
**Step 5.2: CALLERS**
`roccat_connect` / `roccat_disconnect` from probe/remove of:
- hid-roccat-pyra, ryos, savu, arvo, isku, kone, koneplus, konepure,
kovaplus
Syzbot crash: `savu_remove` → `roccat_disconnect` on USB disconnect
workqueue vs `roccat_release` from `__fput`.
`devices_lock` also used by `roccat_open`, `roccat_release`,
`roccat_ioctl` — those are the racing syscalls.
**Step 5.3: CALLEES**
`device_create` / `device_destroy`, `hid_hw_close`,
`wake_up_interruptible`, `roccat_free_device`.
**Step 5.4: REACHABILITY**
Yes. Unprivileged USB gadget / physical unplug plus close of
`/dev/roccat*`. Syzbot has a C repro.
**Step 5.5: SIMILAR PATTERNS**
hidraw holds `minors_rwsem` for the whole `hidraw_connect()` /
`hidraw_disconnect()`. Same idea.
Record: `[USB remove vs fput; userspace-reachable; HID-roccat family]`
---
## PHASE 6: CROSS-REFERENCING AGAINST THIS TREE
**Step 6.1: BUGGY CODE IN THIS TREE?**
Yes, at `v6.18.57:drivers/hid/hid-roccat.c` `roccat_connect()` unlocks
at old line 347 before init; `roccat_disconnect()` unlocks at old line
372 then later reads `device->open`.
`git merge-base --is-ancestor 7e1d29620273b v6.18.57` → not an ancestor.
`git merge-base --is-ancestor d76994443eed v6.18.57` → not an ancestor.
**Step 6.2: BACKPORT DIFFICULTY**
`patch --dry-run -p1` of the upstream diff against
`v6.18.57:drivers/hid/hid-roccat.c` → **clean apply**.
**Step 6.3: RELATED FIXES ALREADY HERE**
- `36bb2d0b91501` — different UAF (readers list in
`roccat_report_event`), already in 6.18.y.
- `da00eac19feef` — leak of cbuf reports, already in 6.18.y.
- This disconnect/open race is **not** fixed in 6.18.57.
Record: `[bug present; clean apply; no substitute fix]`
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1:** `drivers/hid/hid-roccat.c` — HID char device for Roccat
mice/keyboards (`CONFIG_HID_ROCCAT`, depends on `USB_HID`). Criticality:
**PERIPHERAL**, but the UAF is real for those devices and for syzbot USB
emulation.
**Step 7.2:** Driver is old (2010) and low-churn except recent UAF/leak
fixes. Mature code with a long-standing race, not a new subsystem.
Record: `[HID/roccat] [PERIPHERAL] [mature, recent UAF fixes]`
---
## PHASE 8: IMPACT AND RISK
**Step 8.1:** Users of Roccat HID devices with `CONFIG_HID_ROCCAT`; also
fuzzers/USB gadget. Not universal.
**Step 8.2:** Trigger: unplug (or driver unbind) while userspace has the
char device open/closing. Timing-dependent but **reproduced** (syzbot C
repro). Not a normal unprivileged syscall-only path without USB, but USB
remove is a normal user action.
**Step 8.3:** Failure: KASAN UAF in `roccat_disconnect` on `usb_hub_wq`
→ kernel oops / memory corruption. Severity: **HIGH** (crash, potential
memory-safety issue).
**Step 8.4:**
- Benefit: high for affected hardware / USB remove-vs-close; closes a
confirmed UAF.
- Risk: low (8-line lock-scope change, same lock already used around
`hid_hw_close` in release).
- Ratio: **benefit >> risk**. Residual leak on unplug-while-open is
worse than nothing but far better than UAF.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: EVIDENCE**
For:
- Confirmed KASAN UAF, syzbot C repro, crash on USB disconnect vs
`roccat_release`
- Second race: open can lock uninitialized `readers_lock`
- Code in 6.18.57 matches the buggy version
- 8-line lock-scope change, clean apply
- HID maintainer applied 1/2 as a standalone fix
- No new API; not a feature
- Same class of fix already accepted for this file (CVE-2026-43111)
Against:
- Niche HID driver
- Incomplete lifetime (leak if unplug while fds remain); 2/2 kref not
merged
- `roccat_report_event()` still lockless on `devices[]` (pre-existing)
- Connect still publishes the pointer before init, but now under the
lock so open waits
Unresolved:
- Whether a later hid.git for-7.4 kref series will replace this; that
does not make 1/2 unsafe for 6.18.y.
**Step 9.2: STABLE RULES**
1. Obviously correct and tested? **PASS** — lock covers the UAF window;
syzbot repro exists; maintainer applied it.
2. Real bug affecting users? **PASS** — KASAN UAF on unplug vs close.
3. Important (crash/security/corruption)? **PASS** — UAF/oops, HIGH.
4. Small and contained? **PASS** — +3/−5, one file.
5. No new features/APIs? **PASS**.
6. Applies to local tree? **PASS** — clean on v6.18.57.
**Step 9.3: EXCEPTIONS**
Not an ID/quirk/DT/build/docs exception. It is a normal race/UAF fix.
**Step 9.4: DECISION**
Backport to this 6.18.y tree. The bug is here, the fix is small, and it
addresses a real UAF, not a refactor.
---
### What the commit solves for 6.18.y users
On 6.18.57, `roccat_disconnect()` drops `devices_lock` and then reads
`device->open`. Concurrent `roccat_release()` can free that object.
Syzbot hits that as **KASAN slab-use-after-free in
`roccat_disconnect`**. Connect also exposes the object before mutex
init. Extending the existing `devices_lock` critical sections closes
both windows. Remaining leak-if-still-open is the old non-racy path, not
a new regression.
Risk vs benefit: a few lines of lock-scope change vs a demonstrated UAF.
Patch 2/2 is not a prerequisite.
---
Verification:
- [Phase 1] Parsed upstream `d76994443eed`; tags: author SOB + Jiri
Kosina SOB only
- [Phase 1] Series 2/2 has syzbot `d632e93ffcd1452bc61e`; competing
patch has syzbot `c492a9e154f81127551f`
- [Phase 2] Diff +3/−5 in `roccat_connect`/`roccat_disconnect`; compared
to `v6.18.57:drivers/hid/hid-roccat.c`
- [Phase 2] Confirmed open takes `readers_lock` after `devices_lock`;
connect used to init that mutex after unlock
- [Phase 2] Confirmed disconnect old line 382 is `if (device->open)` —
matches KASAN “Read of size 4”
- [Phase 3] `git blame -L 309,387 v6.18.57 -- drivers/hid/hid-roccat.c`:
2010/2011 introducers
- [Phase 3] `git merge-base --is-ancestor 7e1d29620273b v6.18.57` →
false; not in 6.18.57
- [Phase 3] `da00eac19feef` / `36bb2d0b91501` already in 6.18.57;
different bugs
- [Phase 4] `b4 dig -c d76994443eed` → msgid
`20260902094551.200587-1-dmantipov@yandex.ru`
- [Phase 4] `b4 mbox` thread: Jiri applied 1/2, rejected 2/2
- [Phase 4] `b4 dig -w`: Kosina, Tissoires, linux-input
- [Phase 4] WebFetch syzbot: KASAN UAF, C repro, 20 crashes; Oct 8
upstream retest no crash
- [Phase 5] grep callers: nine hid-roccat-* probe/remove paths; syzbot
used savu
- [Phase 6] `git describe HEAD` → `v6.18.57-155-gcdf239ca885b2`; `make
kernelversion` → 6.18.57
- [Phase 6] `patch --dry-run -p1` of upstream diff on v6.18.57 file →
success
- [Phase 7] Kconfig `HID_ROCCAT` depends on `USB_HID`
- [Phase 8] Failure mode verified from syzbot report, not inferred
- UNVERIFIED: later hid.git for-7.4 kref work (not in this tree; 2/2 was
rejected from mainline)
- UNVERIFIED: lore.kernel.org HTTP fetch (403); used `b4` +
openwall/syzkaller instead
The patch is a small, correct UAF/race fix that applies cleanly to this
6.18.57 tree.
**YES**
drivers/hid/hid-roccat.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c
index e54b6a8a92ef7..77042c7edf765 100644
--- a/drivers/hid/hid-roccat.c
+++ b/drivers/hid/hid-roccat.c
@@ -344,8 +344,6 @@ int roccat_connect(const struct class *klass, struct hid_device *hid, int report
return temp;
}
- mutex_unlock(&devices_lock);
-
init_waitqueue_head(&device->wait);
INIT_LIST_HEAD(&device->readers);
mutex_init(&device->readers_lock);
@@ -356,6 +354,7 @@ int roccat_connect(const struct class *klass, struct hid_device *hid, int report
device->cbuf_end = 0;
device->report_size = report_size;
+ mutex_unlock(&devices_lock);
return minor;
}
EXPORT_SYMBOL_GPL(roccat_connect);
@@ -369,15 +368,12 @@ void roccat_disconnect(int minor)
mutex_lock(&devices_lock);
device = devices[minor];
- mutex_unlock(&devices_lock);
device->exist = 0; /* TODO exist maybe not needed */
device_destroy(device->dev->class, MKDEV(roccat_major, minor));
- mutex_lock(&devices_lock);
devices[minor] = NULL;
- mutex_unlock(&devices_lock);
if (device->open) {
hid_hw_close(device->hid);
@@ -385,6 +381,8 @@ void roccat_disconnect(int minor)
} else {
roccat_free_device(device);
}
+
+ mutex_unlock(&devices_lock);
}
EXPORT_SYMBOL_GPL(roccat_disconnect);
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH AUTOSEL 6.18] HID: Intel-thc-hid: Intel-quickspi: Fix buffer overflow
[not found] <20261019135441.1420968-1-sashal@kernel.org>
` (11 preceding siblings ...)
2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] HID: roccat: fix locking in roccat_connect() and roccat_disconnect() Sasha Levin
@ 2026-10-19 13:50 ` Sasha Levin
2026-10-19 15:04 ` sashiko-bot
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] HID: quirks: Add ALWAYS_POLL quirk for Beitong BTP-KP20D dongle Sasha Levin
` (3 subsequent siblings)
16 siblings, 1 reply; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:50 UTC (permalink / raw)
To: patches, stable
Cc: Even Xu, Jiri Kosina, Sasha Levin, xinpeng.sun, jikos, bentiss,
linux-input, linux-kernel
From: Even Xu <even.xu@intel.com>
[ Upstream commit a1cdd72371270640bd357bd3e3b2ec0be17c9536 ]
The input buffers are used to store complete HID-over-SPI packets,
including their protocol headers. However, their sizes are
currently calculated from the payload length only.
Allocate enough space for both the payload and the packet header to
prevent a buffer overflow when the payload reaches its maximum size.
Signed-off-by: Even Xu <even.xu@intel.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a real heap overflow in Intel QuickSPI HID input, and the local
6.18.57 tree still has the undersized `input_buf` allocation, so it
should be backported.
Local tree: **v6.18.57** (`6.18.57`, HEAD `cdf239ca885b2`). The buggy
allocation is present at `v6.18.57`; `HIDSPI_INPUT_BODY_SIZE` already
exists here. The patch applies cleanly.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[HID/intel-thc-hid/intel-quickspi] [fix] [prevent input_buf
overflow by including HIDSPI packet header in allocation]`
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Signed-off-by: Even Xu <even.xu@intel.com>` (author; INTEL THC
maintainer)
- `Signed-off-by: Jiri Kosina <jkosina@suse.com>` (HID maintainer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, `Link:`, or `Cc: stable` (absence is expected)
- Pipeline-only markers ignored: `[Upstream commit
a1cdd72371270640bd357bd3e3b2ec0be17c9536]`, `Signed-off-by: Sasha
Levin`
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- Bug: `input_buf` is sized from HID payload length only, but stores a
full HID-over-SPI packet (header + payload).
- Symptom: buffer overflow when the payload is at its maximum size.
- Root cause: size uses `max_input_len` / `rep_desc_len` and omits
`HIDSPI_INPUT_BODY_HEADER_SIZE` (4 bytes).
- No stack traces, versions, or syzbot IDs.
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. Subject and body state a buffer overflow. The one-
line change matches that claim.
---
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c`
(+2/-1)
- Function: `quickspi_alloc_report_buf()`
- Scope: single-file surgical fix
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- Before (`v6.18.57`): `qsdev->input_buf = devm_kzalloc(...,
max_input_len, ...)` where `max_input_len = max(rep_desc_len,
max_input_len)`.
- After: allocate `HIDSPI_INPUT_BODY_SIZE(max_input_len)` = payload +
`sizeof(struct input_report_body_header)` (packed 4 bytes).
- Path: probe-time allocation; used later on every RX DMA completion.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record: `[BUFFER OVERFLOW / OUT-OF-BOUNDS]`
Mechanism verified in this tree:
1. IRQ thread `quickspi_irq_thread_handler()` calls `thc_rxdma_read(...,
qsdev->input_buf, &input_len, ...)`.
2. `read_dma_buffer()` does `sg_copy_to_buffer(sg, nent, read_buff,
mes_len)` with **no check against `input_buf` allocation size**.
3. The only bound is `mes_len > read_config->max_packet_size`, and
`max_packet_size` is `ALIGN(max_input_len, SZ_4K)`, so a packet of
`max_input_len + 4` is allowed for typical HID sizes.
4. `quickspi_handle_input_data()` treats `input_buf` as `struct
input_report_body` (4-byte header + content).
5. Output path already accounts for the header via
`HIDSPI_OUTPUT_REPORT_SIZE` (from `6fcefe71aeb52`, already in
`v6.18.57`). Input was left inconsistent.
**Step 2.4: ASSESS THE FIX QUALITY**
Record: Obviously correct. Uses an existing macro. 4 extra
`devm_kzalloc` bytes. No locking, API, or ABI change. Regression risk is
very low (slightly larger probe allocation).
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record: Buggy alloc introduced in `4138f21115aec` ("HID: intel-thc-hid:
intel-quickspi: Complete THC QuickSPI driver", Xinpeng Sun, 2025-01-06).
Present since at least **v6.15**. Present in this 6.18.y tree.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Introducer is `4138f21115aec`, which **is** an
ancestor of `v6.18.57`.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record (on this tree, limited to the file):
- `6fcefe71aeb52` — already in `v6.18.57`; sized **output** `report_buf`
with `HIDSPI_OUTPUT_REPORT_SIZE` and added a copy bound. That made the
remaining input undersize obvious.
- `b2301bdb4b3ed`, `c2854af5774b0`, device-ID commits — unrelated.
- Sibling `4bda3254e7b4f` (QuickI2C overflow) is a parallel independent
fix, not a prerequisite.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: Even Xu is listed in MAINTAINERS as `INTEL TOUCH HOST CONTROLLER
(THC) DRIVER` co-maintainer. Related work in-tree includes DMA safety
checks and device IDs. This is a maintainer-authored fix.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: Standalone. Needs only `HIDSPI_INPUT_BODY_SIZE` in
`include/linux/hid-over-spi.h`, present at `v6.18.57:91`. Series is
`[PATCH 2/2]` with QuickI2C; the two files do not depend on each other.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c a1cdd72371270640bd357bd3e3b2ec0be17c9536` →
https://patch.msgid.link/20260922024638.932865-3-even.xu@intel.com
- Cover: `[PATCH 0/2] HID: Intel-thc-hid: Fix potential buffer overflow`
(`20260922024638.932865-1`)
- `b4 dig -a`: **v1 only** (no later revisions)
- Thread saved via `b4 dig -m`; lore.kernel.org HTTP fetch returned
**403**
- Jiri Kosina: “Applied to hid.git#for-7.3/upstream-fixes, thanks.” No
NAK, no requested changes on the SPI patch.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc `bentiss@kernel.org` (Benjamin Tissoires),
`jikos@kernel.org` (Jiri Kosina), `srinivas.pandruvada@linux.intel.com`,
`linux-input@vger.kernel.org`. HID maintainers were on the original
mail. Kosina applied it.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No `Reported-by` / syzbot / bugzilla. Found by the subsystem
maintainer as a size mismatch. Cover letter calls it a **potential**
overflow; the DMA copy path confirms it is reachable, not theoretical.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Independent 2-patch set (QuickI2C + QuickSPI). Sashiko AI
comment was about the **I2C** patch (`report_len` vs
`HIDI2C_PACKET_LEN`), not this SPI change. SPI `report_buf` is already
header-sized in this tree.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: `curl` to lore.kernel.org/stable also returned 403. UNVERIFIED
whether stable@ discussed this specifically. No local evidence it was
rejected.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `quickspi_alloc_report_buf()`
**Step 5.2: TRACE CALLERS**
Record: Only `quickspi_probe()` at `pci-quickspi.c:660`, after
`reset_tic()`, before `quickspi_dma_init()` /
`quickspi_get_report_descriptor()` / `quickspi_hid_probe()`. Standard
PCI probe. `input_buf` is then written from the IRQ thread on
`THC_RXDMA2_INT` (touch input).
**Step 5.3: TRACE CALLEES**
Record: `devm_kzalloc()` only. Consumers: `thc_rxdma_read()` →
`sg_copy_to_buffer()`; `quickspi_handle_input_data()`.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: `quickspi_probe` → IRQ `THC_RXDMA2_INT` →
`thc_rxdma_read(input_buf)` → `quickspi_handle_input_data`. Reachable
whenever an Intel THC HID-over-SPI touch device delivers a max-sized
input or report-descriptor packet. Not a userspace-crafted syscall
overflow; it is device-driven heap overflow on a common input path.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same class of bug in QuickI2C (`HIDI2C_PACKET_LEN`). Output SPI
buffer already fixed by `6fcefe71aeb52`. No other `input_buf` alloc in
this driver.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record: Yes, at `v6.18.57`:
```
qsdev->input_buf = devm_kzalloc(qsdev->dev, max_input_len, GFP_KERNEL);
```
Driver exists from v6.15 through this 6.18.y tree. Bug introduced with
the completed driver (`4138f21115aec`).
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply**. `patch -p1 --dry-run` against the `v6.18.57`
file succeeded. Surrounding function matches. Macro already present.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: Output-side header sizing (`6fcefe71aeb52`) is already in
`v6.18.57`. Input-side overflow is **not** fixed at `v6.18.57`. No
alternate input_buf fix found.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: `[HID / Intel THC QuickSPI]` `[IMPORTANT]` — not core mm/net,
but the HID-over-SPI path for Intel touch on MTL/LNL/PTL/ARL/WCL/NVL.
Crash/overflow there takes down input on those machines.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Actively maintained (device IDs, PM, DMA bounds). Still a small,
contained driver, not a refactoring minefield.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: Driver-specific / config-specific (`CONFIG_INTEL_QUICKSPI`,
`X86_64 && PCI && ACPI`). Users of Intel THC HID-over-SPI touch (Meteor
Lake through Nova Lake PCI IDs in this tree).
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record: Device sends a HID-over-SPI body whose content length equals
`max_input_len` or `rep_desc_len`. That is a normal max-size touch
report / report-descriptor response, not an exotic error path.
Unprivileged userspace cannot directly size the DMA packet; a
malicious/buggy touch controller can. Trigger likelihood: **realistic on
real hardware**.
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record: Heap buffer overflow via `sg_copy_to_buffer` into `devm_kzalloc`
memory. Typical overrun is 4 bytes; DMA `max_packet_size` is 4K-aligned,
so a larger `mes_len` could copy more. Failure mode: heap corruption →
oops/panic or memory corruption. Severity: **HIGH** (not a WARN-only
issue).
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record: Benefit **high** (stops heap overflow on touch RX). Risk **very
low** (2 lines, +4 bytes, existing macro). Ratio strongly favors
backport.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real heap overflow: DMA copies header+payload into a payload-only
buffer.
- Bug exists in this 6.18.57 tree; driver has been in-tree since v6.15.
- Important: kernel memory corruption / crash on a production Intel
touch path.
- Tiny, obviously correct, uses `HIDSPI_INPUT_BODY_SIZE` already in this
tree.
- Output buffer already got the analogous header sizing here; this
completes the same invariant.
- Author is THC maintainer; HID maintainer applied v1 with no
objections.
- Applies cleanly; no prerequisites missing.
AGAINST:
- No public crash report / syzbot (maintainer-found “potential”
overflow).
- Affects only Intel THC QuickSPI, not all machines.
- Cover letter wording is “potential”; DMA copy confirms it is real.
UNRESOLVED:
- lore.kernel.org HTTP 403; discussion recovered via `b4 dig -m`.
- Stable list search unverified for the same 403 reason.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — 4-byte header included via
existing macro; applied by HID maintainer.
2. Fixes a real bug that affects users? **PASS** — undersized
`input_buf` vs DMA copy of full packets.
3. Important issue? **PASS** — heap overflow / memory corruption, HIGH.
4. Small and contained? **PASS** — +2/-1, one function, one file.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — clean apply to `v6.18.57`;
macro present.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not an ID/quirk/DT/build/docs exception. It is a normal memory-
safety fix.
**Step 9.4: MAKE YOUR DECISION**
Backport. The bug is in this tree, the fix is surgical, and the failure
mode is heap overflow on the Intel QuickSPI input path.
---
## What the commit solves for this tree
On 6.18.57, `quickspi_alloc_report_buf()` sizes `input_buf` to the HID
payload only. RX DMA later copies a full HIDSPI body (`struct
input_report_body_header` + content) into that buffer. At max payload
(or max report descriptor), that is at least a 4-byte heap overflow, and
the DMA length check cannot catch it because hardware buffers are
4K-aligned. Touch IRQ handling is a normal path on Intel THC HID-over-
SPI laptops.
The change allocates `HIDSPI_INPUT_BODY_SIZE(max_input_len)` instead.
That matches how this tree already sizes the output buffer. No new API,
no extra locking, no missing prerequisites.
Risk vs benefit: four extra bytes at probe vs heap corruption on input.
Benefit dominates.
---
## Verification
- [Phase 1] Tags: Even Xu + Jiri Kosina SOBs; no Fixes/Reported-by/Cc:
stable (expected).
- [Phase 2] Diff: `quickspi_alloc_report_buf()` switches `devm_kzalloc`
from `max_input_len` to `HIDSPI_INPUT_BODY_SIZE(max_input_len)`
(+2/-1).
- [Phase 2] `include/linux/hid-over-spi.h`: `HIDSPI_INPUT_BODY_SIZE` =
content + packed 4-byte header.
- [Phase 2] `read_dma_buffer()` copies `mes_len` into `input_buf` with
only `max_packet_size` (`ALIGN(..., SZ_4K)`) as a cap.
- [Phase 3] `git blame` at v6.18.57: alloc from `4138f21115aec`
(v6.15+); still payload-only.
- [Phase 3] `git merge-base --is-ancestor 4138f21115aec v6.18.57` → yes;
`6fcefe71aeb52` already in v6.18.57 (output only).
- [Phase 3] Author Even Xu is MAINTAINERS THC driver maintainer.
- [Phase 4] `b4 dig -c a1cdd72371270640bd357bd3e3b2ec0be17c9536`: v1
series; Kosina applied to hid.git#for-7.3/upstream-fixes.
- [Phase 4] `b4 dig -w`: jikos, bentiss, linux-input CCd.
- [Phase 4] UNVERIFIED: live lore.kernel.org pages (HTTP 403); thread
recovered from mbox.
- [Phase 5] Caller: `quickspi_probe()` → IRQ RXDMA2 →
`thc_rxdma_read(input_buf)`.
- [Phase 6] `git describe HEAD` / Makefile: **6.18.57**. Buggy line
present at v6.18.57; `HIDSPI_INPUT_BODY_SIZE` present; `patch --dry-
run` clean.
- [Phase 8] Failure mode: heap overflow on max-size HID-over-SPI input,
severity HIGH.
- UNVERIFIED: whether this was already discussed on stable@ (lore 403).
**YES**
drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
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 1c96d1d85845c..48387a7341604 100644
--- a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
+++ b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
@@ -549,7 +549,8 @@ static int quickspi_alloc_report_buf(struct quickspi_device *qsdev)
max_input_len = max(le16_to_cpu(qsdev->dev_desc.rep_desc_len),
le16_to_cpu(qsdev->dev_desc.max_input_len));
- qsdev->input_buf = devm_kzalloc(qsdev->dev, max_input_len, GFP_KERNEL);
+ qsdev->input_buf = devm_kzalloc(qsdev->dev,
+ HIDSPI_INPUT_BODY_SIZE(max_input_len), GFP_KERNEL);
if (!qsdev->input_buf)
return -ENOMEM;
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH AUTOSEL 6.18] HID: Intel-thc-hid: Intel-quickspi: Fix buffer overflow
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18] HID: Intel-thc-hid: Intel-quickspi: Fix buffer overflow Sasha Levin
@ 2026-10-19 15:04 ` sashiko-bot
0 siblings, 0 replies; 20+ messages in thread
From: sashiko-bot @ 2026-10-19 15:04 UTC (permalink / raw)
To: Sasha Levin; +Cc: linux-input, dmitry.torokhov
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] HID: quickspi: quickspi_alloc_report_buf() under-sizes input_buf for RXDMA
- [Medium] HID: intel-quickspi: quickspi_dma_init() omits header and rep_desc_len in DMA sizes
--
commit 525db4dc56bd312030200280ce09472abe29a406
Author: Even Xu <even.xu@intel.com>
HID: Intel-thc-hid: Intel-quickspi: Fix buffer overflow
This commit expands the allocation of qsdev->input_buf in
quickspi_alloc_report_buf() using HIDSPI_INPUT_BODY_SIZE() so that it accounts
for the 4-byte HID-over-SPI input body header in addition to the maximum
payload length.
> 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 1c96d1d85845c..48387a7341604 100644
> --- a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
> +++ b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
> @@ -549,7 +549,8 @@ static int quickspi_alloc_report_buf(struct quickspi_device *qsdev)
> max_input_len = max(le16_to_cpu(qsdev->dev_desc.rep_desc_len),
> le16_to_cpu(qsdev->dev_desc.max_input_len));
>
> - qsdev->input_buf = devm_kzalloc(qsdev->dev, max_input_len, GFP_KERNEL);
> + qsdev->input_buf = devm_kzalloc(qsdev->dev,
> + HIDSPI_INPUT_BODY_SIZE(max_input_len), GFP_KERNEL);
[Severity: High]
Can qsdev->input_buf still be overflowed during RXDMA reads in
thc_rxdma_read() -> read_dma_buffer()?
In quickspi_irq_thread_handler(), qsdev->input_buf is passed to
thc_rxdma_read() before quickspi_handle_input_data() validates the packet:
drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c:quickspi_irq_thread_handler() {
...
ret = thc_rxdma_read(qsdev->thc_hw, THC_RXDMA2, qsdev->input_buf,
&input_len, &read_finished);
if (ret) {
err_recover = 1;
goto end;
}
quickspi_handle_input_data(qsdev, input_len);
...
}
However, dma_set_max_packet_size() rounds read_config->max_packet_size up to
SZ_4K, and read_dma_buffer() only checks mes_len against
read_config->max_packet_size before copying into read_buff (qsdev->input_buf):
drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.c:read_dma_buffer() {
...
prd_tbl = &read_config->prd_tbls[prd_table_index];
mes_len = calc_message_len(prd_tbl, &nent);
if (mes_len > read_config->max_packet_size) {
dev_err(dev->dev,
"Message length %zu is bigger than buffer length %lu\n",
mes_len, read_config->max_packet_size);
return -EMSGSIZE;
}
sg = read_config->sgls[prd_table_index];
ret = sg_copy_to_buffer(sg, nent, read_buff, mes_len);
...
}
Because the HIDSPI input report header encodes input_report_len in 4-byte
units (HIDSPI_INPUT_HEADER_REPORT_LEN with THC_UNIT_MICROFRAME_SIZE = 2), even
a compliant device sending a report descriptor or maximum-sized input report
whose length is not a multiple of 4 bytes produces a 4-byte-aligned DMA
transfer that exceeds HIDSPI_INPUT_BODY_SIZE(max_input_len) by 1 to 3 bytes.
Furthermore, any incoming SPI frame with mes_len between
HIDSPI_INPUT_BODY_SIZE(max_input_len) and read_config->max_packet_size will be
copied past the end of qsdev->input_buf before quickspi_handle_input_data()
runs.
[Severity: Medium]
Also, should quickspi_dma_init() be updated to match the buffer sizes computed
here in quickspi_alloc_report_buf()?
Right now, quickspi_dma_init() passes the raw max_input_len and max_output_len
from dev_desc to thc_dma_set_max_packet_sizes():
drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c:quickspi_dma_init() {
...
ret = thc_dma_set_max_packet_sizes(qsdev->thc_hw, 0,
le16_to_cpu(qsdev->dev_desc.max_input_len),
le16_to_cpu(qsdev->dev_desc.max_output_len),
0);
...
}
Since QuickSPI receives both report descriptor responses and input reports
over THC_RXDMA2, if HIDSPI_INPUT_BODY_SIZE(max(rep_desc_len, max_input_len))
exceeds ALIGN(max_input_len, SZ_4K) (for example, when max_input_len is at or
within 3 bytes of a 4K boundary so adding the 4-byte header crosses into the
next 4K page, or when rep_desc_len + 4 > ALIGN(max_input_len, SZ_4K)), won't
the RXDMA2 scatterlist and max_packet_size be too small for the transfer?
Similarly, THC_TXDMA omits HIDSPI_OUTPUT_REPORT_HEADER_SIZE and max_input_len
(used for SET_FEATURE reports in qsdev->report_buf).
> if (!qsdev->input_buf)
> return -ENOMEM;
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261019135441.1420968-326-sashal@kernel.org?part=1
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH AUTOSEL 6.18-5.10] HID: quirks: Add ALWAYS_POLL quirk for Beitong BTP-KP20D dongle
[not found] <20261019135441.1420968-1-sashal@kernel.org>
` (12 preceding siblings ...)
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18] HID: Intel-thc-hid: Intel-quickspi: Fix buffer overflow Sasha Levin
@ 2026-10-19 13:50 ` Sasha Levin
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] HID: i2c-hid: Add i2c-hid-quirk-bad-input-size quirk for 0911:5288 device Sasha Levin
` (2 subsequent siblings)
16 siblings, 0 replies; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:50 UTC (permalink / raw)
To: patches, stable
Cc: Aaron Ma, Jiri Kosina, Sasha Levin, jikos, bentiss, linux-input,
linux-kernel
From: Aaron Ma <mapengyu@gmail.com>
[ Upstream commit bfff246b3a31cb45ec297ca5e2a77c1410b207ac ]
The BTP-KP20D dongle in Direct/HID mode (20dd:5159) re-enumerates every
few seconds because usbhid never submits its interrupt-IN URB: no HID
driver binds to the vendor-specific report descriptor, so the device is
never opened, and the firmware treats the idle endpoint as a lost link.
Add HID_QUIRK_ALWAYS_POLL to keep the interrupt-IN URB submitted from
probe time.
Signed-off-by: Aaron Ma <mapengyu@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This is a device-specific HID quirk for a gamepad dongle that constantly
re-enumerates. The local tree is **5.15.221** (`pending-5.15`);
`HID_QUIRK_ALWAYS_POLL` and the quirk table already exist here.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: [HID] [Add] Add ALWAYS_POLL quirk for Beitong BTP-KP20D dongle
(20dd:5159)
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Signed-off-by: Aaron Ma <mapengyu@gmail.com> (author)
- Signed-off-by: Jiri Kosina <jkosina@suse.com> (HID maintainer)
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, Link:,
or Cc: stable
- Absence of Fixes:/Cc: stable is expected for this review pipeline and
is not a negative signal
- Ignore any pipeline-added Sasha Levin SOB / Upstream commit markers
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: BTP-KP20D in Direct/HID mode (20dd:5159) re-enumerates every few
seconds
- Symptom: USB disconnect/reconnect loop; the dongle is unusable
- Root cause: usbhid does not submit the interrupt-IN URB until the HID
device is opened. Vendor-specific report descriptors do not produce a
bound/opened input client, so the firmware treats the idle endpoint as
a lost link
- Fix: HID_QUIRK_ALWAYS_POLL so the interrupt-IN URB is submitted from
probe/start time
- No kernel-version range stated; this is hardware firmware behavior,
not a regression in a specific kernel commit
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not a disguised cleanup. It is an explicit hardware quirk. The
word “Add” is the normal form for quirk/ID table entries that still fix
real devices.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- drivers/hid/hid-ids.h: +3 (USB_VENDOR_ID_BEITONG 0x20dd,
USB_DEVICE_ID_BEITONG_KP20D 0x5159)
- drivers/hid/hid-quirks.c: +1 (hid_quirks[] entry with
HID_QUIRK_ALWAYS_POLL)
- Functions: none; data-table only
- Scope: single-purpose, two-file, 4-line surgical addition
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: 20dd:5159 is a generic USB HID device with no special quirk.
usbhid_start() does not submit urbin unless a client opens the device
(usbhid_open)
- After: hid_lookup_quirk() returns HID_QUIRK_ALWAYS_POLL.
usbhid_start() (called from hid_hw_start() during hid-generic probe)
calls hid_start_in() immediately and leaves HID_IN_POLLING set so
usbhid_close() does not kill the URB
- Path: probe/start of this one VID:PID, not a global HID change
Step 2.3: IDENTIFY THE BUG MECHANISM
Record: Hardware workaround. Category (h). Firmware requires interrupt-
IN polling to keep the USB link; the kernel only polls after open.
ALWAYS_POLL is the existing mechanism for that class of devices
(mice/keyboards/dongles that disconnect if not polled).
Step 2.4: ASSESS THE FIX QUALITY
Record: Obviously correct. Same pattern as many ALWAYS_POLL entries
already in this tree (8BitDo Pro 3, Edifier QR30, Cooler Master MM712,
ADATA XPG, PixArt mice, etc.). Regression risk is limited to VID 0x20dd
/ PID 0x5159: extra interrupt polling and remote-wakeup flag. That is
the intended tradeoff and is cheaper than a reconnect loop. No API,
locking, or structural change.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record:
- Insertion in hid-ids.h is between BAANTO (9ed326951806c4, 2012) and
BELKIN (a11b3fab94d4fb, 2010)
- Insertion in hid-quirks.c is between ATEN_UC100KM and
CHICONY_MULTI_TOUCH (d5d3e202753cc0, 2017)
- HID_QUIRK_ALWAYS_POLL is BIT(10) in include/linux/hid.h, present since
0b750b3baa2d6 (“HID: usbhid: add always-poll quirk”, 2014-09-08)
- usbhid_start()/usbhid_open()/usbhid_close() already implement
ALWAYS_POLL in this checkout
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. Not a regression in a specific commit; the
device’s firmware misbehaves on the long-standing “poll only when
opened” policy. The policy itself dates to 2014 and is in this 5.15
tree.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record: This tree already contains many ALWAYS_POLL quirk backports,
including:
- f9ad98cff302c HID: quirks: add HID_QUIRK_ALWAYS_POLL for 8BitDo Pro 3
(identical 4-line pattern)
- 16c2ca35257ed Edifier QR30
- 9727b5dc98c33 Cooler Master MM712 dongle
- 5c46ec760d3be ADATA XPG wireless mouse
No Beitong/BTP-KP20D/20dd:5159 history. Standalone, not patch N/M.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Aaron Ma has prior HID work in this tree (i2c-hid Raydium
resume/IRQ, hid_report_len, LG MELF0410). HID maintainer Jiri Kosina
applied the patch. Not a drive-by unknown-subsystem change.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: Depends only on HID_QUIRK_ALWAYS_POLL, hid_quirks[],
hid_lookup_quirk(), and usbhid ALWAYS_POLL handling — all present. Can
apply standalone.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- Message-ID: 20260803053932.5897-1-mapengyu@gmail.com
- b4 mbox retrieved a 2-message thread (lore.kernel.org HTTP 403, so b4
was used instead of WebFetch)
- v1 only; no v2/v3
- Recipients: Jiri Kosina, Benjamin Tissoires, linux-input, linux-kernel
- Jiri Kosina: “Applied, thanks.” (2026-08-03). No NAK, no requested
changes, no stable discussion in-thread
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: Sent to both HID maintainers (Jiri Kosina, Benjamin Tissoires).
Applied by Jiri Kosina. No extra Reviewed-by tags; maintainer apply is
the review signal.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No syzbot/bugzilla link. Description is a concrete hardware
failure (re-enumerate every few seconds). No public multi-user bugzilla
thread found.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Standalone [PATCH], not part of a series. No other Beitong HID
patches in this tree.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: lore.kernel.org/stable WebFetch returned 403. Web search found
no stable-list discussion of this patch. That is consistent with a newly
applied mainline quirk awaiting stable evaluation.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: No functions modified. Data consumed by hid_gets_squirk() /
hid_lookup_quirk().
Step 5.2: TRACE CALLERS
Record:
- hid_lookup_quirk() is called from usbhid_parse() and
hid_device_probe()
- hid-generic matches HID_ANY_ID and hid_generic_probe() calls
hid_hw_start()
- hid_hw_start() -> usbhid_start() -> if ALWAYS_POLL: hid_start_in()
- usbhid_open()/usbhid_close() skip starting/stopping the in-URB when
ALWAYS_POLL is set
- Context: USB device enumeration / HID probe, not a hot syscall path
for other devices
Step 5.3: TRACE CALLEES
Record: The new table entry does not call anything. ALWAYS_POLL path
uses usb_autopm_get_interface, hid_start_in, and sets
needs_remote_wakeup — existing usbhid code.
Step 5.4: FOLLOW THE CALL CHAIN
Record: Plugging in 20dd:5159 -> usbhid_probe -> hid_add_device -> hid-
generic probe -> hid_hw_start -> usbhid_start. Userspace-reachable by
inserting the dongle. Without the quirk the device resets every few
seconds even if nothing opens it.
Note: the commit text says “no HID driver binds.” hid-generic still
matches HID_ANY_ID; the precise failure is that the device is never
opened, so urbin is never submitted. ALWAYS_POLL is still the correct
existing fix for that.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Dozens of HID_QUIRK_ALWAYS_POLL entries already in
drivers/hid/hid-quirks.c in this tree. Same bug class (dongle/mouse
disconnects if interrupt-IN is idle).
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: Yes. usbhid still starts interrupt-IN only on open unless
ALWAYS_POLL is set. 20dd:5159 is not in hid-ids.h or hid-quirks.c. USB
vendor 0x20dd is not used as a HID ID here (only unrelated 0x20dd hits
in qla2xxx debug ids, ralink USB product 0x0471:0x20dd, GPU register
offsets). The firmware bug is independent of kernel version; 5.15 users
with this dongle hit it.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Clean apply. Local hid-ids.h has BAANTO then BELKIN; local hid-
quirks.c has ATEN_UC100KM then CHICONY_MULTI_TOUCH. No BEITONG symbols
to conflict with. Expected difficulty: clean apply.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: No Beitong fix present. Generic ALWAYS_POLL infrastructure is
present. No alternate workaround for 20dd:5159.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: HID / USB HID (drivers/hid). IMPORTANT for users of this
controller; PERIPHERAL in the sense that only one VID:PID is affected.
Not staging.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Mature and actively backported here (recent HID race/overflow
fixes, plus ongoing quirk-ID additions). HID CORE maintainers: Jiri
Kosina, Benjamin Tissoires.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Driver-specific / device-specific. Only USB 20dd:5159 (Beitong
BTP-KP20D Direct/HID mode). No effect on other HID devices.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Trigger is plugging in the dongle in Direct/HID mode. Common for
owners of that hardware; not a rare race. Unprivileged user can trigger
it by using the device. Happens every few seconds until unplugged.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: Repeated USB re-enumeration; device unusable; USB reconnect
noise. Not a kernel oops/UAF. Severity MEDIUM-HIGH for affected users
(hardware does not work), LOW blast radius.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: makes this dongle usable on 5.15; same class of quirks
already shipped in this tree
- Risk: very low (4 lines, one VID:PID, existing quirk bit)
- Ratio: strongly favorable
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Real hardware failure: reconnect loop every few seconds
- Established HID_QUIRK_ALWAYS_POLL mechanism, present since 2014 in
this tree
- Textbook stable exception: hardware quirk / device ID on an existing
driver
- 4-line table addition, no APIs, no refactor
- Applies cleanly to 5.15.221
- HID maintainer applied it
- Identical ALWAYS_POLL ID additions (e.g. 8BitDo Pro 3) already live in
this tree
AGAINST:
- Affects one gamepad dongle, not a core crash
- No syzbot/CVE/multi-user bugzilla trail
- Commit message slightly overstates “no HID driver binds”
UNRESOLVED:
- Could not HTTP-fetch lore.kernel.org (403); thread recovered via b4
mbox
- Could not query lore.kernel.org/stable (403); no evidence of an
explicit stable NAK
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? PASS — table entry using existing
quirk; maintainer applied
2. Fixes a real bug that affects users? PASS — dongle re-enumerates and
is unusable
3. Important issue? PASS — hardware-unusable reconnect loop (quirk
exception; not a kernel panic)
4. Small and contained? PASS — 4 lines, two files
5. No new features or APIs? PASS — no new Kconfig, sysfs, or userspace
ABI; quirk bit already exists
6. Can apply to the local tree? PASS — insertion context present;
ALWAYS_POLL implemented
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: Hardware quirk/workaround plus device ID addition to an existing
driver. Both are automatic-qualify exceptions in the stable rules given
above.
Step 9.4: MAKE YOUR DECISION
Backport. The local 5.15 tree already has the ALWAYS_POLL machinery and
routinely takes this exact class of HID quirk. The patch is the minimal,
device-scoped fix for a dongle that otherwise cannot stay on the bus.
===============================================================
What the commit solves for stable users
===============================================================
On 5.15, usbhid still submits the interrupt-IN URB only when a HID
client opens the device. The BTP-KP20D firmware treats an idle interrupt
endpoint as a lost link and resets, so Direct/HID mode never stays
enumerated. HID_QUIRK_ALWAYS_POLL already starts that URB in
usbhid_start(); this commit only names 20dd:5159 so that path runs. That
is the same fix already used here for 8BitDo, Edifier, Cooler Master,
and many PixArt mice.
Risk vs benefit: benefit is a working controller for anyone on this LTS
tree with that dongle; risk is polling one extra interrupt endpoint on
that VID:PID only.
Concerns: none material. No missing prerequisites. No backport rewrite
needed.
===============================================================
Verification
===============================================================
- [Phase 1] Parsed subject/tags: Add ALWAYS_POLL; SOBs Aaron Ma + Jiri
Kosina; no Fixes/Reported-by/Cc: stable
- [Phase 2] Diff: +3 hid-ids.h, +1 hid-quirks.c; no function bodies
- [Phase 2] Local usbhid_start() at hid-core.c:1183 already implements
ALWAYS_POLL via hid_start_in()
- [Phase 3] git describe HEAD / make kernelversion:
p-5.15-2-g9a29d9b0f9507, 5.15.221, branch pending-5.15
- [Phase 3] git blame include/linux/hid.h:373: HID_QUIRK_ALWAYS_POLL
BIT(10) present
- [Phase 3] git log -S HID_QUIRK_ALWAYS_POLL -- drivers/hid/usbhid/hid-
core.c include/linux/hid.h: introduced by 0b750b3baa2d6 (2014)
- [Phase 3] git grep USB_VENDOR_ID_BEITONG / BTP-KP20D: absent in this
tree
- [Phase 3] git grep 0x20dd: no HID vendor collision
- [Phase 3] Precedent already in this tree: f9ad98cff302c (8BitDo
ALWAYS_POLL, same 4-line shape)
- [Phase 4] b4 mbox 20260803053932.5897-1-mapengyu@gmail.com: 2
messages, v1 only, Jiri “Applied, thanks.”
- [Phase 4] WebFetch lore.kernel.org: 403; used b4 instead
- [Phase 5] Call chain: hid_lookup_quirk -> hid-generic_probe ->
hid_hw_start -> usbhid_start
- [Phase 6] Insertion points exist: hid-ids.h BAANTO then BELKIN; hid-
quirks.c ATEN_UC100KM then CHICONY_MULTI_TOUCH
- [Phase 7] MAINTAINERS: HID CORE LAYER, Jiri Kosina / Benjamin
Tissoires
- [Phase 8] Failure mode: USB re-enumeration loop, device-specific,
severity MEDIUM-HIGH for that hardware
- UNVERIFIED: stable@ mailing-list archive (lore 403); no evidence this
was rejected for stable
**YES**
drivers/hid/hid-ids.h | 3 +++
drivers/hid/hid-quirks.c | 1 +
2 files changed, 4 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index a9db2b30be9bd..c1a7f5558ccd1 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -262,6 +262,9 @@
#define USB_VENDOR_ID_BAANTO 0x2453
#define USB_DEVICE_ID_BAANTO_MT_190W2 0x0100
+#define USB_VENDOR_ID_BEITONG 0x20dd
+#define USB_DEVICE_ID_BEITONG_KP20D 0x5159
+
#define USB_VENDOR_ID_BELKIN 0x050d
#define USB_DEVICE_ID_FLIP_KVM 0x3201
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 9d18b962e0ea6..3de594ee25c38 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -45,6 +45,7 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM), HID_QUIRK_NOGET },
+ { HID_USB_DEVICE(USB_VENDOR_ID_BEITONG, USB_DEVICE_ID_BEITONG_KP20D), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH), HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE2), HID_QUIRK_ALWAYS_POLL },
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH AUTOSEL 6.18-5.10] HID: i2c-hid: Add i2c-hid-quirk-bad-input-size quirk for 0911:5288 device
[not found] <20261019135441.1420968-1-sashal@kernel.org>
` (13 preceding siblings ...)
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] HID: quirks: Add ALWAYS_POLL quirk for Beitong BTP-KP20D dongle Sasha Levin
@ 2026-10-19 13:50 ` Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-6.6] HID: logitech-hidpp: Add support for G502 X Plus USB mouse Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18] HID: wacom: avoid copying Bluetooth input reports Sasha Levin
16 siblings, 0 replies; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:50 UTC (permalink / raw)
To: patches, stable
Cc: Youth Cao, Jiri Kosina, Sasha Levin, jikos, bentiss, linux-input,
linux-kernel
From: Youth Cao <cocoh2os08@gmail.com>
[ Upstream commit 58d97b45f3f43af0afd9c74e8480d22d36fd3f72 ]
I have recently acquired a cheap Apollo Lake-based laptop that uses a
Hynitron CST128-A touchpad controller. While booting from a Debian LiveCD,
the kernel log is flooded with the following error (though the touchpad
works well):
i2c_hid_acpi i2c-ALPS0001:00: i2c_hid_get_input: incomplete report (27/42405)
The CST128-A was identified via ACPI as ALPS0001:00, and the I2C HID
device ID (0911:5288) was shared with the Hantick 5288.
Add the I2C_HID_QUIRK_BAD_INPUT_SIZE quirk option to the existing Hantick
5288 quirk entry to suppress the kernel log flood.
Signed-off-by: Youth Cao <cocoh2os08@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Local tree is **6.18.57** (`v6.18.57-155-gcdf239ca885b2`). This is a
one-line HID i2c-hid hardware quirk for device `0911:5288`. The quirk
table, `I2C_HID_QUIRK_BAD_INPUT_SIZE`, and the Hantick 5288 entry are
all already in this tree.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: **[HID/i2c-hid] [Add] hardware quirk
`I2C_HID_QUIRK_BAD_INPUT_SIZE` for I2C HID ID 0911:5288 (Hantick 5288 /
Hynitron CST128-A)**
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- **Fixes:** none (expected for this review)
- **Reported-by:** none (author is the reporter: “I have recently
acquired…”)
- **Tested-by:** none
- **Reviewed-by:** none on the commit
- **Acked-by:** none
- **Link:** none on the commit; lore thread recovered via `b4 dig`
- **Cc: stable:** none (expected)
- **Signed-off-by:** Youth Cao (author); Jiri Kosina (HID maintainer,
applied it)
- Ignore pipeline SOBs/Upstream markers as instructed
Notable: HID maintainer SOB. Single reporter, real hardware.
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- **Bug:** Hynitron CST128-A touchpad (ACPI `ALPS0001:00`, I2C HID ID
`0911:5288`) reports a bogus input length.
- **Symptom:** kernel log flooded with `i2c_hid_get_input: incomplete
report (27/42405)`. Touchpad still works.
- **Root cause:** device writes an invalid HID input length (42405 =
`0xA5A5`) while `wMaxInputLength` is 27.
- **Fix:** OR `I2C_HID_QUIRK_BAD_INPUT_SIZE` onto the existing Hantick
5288 quirk so the driver uses max input length instead of dropping the
report and calling unratelimited `dev_err()`.
- **Version info:** none in the message. Hardware is cheap Apollo Lake
laptops; driver support for this ID dates to 2017.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Not a disguised cleanup. Explicit hardware quirk. Same class as
USB/PCI/codec quirks that stable already takes.
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- **File:** `drivers/hid/i2c-hid/i2c-hid-core.c` — 1 insertion, 1
deletion
- **Function / data:** `i2c_hid_quirks[]` table, Hantick 5288 entry
- **Scope:** single-file, one-line surgical quirk
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- **Before:** `0911:5288` only has `I2C_HID_QUIRK_NO_IRQ_AFTER_RESET`.
In `i2c_hid_get_input()`, if `ret_size > size || ret_size <
sizeof(__le16)`, the IRQ path logs `incomplete report` via `dev_err()`
(not ratelimited) and **returns without delivering the HID report**.
- **After:** same ID also has `I2C_HID_QUIRK_BAD_INPUT_SIZE`. On a bad
size, the driver overwrites the length prefix with `size`
(`min(wMaxInputLength, bufsize)`) and continues into
`hid_safe_input_report()`.
- **Path:** IRQ handler (`i2c_hid_irq` → `i2c_hid_get_input`), not
probe/error-init. Only this VID/PID.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- **Category:** hardware workaround (quirk table)
- **Mechanism:** device reports garbage length (`0xA5A5` / 42405).
Without the quirk, every such IRQ logs and drops the report. The quirk
is the existing BAD_INPUT_SIZE path added in 2019 for Lenovo Y720.
Verified BAD_INPUT_SIZE handler in this tree:
```561:570:drivers/hid/i2c-hid/i2c-hid-core.c
if (ret_size > size || ret_size < sizeof(__le16)) {
if (ihid->quirks & I2C_HID_QUIRK_BAD_INPUT_SIZE) {
*(__le16 *)ihid->inbuf = cpu_to_le16(size);
ret_size = size;
} else {
dev_err(&ihid->client->dev,
"%s: incomplete report (%d/%d)\n",
__func__, size, ret_size);
return;
```
`size` is already capped to `ihid->bufsize`, so forcing `ret_size =
size` does not overflow the input buffer.
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Obviously correct: one flag on an existing table entry; handler
already used by Lenovo Y720 (`USB_VENDOR_ID_ITE` / Legion Y720) in
this tree.
- Minimal, no API/refactor.
- **Regression risk:** low. Quirk only runs when the length is already
invalid. Well-formed reports for other 0911:5288 boards (Cube Thinker,
EZBook 3 Pro, T-bao, etc. from Hans de Goede’s 2017 commit) are
unchanged. Worst case on a truly truncated packet is processing a
padded report instead of dropping it — same as Y720 since 2019.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record:
- Hantick 5288 table entry introduced by **402946a8ef71e** (Hans de
Goede, 2017-11-07): `HID: i2c-hid: Add no-irq-after-reset quirk for
0911:5288 device`. Present in **v6.18.57**.
- `I2C_HID_QUIRK_BAD_INPUT_SIZE` introduced by **fd09137687016** (Pavel
Balan, 2019-11-27) for Lenovo Y720 incomplete-report flood. Present in
**v6.18.57**.
- Buggy combination (Hantick ID without BAD_INPUT_SIZE) has been in-tree
for years.
Step 3.2: FOLLOW THE FIXES: TAG
Record: No `Fixes:` tag. Not applicable. The “broken” state is hardware,
not a recent kernel regression.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record:
- Same-file relatives: `fd09137687016` (Y720 BAD_INPUT_SIZE),
`402946a8ef71e` (Hantick NO_IRQ_AFTER_RESET), `fb6acf76c3fdd` (Raydium
incomplete-report flood).
- Not a numbered series. Standalone v1.
- Prerequisite code (quirk bit + table entry + handler) is in this tree.
No missing helpers.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Youth Cao has only this commit under `drivers/hid/i2c-hid/`
here. Not the maintainer. Applied by Jiri Kosina, HID maintainer.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: None beyond 2017/2019 infrastructure already in 6.18.57.
Standalone one-liner.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- `b4 dig -c 58d97b45f3f43af0afd9c74e8480d22d36fd3f72` →
https://patch.msgid.link/20260903161444.786-1-cocoh2os08@gmail.com
- `b4 dig -a`: **v1 only** (2026-09-04). Applied as submitted.
- Thread: author submission; sashiko-bot flag of an **unrelated pre-
existing DMA** issue in `i2c_hid_fetch_hid_descriptor()`; Jiri Kosina
“Applied, thanks.” (2026-09-11).
- No NAK, no request for v2, no stable nomination in review.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record (`b4 dig -w`): To/Cc included Jiri Kosina, Benjamin Tissoires,
linux-input, linux-kernel. Maintainer applied it. No extra Reviewed-by.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: The patch *is* the bug report. One user, Debian LiveCD, Apollo
Lake + CST128-A. Concrete log line. Author says the touchpad “works
well” aside from the flood.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: Standalone. Not 2/N. No sibling patches required.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: Web search of lore.kernel.org/stable for this subject/ID found
no prior stable discussion (lore HTTP 403 from this environment;
openwall/lkml used instead). **UNVERIFIED** that nobody requested it on
stable@, but nothing found arguing against it.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: No function body changed. Data only: `i2c_hid_quirks[]`. Runtime
effect is in `i2c_hid_lookup_quirk()` and `i2c_hid_get_input()`.
Step 5.2: TRACE CALLERS
Record:
- `i2c_hid_lookup_quirk()` called from `__i2c_hid_core_probe()`
(`ihid->quirks = ...`) — device probe, once per device.
- `i2c_hid_get_input()` called from `i2c_hid_irq()` — interrupt context,
every input IRQ.
- Impact surface: only VID/PID 0911:5288.
Step 5.3: TRACE CALLEES
Record: After the quirk, path continues to `hid_safe_input_report()`
(present in v6.18.57). Input buffer already sized; length forced to
`size ≤ bufsize`.
Step 5.4: FOLLOW THE CALL CHAIN
Record: ACPI I2C HID enumeration (`i2c-hid-acpi`) → probe → IRQ on
touchpad activity. Reachable on real laptops without special syscalls.
`CONFIG_I2C_HID` is `default y`; `I2C_HID_ACPI` is the usual x86 laptop
path.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Same quirk already used for Lenovo Legion Y720. Same “incomplete
report” flood class previously fixed (Y720, Raydium). Pattern is
established, not experimental.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: **Yes.** At v6.18.57:
```
{ I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288,
I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
```
IDs in `drivers/hid/hid-ids.h`: `I2C_VENDOR_ID_HANTICK 0x0911`,
`I2C_PRODUCT_ID_HANTICK_5288 0x5288`. BAD_INPUT_SIZE bit and handler
exist. Bug introduced with this hardware + the 2017 ID match, not after
6.18 branched.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: **Minor context only.** `git apply --check` of the stored hunk
onto v6.18.57 fails because context includes the later Yoga Slim 7x
keyboard quirk line
(`I2C_DEVICE_ID_ITE_LENOVO_YOGA_SLIM_7X_G11_KEYBOARD`), which is **not**
in v6.18.57. The Hantick line itself matches. A 1-line context tweak
applies cleanly. Not a semantic rework.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: Y720 BAD_INPUT_SIZE is present. Nothing else already adds
BAD_INPUT_SIZE for 0911:5288 at v6.18.57. No alternate fix.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: **HID / i2c-hid** (`drivers/hid/i2c-hid/`). **IMPORTANT** for
laptop input (touchpads/touchscreens), not core mm/fs. Peripheral in the
sense of one cheap-laptop ID, but i2c-hid itself is common.
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Actively maintained (Dell S4, Elan panel, QTEC, Goodix, buffer
overflow fixes in recent 6.18 history). Quirk table is a mature, long-
lived mechanism.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Driver/hardware-specific. Users of I2C HID `0911:5288` (Hantick
5288 clones, Hynitron CST128-A on cheap Apollo Lake laptops).
`CONFIG_I2C_HID` / `I2C_HID_ACPI`.
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Touchpad IRQs that carry a bogus length. Author saw it at boot
on a Debian LiveCD, so it is not rare-on-error-only for this hardware.
Unprivileged users generate IRQs by using the pad; they cannot change
the VID/PID. Not a security trigger.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record:
- **Failure mode:** unratelimited `dev_err()` from IRQ context →
dmesg/journal flood; those reports are dropped.
- **Severity:** **MEDIUM** as a log flood; can still hurt (console spam,
log wrap, hiding other messages). Not oops/deadlock/corruption. Author
says the pad still works, so some reports are valid.
- Hardware-quirk exception still applies.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- **Benefit:** medium for affected hardware (stops flood; may deliver
reports that were dropped). Low for everyone else (no code path
change).
- **Risk:** very low (1 line, existing quirk, ID-matched).
- **Ratio:** favorable. Classic stable quirk.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
**FOR:**
- Real hardware, real user log, concrete `incomplete report (27/42405)`.
- Existing quirk infrastructure in 6.18.57; same pattern as Y720 (2019).
- One line, ID-scoped, no new API.
- HID maintainer applied v1 with no objections.
- Unratelimited `dev_err` in IRQ is a real nuisance on these machines.
- Stable exception: hardware quirk on an existing driver.
**AGAINST:**
- Not a crash, UAF, or data-corruption fix; author says the touchpad
already works.
- Applies to every 0911:5288, not only CST128-A/ALPS0001 (mitigated:
quirk inert on valid lengths).
- Naive apply onto bare v6.18.57 needs a tiny context tweak (Yoga Slim
line).
**UNRESOLVED:**
- Could not fetch lore.kernel.org (HTTP 403); used `b4 dig` mbox +
Openwall/LKML.
- No stable@ thread found; absence not treated as a negative.
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? **PASS** — one flag; author tested on
the laptop; maintainer applied.
2. Fixes a real bug that affects users? **PASS** — log flood + dropped
bad-size reports on real hardware.
3. Important issue? **PASS** under the hardware-quirk exception;
severity MEDIUM, not CRITICAL.
4. Small and contained? **PASS** — 1 line, one table entry.
5. No new features or APIs? **PASS** — reuses
`I2C_HID_QUIRK_BAD_INPUT_SIZE`.
6. Can apply to the local tree? **PASS** — code exists in 6.18.57; at
most a context-line adjustment.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: **Hardware quirk/workaround** on an existing i2c-hid quirk
table. Explicitly in-scope for stable.
Step 9.4: MAKE YOUR DECISION
This should be backported to this 6.18.y tree. The buggy Hantick entry
and BAD_INPUT_SIZE handler are already here. The change is the standard
way this driver papers over broken input-length hardware.
What it solves for stable users: cheap Apollo Lake machines with
0911:5288 (Hynitron CST128-A / Hantick clones) stop flooding the log on
every bad-sized HID IRQ, matching the Y720 precedent.
Risk vs benefit: very low risk, localized benefit, no prerequisites
missing.
Concerns: trivial hunk-context conflict with the Yoga Slim quirk line if
applying the mainline diff onto unmodified v6.18.57; the Hantick line
itself does not need rework.
Verification:
- [Phase 1] Parsed subject/tags/body from `git show 245d6017beff2` /
upstream `58d97b45f3f4`; no Fixes/Reported-by/Cc:stable; SOB Youth Cao
+ Jiri Kosina
- [Phase 2] Diff is 1 line in `i2c_hid_quirks[]`; handler at
`i2c_hid_get_input()` lines 561–570 verified; `size` capped to
`bufsize` at 532–533
- [Phase 2] 42405 == 0xA5A5 verified arithmetically
- [Phase 3] `git merge-base --is-ancestor 402946a8ef71e v6.18.57` YES;
`fd09137687016` YES; this commit NOT in v6.18.57
- [Phase 3] `git blame -L 120,145 v6.18.57 --
drivers/hid/i2c-hid/i2c-hid-core.c`: Hantick entry from 402946a8ef71e
/ 67b18dfb8cfc6d
- [Phase 3] Author `git log --author='Youth Cao'` only this i2c-hid
commit
- [Phase 4] `b4 dig -c 58d97b45f3f4` → msgid 20260903161444.786-1; `-a`
v1 only; `-w` Kosina + Tissoires + linux-input; `-m` 3-message mbox
- [Phase 4] Openwall: Jiri Kosina “Applied, thanks.”; sashiko-bot pre-
existing DMA note unrelated
- [Phase 4] lore.kernel.org WebFetch 403; stable@ search found no
discussion of this ID
- [Phase 5] `git grep` callers: lookup at probe 1073; get_input from
`i2c_hid_irq` 592
- [Phase 5] `hid_safe_input_report` ancestor of v6.18.57: YES
- [Phase 6] `make kernelversion` / Makefile: 6.18.57; Hantick IDs in
v6.18.57 `hid-ids.h` 646–647
- [Phase 6] `git apply --check` of the stored hunk onto v6.18.57 fails
on Yoga Slim context line; Hantick source line identical
- [Phase 7] Kconfig: `I2C_HID` default y; `I2C_HID_ACPI` for this ACPI
path
- [Phase 8] Failure mode: IRQ `dev_err` flood + dropped reports; not
oops
- UNVERIFIED: full lore.kernel.org HTML thread (403); whether any
0911:5288 unit is harmed by processing bad-size frames (no reports
found)
**YES**
drivers/hid/i2c-hid/i2c-hid-core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index 29c4f624f3c5c..e5a4c7deba502 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -123,7 +123,7 @@ static const struct i2c_hid_quirks {
__u32 quirks;
} i2c_hid_quirks[] = {
{ I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288,
- I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
+ I2C_HID_QUIRK_NO_IRQ_AFTER_RESET | I2C_HID_QUIRK_BAD_INPUT_SIZE },
{ I2C_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_VOYO_WINPAD_A15,
I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
{ I2C_VENDOR_ID_RAYDIUM, I2C_PRODUCT_ID_RAYDIUM_3118,
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH AUTOSEL 6.18-6.6] HID: logitech-hidpp: Add support for G502 X Plus USB mouse
[not found] <20261019135441.1420968-1-sashal@kernel.org>
` (14 preceding siblings ...)
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] HID: i2c-hid: Add i2c-hid-quirk-bad-input-size quirk for 0911:5288 device Sasha Levin
@ 2026-10-19 13:51 ` Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18] HID: wacom: avoid copying Bluetooth input reports Sasha Levin
16 siblings, 0 replies; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:51 UTC (permalink / raw)
To: patches, stable
Cc: Stuart Hayhurst, Bastien Nocera, Jiri Kosina, Sasha Levin, jikos,
bentiss, linux-input, linux-kernel
From: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
[ Upstream commit 6f4b44abe4ccdcfdab75c9493b8c7634fee37133 ]
The wireless dongle is already supported, this adds detection for
the mouse in wired mode. Supports battery reporting.
Signed-off-by: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
Reviewed-by: Bastien Nocera <hadess@hadess.net>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The local checkout is **pending-5.15** (kernel **5.15.221**). This is a
two-line USB ID addition to an existing HID++ driver, which stable rules
explicitly allow.
## Phase 1: Commit message forensics
**Step 1.1: Subject line**
Record: **[HID / logitech-hidpp] [Add] [USB detection for G502 X Plus
wired mouse]**
**Step 1.2: Tags**
Record:
- Signed-off-by: Stuart Hayhurst \<stuart.a.hayhurst@gmail.com\>
(author)
- Reviewed-by: Bastien Nocera \<hadess@hadess.net\> (HID++ reviewer)
- Signed-off-by: Jiri Kosina \<jkosina@suse.com\> (HID maintainer)
- No Fixes: tag (expected)
- No Cc: stable (expected)
- No Reported-by / Tested-by / Link:
- Ignore any pipeline “Upstream commit” / Sasha Levin SOB if present
**Step 1.3: Body**
Record: [Bug/gap: G502 X Plus is detected on the Lightspeed dongle but
not when plugged in over USB.] [Symptom: no HID++ binding in wired mode,
so no kernel battery reporting.] [No version range in the message.]
[Root cause: missing `HID_USB_DEVICE(..., 0xC095)` in
`hidpp_devices[]`.]
**Step 1.4: Hidden bug fix?**
Record: Not a disguised leak/race fix. It is a **new device ID** for
existing driver code.
## Phase 2: Diff analysis
**Step 2.1: Inventory**
Record: `drivers/hid/hid-logitech-hidpp.c` only; **+2 / -0**. Function:
`hidpp_devices[]` ID table. Scope: single-file surgical ID add.
**Step 2.2: Code flow**
Record: Before: USB `046d:c095` is not matched by logitech-hidpp and is
handled by hid-generic (mouse works; no HID++ battery). After:
`hidpp_probe()` binds with `driver_data = 0` (same as G403/G703/G903 USB
entries). Path: device enumeration / probe, not an error path.
**Step 2.3: Bug mechanism**
Record: **Hardware ID / quirk table (h).** Missing product ID; adding
`HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC095)`.
**Step 2.4: Fix quality**
Record: Obviously correct; matches neighboring Lightspeed USB mice. No
API, locking, or structure change. Regression risk is low; the 2019 G502
revert was for **different** PIDs (Hero/Proteus 0xC07D/0xC332/0xC08B),
not this Lightspeed X device.
## Phase 3: Git history
**Step 3.1: Blame**
Record: USB HID++ IDs in this tree come from `91cf9a98ae4127` (2019) and
`27fc32fd941796` (2019), plus G915 TKL `fd41646d43504` (backported
2023). Table has been stable for years.
**Step 3.2: Fixes: tag**
Record: None. This does not revert a bug-introducing commit; it adds an
ID.
**Step 3.3: Related file history**
Record: Related mainline IDs: `a343a7682acc5` (G502 Lightspeed 0xC08D,
2023) and `fce551616dfa4` (G502 X Lightspeed 0xC098, 2026). Neither is
in this tree. Not a numbered series; standalone v1. Same-author
companion `456d506b6041d` (duplicate G703 ID) is unrelated cleanup.
**Step 3.4: Author**
Record: Stuart Hayhurst is a regular HID++ ID contributor. Same
author/reviewer pair already landed G915 TKL IDs in **this** 5.15 tree
(`fd41646d43504`).
**Step 3.5: Dependencies**
Record: No new helpers. Needs existing `hidpp_devices[]` /
`HID_USB_DEVICE` / battery init. Unified Battery 0x1004
(`e037acf0b1aed`) **is** an ancestor of this tree. G502 Lightspeed
0xC08D is only nearby context, not a functional prerequisite.
Standalone.
## Phase 4: Mailing list / external
**Step 4.1: Original discussion**
Record: `b4 dig -c 6f4b44abe4ccd` → https://patch.msgid.link/20260721171
246.461232-5-stuart.a.hayhurst@gmail.com
`b4 dig -a`: **v1 only**. Thread: Bastien `Reviewed-by`; Jiri “Applied,
thanks.” No NAK, no stable concern.
**Step 4.2: Recipients (`b4 dig -w`)**
Record: Jiri Kosina, Benjamin Tissoires, Bastien Nocera, Filipe Laíns,
linux-input, linux-kernel.
**Step 4.3: Bug report**
Record: No syzbot/bugzilla. Author describes wired detection + battery.
Libratbag also lists G502 X Plus wired 0xC095 (external confirmation of
the PID).
**Step 4.4: Series**
Record: Subject is `[PATCH]`, not `X/Y`. Later G502 X Lightspeed ID
(`fce551616dfa4`) is a separate author/date.
**Step 4.5: stable@**
Record: lore.kernel.org WebFetch returned 403. UNVERIFIED on stable@
archives. `Documentation/process/stable-kernel-rules.rst` line 24: “New
device IDs and quirks are also accepted.”
## Phase 5: Semantic / call graph
**Step 5.1: Functions**
Record: `hidpp_devices[]` only. Consumed by `hidpp_driver.id_table` →
`hidpp_probe()`.
**Step 5.2: Callers**
Record: HID core match → `hidpp_probe()` → `hidpp_connect_event()` →
`hidpp_initialize_battery()`. Userspace-visible on USB plug-in.
**Step 5.3: Callees**
Record: Unchanged. Battery path already tries 0x1000, then 0x1004, then
0x1001.
**Step 5.4: Reachability**
Record: Yes, from plugging the mouse in over USB. Unprivileged physical
access; not a syscall fuzzer path.
**Step 5.5: Similar patterns**
Record: Same pattern as G403/G703/G903 USB IDs already here, and G915
TKL already backported here.
## Phase 6: This tree (5.15.221)
**Step 6.1: Does the gap exist?**
Record: Yes. `hidpp_devices[]` around `drivers/hid/hid-logitech-
hidpp.c:4354` has G403 `0xC082` then G703 `0xC087`. **No `0xC095`.**
`git merge-base --is-ancestor 6f4b44abe4ccd HEAD` → not ancestor.
Wireless still covered by `LDJ_DEVICE(HID_ANY_ID)` at line 4338.
**Step 6.2: Backport difficulty**
Record: **Minor context tweak.** Upstream hunk sits after G502
Lightspeed `0xC08D`, which is not in 5.15. Insert after G403 / before
G703. Two lines.
**Step 6.3: Related fixes already here?**
Record: No `0xC095`. G915 TKL IDs are present (same class of HID++ ID
add). Unified Battery is present.
## Phase 7: Subsystem
**Step 7.1:** Record: **HID / logitech-hidpp**. Criticality:
**IMPORTANT** (common USB HID, not core mm/net).
`CONFIG_HID_LOGITECH_HIDPP`.
**Step 7.2:** Record: Mature driver; ID table is the usual extension
point. Still receiving stable HID++ fixes on this branch.
## Phase 8: Impact / risk
**Step 8.1:** Record: **driver-specific / hardware-specific** — Logitech
G502 X Plus in **wired USB** mode.
**Step 8.2:** Record: Trigger = plug in with cable. Common for
charging/wired use. Not remotely triggerable.
**Step 8.3:** Record: Without the ID, generic HID still moves the
cursor. With the ID, HID++ battery sysfs works. Severity **MEDIUM** as a
bug, but this is the **device-ID exception**, not a crash fix.
**Step 8.4:** Record: Benefit: battery/HID++ for a shipping 2022 mouse
on 5.15 LTS. Risk: very low (2 lines, no quirks). Same shape as G915 TKL
already on this tree. Ratio: **favorable**.
## Phase 9: Synthesis
**Evidence FOR**
- Stable rules explicitly accept new device IDs (`stable-kernel-
rules.rst`).
- Driver and battery stack (including 0x1004) exist in 5.15.221.
- +2 lines, no new API, no quirks.
- Reviewed by Bastien Nocera; applied by Jiri Kosina.
- Precedent on this tree: G915 TKL USB/BT IDs (`fd41646d43504`), same
author, same “battery on top of hid-generic” rationale.
- 0xC095 is unused by other HID drivers here.
**Evidence AGAINST**
- Not a crash/UAF/security fix; mouse already works via hid-generic.
- 2019 G502 USB IDs were reverted for timeouts — **different PIDs**.
- Hunk context needs a tiny edit because 0xC08D is missing.
**Unresolved**
- Could not fetch lore/stable HTML (403). Thread recovered via `b4`
mbox.
- Did not physically test a G502 X Plus on 5.15.
**Stable rules checklist**
1. Obviously correct and tested? **PASS** (trivial ID; author + HID++
reviewer).
2. Fixes a real user-visible gap? **PASS** (wired HID++/battery).
3. Important? **PASS** under the device-ID exception (not a panic).
4. Small and contained? **PASS** (+2 lines, one table).
5. No new features/APIs? **PASS** (existing probe/battery only).
6. Applies to this tree? **PASS** with trivial context adjust.
**Exception category:** New USB device ID on an existing driver.
This belongs on 5.15.y: the hardware is real, the driver already handles
this class of Lightspeed USB mice, and the change is the same kind of ID
add this tree has already taken.
Verification:
- [Phase 1] Tags: author SOB, Bastien Reviewed-by, Jiri SOB; no Fixes/Cc
stable
- [Phase 2] Diff: +2 lines in `hidpp_devices[]`, USB 0xC095, no quirks
- [Phase 3] Mainline SHA `6f4b44abe4ccdcfdab75c9493b8c7634fee37133`; not
ancestor of HEAD
- [Phase 3] Unified Battery `e037acf0b1aed` **is** ancestor of HEAD
- [Phase 3] G502 Lightspeed `a343a7682acc5` is **not** in this tree
(context only)
- [Phase 4] `b4 dig -c 6f4b44abe4ccd`: lore match; v1 only; Reviewed-by
+ Applied
- [Phase 4] WebFetch lore/stable: 403; thread read from
`/tmp/g502xplus.mbox`
- [Phase 5] ID table → `hidpp_probe` → `hidpp_initialize_battery`
(0x1000/1004/1001)
- [Phase 6] `git describe HEAD`: p-5.15-2-g9a29d9b0f9507; `make
kernelversion`: 5.15.221; branch pending-5.15
- [Phase 6] No 0xC095 in `hidpp_devices[]`; `LDJ_DEVICE(HID_ANY_ID)`
present
- [Phase 6] G915 TKL IDs already backported here (`fd41646d43504`)
- [Phase 7] `CONFIG_HID_LOGITECH_HIDPP`; Kconfig selects POWER_SUPPLY
- [Phase 8] Failure mode: missing HID++/battery in wired mode, not oops
- UNVERIFIED: stable@ archive search (HTTP 403); no hardware test on
5.15
**YES**
drivers/hid/hid-logitech-hidpp.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index a2bb7d8b15b69..a931713a9cb69 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -4615,6 +4615,8 @@ static const struct hid_device_id hidpp_devices[] = {
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC082) },
{ /* Logitech G502 Lightspeed Wireless Gaming Mouse over USB */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC08D) },
+ { /* Logitech G502 X Plus Wireless Gaming Mouse over USB */
+ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC095) },
{ /* Logitech G703 Gaming Mouse over USB */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC087) },
{ /* Logitech G703 Hero Gaming Mouse over USB */
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH AUTOSEL 6.18] HID: wacom: avoid copying Bluetooth input reports
[not found] <20261019135441.1420968-1-sashal@kernel.org>
` (15 preceding siblings ...)
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-6.6] HID: logitech-hidpp: Add support for G502 X Plus USB mouse Sasha Levin
@ 2026-10-19 13:51 ` Sasha Levin
2026-10-19 15:07 ` sashiko-bot
16 siblings, 1 reply; 20+ messages in thread
From: Sasha Levin @ 2026-10-19 13:51 UTC (permalink / raw)
To: patches, stable
Cc: Ruoyu Wang, Jason Gerecke, Jiri Kosina, Sasha Levin, ping.cheng,
jikos, bentiss, linux-input, linux-kernel
From: Ruoyu Wang <ruoyuw560@gmail.com>
[ Upstream commit 8310cdeefc8a14d2093c3234b570c7805c20bcbf ]
wacom_intuos_bt_irq() duplicates the received Bluetooth report with
kmemdup() so that it can pass 10-byte input report payloads to the
common Intuos parser. The helper then copies each payload back into
wacom->data before calling wacom_intuos_irq().
Avoid the allocation and copy by temporarily pointing wacom->data at the
current 10-byte payload while the common parser runs, then restoring the
original report pointer. The Bluetooth report parser keeps using the
original report buffer for dispatch and battery parsing, while the common
parser sees the same payload bytes as before.
This also removes the unchecked kmemdup() result from the Bluetooth IRQ
path.
Suggested-by: Jason Gerecke <jason.gerecke@wacom.com>
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
Reviewed-by: Jason Gerecke <jason.gerecke@wacom.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Vanilla 6.18.53 still has the unchecked `kmemdup(GFP_KERNEL)` in this
Bluetooth IRQ path. The rest of the walkthrough is below.
===============================================================
PHASE 1: COMMIT MESSAGE FORENSICS
===============================================================
Step 1.1: PARSE THE SUBJECT LINE
Record: [HID: wacom] [avoid] [stop kmemdup/memcpy of Bluetooth Intuos
reports by switching the parser onto the live 10-byte payload]
Step 1.2: PARSE ALL COMMIT MESSAGE TAGS
Record:
- Suggested-by: Jason Gerecke <jason.gerecke@wacom.com>
- Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com> (author)
- Reviewed-by: Jason Gerecke <jason.gerecke@wacom.com> (Wacom driver
maintainer)
- Signed-off-by: Jiri Kosina <jkosina@suse.com> (HID maintainer)
- Ignore: `[Upstream commit 8310cdeefc8a...]`, `Signed-off-by: Sasha
Levin`
- No Fixes:, Reported-by:, Tested-by:, Link:, or Cc: stable (absence
expected)
Notable: maintainer both suggested the approach and reviewed it.
Step 1.3: ANALYZE THE COMMIT BODY TEXT
Record:
- Bug: `wacom_intuos_bt_irq()` `kmemdup()`s the Bluetooth report, then
`wacom_intuos_bt_process_data()` `memcpy`s each 10-byte payload into
`wacom->data` for `wacom_intuos_irq()`. The `kmemdup()` result is not
checked.
- Symptom: NULL deref of `data[0]` if allocation fails; also an
allocation+copy on every report.
- Version info: none in the message. The `kmemdup` itself was added
later (see Phase 3).
- Root cause: the copy exists only so the shared Intuos parser can see a
10-byte payload without destroying the packed Bluetooth report. The
author replaces that with a temporary `wacom->data` pointer swap.
Step 1.4: DETECT HIDDEN BUG FIXES
Record: Yes. v1 on the list was explicitly `HID: wacom: handle kmemdup
failure in Bluetooth IRQ path` (NULL check). v2, at Jason Gerecke’s
request, removes the allocation instead. This is a crash fix written as
“avoid copying.”
===============================================================
PHASE 2: DIFF ANALYSIS - LINE BY LINE
===============================================================
Step 2.1: INVENTORY THE CHANGES
Record:
- File: `drivers/hid/wacom_wac.c` (~5 insertions, 3 deletions; series
mail said 8 lines)
- Functions: `wacom_intuos_bt_process_data()`, `wacom_intuos_bt_irq()`
- Scope: single-file surgical fix
Step 2.2: UNDERSTAND THE CODE FLOW CHANGE
Record:
- Before: `wacom_intuos_bt_irq()` does `data = kmemdup(wacom->data, len,
GFP_KERNEL)` then `switch (data[0])`. Helper `memcpy(wacom->data,
data, 10)` then `wacom_intuos_irq()`. `kfree(data)` at the end.
- After: `data = wacom->data`. Helper saves `wacom->data`, points it at
the 10-byte slice, calls `wacom_intuos_irq()`, restores the original
pointer.
- Path: HID input IRQ for `INTUOS4WL` (Wacom Intuos4 Wireless, USB ID
0xBD), not probe/error-only.
Step 2.3: IDENTIFY THE BUG MECHANISM
Record:
- Category: NULL deref on failed `kmemdup`; GFP_KERNEL allocation on the
HID input IRQ path.
- Mechanism: `hid_irq_in()` (USB URB complete) →
`hid_safe_input_report()` → `wacom_raw_event()` → `wacom_wac_irq()` →
`wacom_intuos_bt_irq()`. `__hid_input_report()` uses `down_trylock()`
because this can run in atomic context. `kmemdup(..., GFP_KERNEL)`
there can sleep or return NULL; `switch (data[0])` then oopses. The
pointer swap keeps the packed report intact without allocating.
Step 2.4: ASSESS THE FIX QUALITY
Record:
- Quality: small, equivalent for this device. `wacom_intuos_inout()` /
`wacom_intuos_general()` / INTUOS4 pad parsing only read
`data[0]`–`data[9]`. Restore of `wacom->data` is synchronous; nothing
stashes the pointer.
- Regression risk: low-medium. Sashiko flagged unaligned
`be16_to_cpup((__be16 *)&data[2])` because payloads start at offset
1/11. Old `memcpy` landed those 10 bytes on the aligned URB buffer;
the new pointer does not. Jason Gerecke treated that as non-blocking
and asked for a later alignment cleanup. Intuos4 WL is a PC USB
tablet, so strict-alignment ARM faults are unlikely. No API/data-
structure change.
===============================================================
PHASE 3: GIT HISTORY INVESTIGATION
===============================================================
Step 3.1: BLAME THE CHANGED LINES
Record:
- Bluetooth packing/`memcpy` helper: 81af7e61a774e6 (Benjamin Tissoires,
2014-08-06).
- `kmemdup`/`kfree`: 5e013ad206895e (“HID: wacom: Remove static
WACOM_PKGLEN_MAX limit”, Jason Gerecke, 2025-03-03). That replaced a
stack `unsigned char data[WACOM_PKGLEN_MAX]` + `memcpy`. First in
v6.15 (in v6.15, not in v6.14). Present in this 6.18.53 tree.
Step 3.2: FOLLOW THE FIXES: TAG
Record: No Fixes: tag. Functionally this repairs 5e013ad206895e, which
is an ancestor of this tree.
Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES
Record:
- c8dc23c97680e “HID: wacom: fix out-of-bounds read in
wacom_intuos_bt_irq” — length checks; already in v6.18.53.
- 74ec08f7b81c2 — Pro2 BT length validation, different function.
- Standalone; not patch x/y. No extra prereqs beyond the `kmemdup` code
this tree already has.
Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS
Record: Ruoyu Wang has this one wacom commit here. Jason Gerecke is the
Wacom maintainer and both introduced the `kmemdup` and reviewed this
fix.
Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS
Record: None. Uses existing `wacom->data` / `wacom_intuos_irq()`.
Applies to v6.18.53 as written.
===============================================================
PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
===============================================================
Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION
Record:
- Lore/msgid:
https://patch.msgid.link/20260617072035.3373487-1-ruoyuw560@gmail.com
- v1 (2026-06-06):
https://patch.msgid.link/20260606040344.4-1-ruoyuw560@gmail.com —
NULL-check only.
- v2 (2026-06-17): pointer swap, as Jason asked.
- v1: Jason Reviewed-by + “do away with the kmemdup entirely.”
- v2: Sashiko unaligned-access warning; Jason: do not block; wants a
later alignment cleanup; Reviewed-by.
- Jiri Kosina: “Applied, thanks.”
- No NAK. No reviewer Cc: stable.
Step 4.2: CHECK WHO REVIEWED THE PATCH
Record: To/Cc: Ping Cheng, Jason Gerecke, Jiri Kosina, Benjamin
Tissoires, linux-input, linux-kernel. Jason reviewed; Jiri applied.
Step 4.3: SEARCH FOR THE BUG REPORT
Record: No Reported-by / bugzilla / syzbot. Found by code review of the
unchecked `kmemdup`.
Step 4.4: CHECK FOR RELATED PATCHES AND SERIES
Record: v1→v2 of one patch, not a multi-commit series. Related OOB fix
already in this tree.
Step 4.5: CHECK STABLE MAILING LIST HISTORY
Record: UNVERIFIED — lore.kernel.org/stable returned 403. b4 thread has
no stable discussion.
===============================================================
PHASE 5: CODE SEMANTIC ANALYSIS
===============================================================
Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF
Record: `wacom_intuos_bt_process_data()`, `wacom_intuos_bt_irq()`.
Step 5.2: TRACE CALLERS
Record:
- `wacom_intuos_bt_irq()` ← `wacom_wac_irq()` case `INTUOS4WL`
(`drivers/hid/wacom_wac.c`).
- `wacom_wac_irq()` ← `wacom_raw_event()` (`wacom_sys.c`).
- USB: `hid_irq_in()` (`drivers/hid/usbhid/hid-core.c`) calls
`hid_safe_input_report()` from URB complete (atomic/softirq).
- Bluetooth HIDP: `hidp_process_report()` from the l2cap/session path
(process context). This device is USB ID 0xBD, so the USB IRQ path is
the one that matters.
- Device table: `wacom_features_0xBD` / “Wacom Intuos4 WL”.
Step 5.3: TRACE CALLEES
Record: `wacom_intuos_irq()` → pad/inout/general parsers;
`wacom_notify_battery()`; `input_sync()`. No alloc after the change.
Step 5.4: FOLLOW THE CALL CHAIN
Record: Reachable from normal USB HID input of Intuos4 Wireless.
Unprivileged userspace is not required; hardware input is enough. Not a
syscall fuzzer path.
Step 5.5: SEARCH FOR SIMILAR PATTERNS
Record: Pro2 BT (`wacom_intuos_pro2_bt_irq`) does not `kmemdup`. This
packed 10-byte copy was unique to Intuos4 WL.
===============================================================
PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
===============================================================
Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?
Record: Yes. Local tree: 6.18.53 (`autosel`,
`v6.18.53-5049-g0f0bdc2b0dffb`). `v6.18.53:drivers/hid/wacom_wac.c`
still has `kmemdup` + `memcpy` + unchecked `data[0]`. Upstream fix
8310cdeefc8a is not an ancestor of v6.18.53.
Step 6.2: CHECK FOR BACKPORT COMPLICATIONS
Record: Clean apply. Surrounding OOB length checks are already in
6.18.53.
Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE
Record: OOB length checks yes. No earlier version of this pointer-
swap/NULL-check.
===============================================================
PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
===============================================================
Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY
Record: HID / Wacom tablet driver. IMPORTANT for tablet users,
PERIPHERAL overall (one 2010-era wireless Intuos4 model).
Step 7.2: ASSESS SUBSYSTEM ACTIVITY
Record: Active (device IDs, BT OOB fixes, pktlen work). The `kmemdup` is
from the v6.15 pktlen change, not ancient code.
===============================================================
PHASE 8: IMPACT AND RISK ASSESSMENT
===============================================================
Step 8.1: DETERMINE WHO IS AFFECTED
Record: Driver-specific — Intuos4 Wireless (`INTUOS4WL`, USB
0x056A:0x00BD).
Step 8.2: DETERMINE THE TRIGGER CONDITIONS
Record: Every packed BT/WL input report allocates. Oops if `kmemdup`
fails; GFP_KERNEL from USB complete is illegal even when the alloc hits
the slab cache. Not a userspace-triggered security hole.
Step 8.3: DETERMINE THE FAILURE MODE SEVERITY
Record: NULL deref → oops (HIGH). GFP_KERNEL from URB complete →
sleeping-in-atomic WARN/instability (HIGH). Practical hit rate is low
(small alloc, old device), but the bug is on the live input path.
Step 8.4: CALCULATE RISK-BENEFIT RATIO
Record:
- Benefit: medium — real IRQ-path crash/atomic-sleep fix, small user
population.
- Risk: low — ~8 lines, maintainer-reviewed; unaligned `be16_to_cpup` is
the main caveat and was accepted upstream.
- Ratio: benefit outweighs risk for 6.18.y.
===============================================================
PHASE 9: FINAL SYNTHESIS
===============================================================
Step 9.1: COMPILE THE EVIDENCE
FOR:
- Unchecked `kmemdup` NULL deref in this 6.18.53 tree.
- GFP_KERNEL on USB HID URB complete; 5e013ad replaced an atomic-safe
stack buffer.
- v1 was an explicit crash fix; v2 is the maintainer-preferred form.
- Reviewed by Jason Gerecke, applied by Jiri Kosina.
- Small, no new API, applies cleanly, parsers only use 10 payload bytes.
AGAINST:
- Niche Intuos4 Wireless hardware.
- No user/syzbot report.
- Subject reads like an optimization.
- Unaligned access vs old memcpy-to-aligned-buffer; no follow-up
alignment patch verified here.
UNRESOLVED:
- No stable@ thread (lore 403).
- No evidence of a field oops.
Step 9.2: APPLY THE STABLE RULES CHECKLIST
1. Obviously correct and tested? PASS — pointer save/restore; Wacom
maintainer Reviewed-by.
2. Fixes a real bug that affects users? PASS — NULL deref and GFP_KERNEL
in IRQ on a shipping device path.
3. Important issue? PASS — oops / sleeping-in-atomic (HIGH), not a style
cleanup.
4. Small and contained? PASS — one file, ~8 lines.
5. No new features or APIs? PASS.
6. Can apply to the local tree? PASS — buggy code is in v6.18.53; patch
matches.
Step 9.3: CHECK FOR EXCEPTION CATEGORIES
Record: Not a device-ID/quirk/DT/build/docs exception. Ordinary bugfix.
Step 9.4: MAKE YOUR DECISION
This belongs on 6.18.53. The tree still does `kmemdup(..., GFP_KERNEL)`
in `wacom_intuos_bt_irq()` and dereferences `data[0]` with no NULL
check, on the USB HID complete path. Replacing that with a temporary
`wacom->data` pointer is the same fix the maintainer asked for, and it
applies here without extra commits.
Verification:
- [Phase 1] Tags: Suggested-by/Reviewed-by Jason Gerecke, SOB Ruoyu Wang
and Jiri Kosina; no Fixes/Reported-by/Cc: stable
- [Phase 1] v1 subject from b4: “handle kmemdup failure in Bluetooth IRQ
path”
- [Phase 2] Diff: drop kmemdup/kfree/memcpy; save/restore `wacom->data`
around `wacom_intuos_irq()`
- [Phase 2] Parsers for INTUOS4WL use `data[0]`–`data[9]` only
(inout/general/pad)
- [Phase 3] Blame: kmemdup from 5e013ad206895e (v6.15+); in HEAD and
v6.18.53
- [Phase 3] `git merge-base --is-ancestor 5e013ad206895e v6.18.53` →
yes; `8310cdeefc8a` → no
- [Phase 3] Related OOB fix c8dc23c97680e already in v6.18.53
- [Phase 4] `b4 dig -c 8310cdeefc8a` → v1+v2 msgid links; Jason reviewed
both; Jiri applied v2
- [Phase 4] Sashiko unaligned warning; Jason said do not block
- [Phase 4] lore.kernel.org WebFetch 403; stable@ search UNVERIFIED
- [Phase 5] Call chain: `hid_irq_in` → `hid_safe_input_report` →
`wacom_raw_event` → `wacom_intuos_bt_irq`; USB 0xBD Intuos4 WL
- [Phase 6] `git describe HEAD` → v6.18.53-5049-g0f0bdc2b0dffb; `make
kernelversion` → 6.18.53
- [Phase 6] `git show v6.18.53:drivers/hid/wacom_wac.c` still has
kmemdup
- [Phase 8] Failure: NULL deref / GFP_KERNEL from URB complete; severity
HIGH
- UNVERIFIED: whether this was already requested on stable@
**YES**
drivers/hid/wacom_wac.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index af76e49fd0f25..8feb8027be95e 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1192,8 +1192,11 @@ static int int_dist(int x1, int y1, int x2, int y2)
static void wacom_intuos_bt_process_data(struct wacom_wac *wacom,
unsigned char *data)
{
- memcpy(wacom->data, data, 10);
+ u8 *saved_data = wacom->data;
+
+ wacom->data = data;
wacom_intuos_irq(wacom);
+ wacom->data = saved_data;
input_sync(wacom->pen_input);
if (wacom->pad_input)
@@ -1202,7 +1205,7 @@ static void wacom_intuos_bt_process_data(struct wacom_wac *wacom,
static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len)
{
- u8 *data = kmemdup(wacom->data, len, GFP_KERNEL);
+ u8 *data = wacom->data;
int i = 1;
unsigned power_raw, battery_capacity, bat_charging, ps_connected;
@@ -1242,7 +1245,6 @@ static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len)
break;
}
- kfree(data);
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH AUTOSEL 6.18] HID: wacom: avoid copying Bluetooth input reports
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18] HID: wacom: avoid copying Bluetooth input reports Sasha Levin
@ 2026-10-19 15:07 ` sashiko-bot
0 siblings, 0 replies; 20+ messages in thread
From: sashiko-bot @ 2026-10-19 15:07 UTC (permalink / raw)
To: Sasha Levin; +Cc: linux-input, dmitry.torokhov
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] HID: wacom: unaligned 16-bit reads in wacom_intuos_general() on BT reports
--
commit c4e8a30b627ffd270cacd2aea99e17a24a724562
Author: Ruoyu Wang <ruoyuw560@gmail.com>
HID: wacom: avoid copying Bluetooth input reports
This commit avoids duplicating Bluetooth reports with kmemdup() in
wacom_intuos_bt_irq() by temporarily updating wacom->data to point at each
10-byte payload slice in wacom_intuos_bt_process_data() before calling
wacom_intuos_irq().
> diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
> index af76e49fd0f25..8feb8027be95e 100644
> --- a/drivers/hid/wacom_wac.c
> +++ b/drivers/hid/wacom_wac.c
> @@ -1192,8 +1192,11 @@ static int int_dist(int x1, int y1, int x2, int y2)
> static void wacom_intuos_bt_process_data(struct wacom_wac *wacom,
> unsigned char *data)
> {
> - memcpy(wacom->data, data, 10);
> + u8 *saved_data = wacom->data;
> +
> + wacom->data = data;
> wacom_intuos_irq(wacom);
> + wacom->data = saved_data;
[Severity: Medium]
Could pointing wacom->data directly at the payload slice introduce unaligned
16-bit memory accesses in wacom_intuos_general()?
When an Intuos4 Wireless report 0x03 or 0x04 arrives in wacom_intuos_bt_irq(),
it calls wacom_intuos_bt_process_data(wacom, data + i) with odd byte offsets
(i = 1, 11, and 21):
drivers/hid/wacom_wac.c:wacom_intuos_bt_irq() {
...
switch (data[0]) {
case 0x04:
...
wacom_intuos_bt_process_data(wacom, data + i);
i += 10;
fallthrough;
case 0x03:
...
wacom_intuos_bt_process_data(wacom, data + i);
i += 10;
wacom_intuos_bt_process_data(wacom, data + i);
i += 10;
...
}
Previously, memcpy(wacom->data, data, 10) copied each 10-byte payload to the
start of the aligned wacom->data buffer. By setting wacom->data to data + 1,
data + 11, or data + 21 directly, the call chain
wacom_intuos_bt_process_data() -> wacom_intuos_irq() ->
wacom_intuos_general() will dereference &data[2] and &data[4] at odd byte
offsets (3, 5, 13, 15, 23, and 25) via be16_to_cpup():
drivers/hid/wacom_wac.c:wacom_intuos_general() {
...
x = (be16_to_cpup((__be16 *)&data[2]) << 1) | ((data[9] >> 1) & 1);
y = (be16_to_cpup((__be16 *)&data[4]) << 1) | (data[9] & 1);
...
}
Since be16_to_cpup() expects natural 16-bit alignment, won't this trigger
UBSAN alignment splats or alignment faults on strict-alignment architectures
unless get_unaligned_be16() is used?
>
> input_sync(wacom->pen_input);
> if (wacom->pad_input)
[ ... ]
>
>
>
[]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261019135441.1420968-386-sashal@kernel.org?part=1
^ permalink raw reply [flat|nested] 20+ messages in thread