* [PATCH] HID: lenovo: Fix buffer over-read in X12 Tab raw_event handler
@ 2026-05-11 13:28 Kean
2026-05-11 17:52 ` Mark Pearson
2026-05-12 4:49 ` sashiko-bot
0 siblings, 2 replies; 4+ messages in thread
From: Kean @ 2026-05-11 13:28 UTC (permalink / raw)
To: derekjohn.clark, mpearson-lenovo
Cc: jikos, bentiss, linux-input, linux-kernel, Kean
In lenovo_raw_event(), the X12 Tab keyboard handler reads a 4-byte
little-endian value via *(__le32 *)data but only guards the access
with a size >= 3 check. If a 3-byte report with ID 0x03 is received,
the code reads one byte beyond the end of the buffer.
Change the size check to >= 4 to match the actual access width.
Signed-off-by: Kean <rh_king@163.com>
---
drivers/hid/hid-lenovo.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
index a6b73e03c16b..4686ecb6cfa8 100644
--- a/drivers/hid/hid-lenovo.c
+++ b/drivers/hid/hid-lenovo.c
@@ -793,7 +793,7 @@ static int lenovo_raw_event(struct hid_device *hdev,
*/
if (unlikely((hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB
|| hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB2)
- && size >= 3 && report->id == 0x03))
+ && size >= 4 && report->id == 0x03))
return lenovo_raw_event_TP_X12_tab(hdev, le32_to_cpu(*(__le32 *)data));
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] HID: lenovo: Fix buffer over-read in X12 Tab raw_event handler
2026-05-11 13:28 [PATCH] HID: lenovo: Fix buffer over-read in X12 Tab raw_event handler Kean
@ 2026-05-11 17:52 ` Mark Pearson
2026-05-12 4:49 ` sashiko-bot
1 sibling, 0 replies; 4+ messages in thread
From: Mark Pearson @ 2026-05-11 17:52 UTC (permalink / raw)
To: Kean, Derek J . Clark
Cc: Jiri Kosina, Benjamin Tissoires, linux-input, linux-kernel
On Mon, May 11, 2026, at 9:28 AM, Kean wrote:
> In lenovo_raw_event(), the X12 Tab keyboard handler reads a 4-byte
> little-endian value via *(__le32 *)data but only guards the access
> with a size >= 3 check. If a 3-byte report with ID 0x03 is received,
> the code reads one byte beyond the end of the buffer.
>
> Change the size check to >= 4 to match the actual access width.
>
> Signed-off-by: Kean <rh_king@163.com>
> ---
> drivers/hid/hid-lenovo.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
> index a6b73e03c16b..4686ecb6cfa8 100644
> --- a/drivers/hid/hid-lenovo.c
> +++ b/drivers/hid/hid-lenovo.c
> @@ -793,7 +793,7 @@ static int lenovo_raw_event(struct hid_device *hdev,
> */
> if (unlikely((hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB
> || hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB2)
> - && size >= 3 && report->id == 0x03))
> + && size >= 4 && report->id == 0x03))
> return lenovo_raw_event_TP_X12_tab(hdev, le32_to_cpu(*(__le32 *)data));
>
> return 0;
> --
> 2.53.0
Looks good to me. Thanks!
Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Mark
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] HID: lenovo: Fix buffer over-read in X12 Tab raw_event handler
2026-05-11 13:28 [PATCH] HID: lenovo: Fix buffer over-read in X12 Tab raw_event handler Kean
2026-05-11 17:52 ` Mark Pearson
@ 2026-05-12 4:49 ` sashiko-bot
2026-05-14 12:58 ` [PATCH] HID: lenovo: Fix buffer over-read and unaligned access " Kean
1 sibling, 1 reply; 4+ messages in thread
From: sashiko-bot @ 2026-05-12 4:49 UTC (permalink / raw)
To: Kean; +Cc: linux-input, dmitry.torokhov
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Unaligned memory access via direct pointer cast in raw event handler.
- [High] Missing input capability registration causes hotkey events to be silently dropped.
--
commit a1525e53f7f5fe161ed804808d59755ff69c771f
Author: Kean <rh_king@163.com>
HID: lenovo: Fix buffer over-read in X12 Tab raw_event handler
In lenovo_raw_event(), the X12 Tab keyboard handler reads a 4-byte
little-endian value via *(__le32 *)data but only guards the access
with a size >= 3 check. If a 3-byte report with ID 0x03 is received,
the code reads one byte beyond the end of the buffer.
Change the size check to >= 4 to match the actual access width.
> diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
> index a6b73e03c16b3..4686ecb6cfa8e 100644
> --- a/drivers/hid/hid-lenovo.c
> +++ b/drivers/hid/hid-lenovo.c
> @@ -793,7 +793,7 @@ static int lenovo_raw_event(struct hid_device *hdev,
> */
> if (unlikely((hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB
> || hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB2)
> - && size >= 3 && report->id == 0x03))
> + && size >= 4 && report->id == 0x03))
> return lenovo_raw_event_TP_X12_tab(hdev, le32_to_cpu(*(__le32 *)data));
This isn't a regression from this patch, but could this direct pointer cast
lead to unaligned memory access exceptions?
The data pointer provided by the HID core can have arbitrary alignment
depending on the transport layer. For instance, if injected via uhid using
UHID_INPUT2, the payload data starts at an offset of 6 bytes from the start
of the uhid_event struct, which is 2-byte aligned but not 4-byte aligned.
On architectures that do not natively support unaligned memory access,
dereferencing an unaligned pointer triggers an unaligned access exception.
Would it be safer to use get_unaligned_le32(data) to safely extract the
value?
Also, another issue not introduced by this patch: do the hotkey events
processed by lenovo_raw_event_TP_X12_tab() get silently dropped by the input
core?
The lenovo_raw_event_TP_X12_tab() handler reports events for keys like
KEY_RFKILL, KEY_PERFORMANCE, and KEY_BOOKMARKS:
drivers/hid/hid-lenovo.c:lenovo_raw_event_TP_X12_tab() {
...
case TP_X12_RAW_HOTKEY_FN_F8:
if (hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB) {
report_key_event(input, KEY_RFKILL);
return 1;
}
report_key_event(input, KEY_PERFORMANCE);
return 1;
...
}
However, if these key capabilities are not registered in the input_dev's
keybit array during device initialization, the kernel's input core checks
is_event_supported(code, dev->keybit, KEY_MAX) and drops the events when
report_key_event() is called.
Are these custom hotkey capabilities properly registered during device setup
to prevent them from being filtered out?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260511132854.1351379-1-rh_king@163.com?part=1
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH] HID: lenovo: Fix buffer over-read and unaligned access in X12 Tab raw_event handler
2026-05-12 4:49 ` sashiko-bot
@ 2026-05-14 12:58 ` Kean
0 siblings, 0 replies; 4+ messages in thread
From: Kean @ 2026-05-14 12:58 UTC (permalink / raw)
To: sashiko-bot, derekjohn.clark
Cc: linux-input, mpearson-lenovo, jikos, bentiss, linux-kernel, Kean
In lenovo_raw_event(), the X12 Tab keyboard handler reads a 4-byte
little-endian value from the raw HID report buffer but:
1. The size guard is size >= 3, while the access reads 4 bytes.
A malformed 3-byte report with ID 0x03 would over-read the
buffer by one byte.
2. Casting u8 *data directly to __le32 * can trigger unaligned
access faults on architectures like ARM, MIPS, and SPARC,
because HID input buffers carry no alignment guarantee.
(e.g. uhid payloads start at offset 6 in struct uhid_event,
giving only 2-byte alignment.)
Fix both by tightening the size check to >= 4 and replacing the
open-coded cast + le32_to_cpu() with get_unaligned_le32(), which
handles the LE-to-CPU conversion safely regardless of alignment.
Link: https://sashiko.dev/#/message/20260512044911.99B6DC2BCB0%40smtp.kernel.org
Assisted-by: CLAUDE:claude-4-sonnet
Signed-off-by: Kean <rh_king@163.com>
---
drivers/hid/hid-lenovo.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
index a6b73e03c16b..c11957ae8b77 100644
--- a/drivers/hid/hid-lenovo.c
+++ b/drivers/hid/hid-lenovo.c
@@ -30,6 +30,7 @@
#include <linux/hid.h>
#include <linux/input.h>
#include <linux/leds.h>
+#include <linux/unaligned.h>
#include <linux/workqueue.h>
#include "hid-ids.h"
@@ -793,8 +794,8 @@ static int lenovo_raw_event(struct hid_device *hdev,
*/
if (unlikely((hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB
|| hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB2)
- && size >= 3 && report->id == 0x03))
- return lenovo_raw_event_TP_X12_tab(hdev, le32_to_cpu(*(__le32 *)data));
+ && size >= 4 && report->id == 0x03))
+ return lenovo_raw_event_TP_X12_tab(hdev, get_unaligned_le32(data));
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-05-14 12:59 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-11 13:28 [PATCH] HID: lenovo: Fix buffer over-read in X12 Tab raw_event handler Kean
2026-05-11 17:52 ` Mark Pearson
2026-05-12 4:49 ` sashiko-bot
2026-05-14 12:58 ` [PATCH] HID: lenovo: Fix buffer over-read and unaligned access " Kean
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox