Skip to content

Commit 70eda68

Browse files
committed
Merge tag 'hid-for-linus-2026051401' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID fixes from Jiri Kosina: - fixes for a few OOB/UAF in several HID drivers (Florian Pradines, Lee Jones, Michael Zaidman, Rosalie Wanders, Sangyun Kim and Tomasz Pakuła) - more general sanitation of input data, dealing with potentially malicious hardware in hid-core (Benjamin Tissoires) - a few device-specific quirks and fixups * tag 'hid-for-linus-2026051401' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (22 commits) HID: logitech-hidpp: Add support for newer Bluetooth keyboards HID: pidff: Fix integer overflow in pidff_rescale HID: i2c-hid: add reset quirk for BLTP7853 touchpad HID: core: introduce hid_safe_input_report() HID: pass the buffer size to hid_report_raw_event HID: google: hammer: stop hardware on devres action failure HID: appletb-kbd: run inactivity autodim from workqueues HID: appletb-kbd: fix UAF in inactivity-timer cleanup path HID: playstation: Clamp num_touch_reports HID: magicmouse: Prevent out-of-bounds (OOB) read during DOUBLE_REPORT_ID HID: mcp2221: fix OOB write in mcp2221_raw_event() HID: quirks: really enable the intended work around for appledisplay HID: hid-sjoy: race between init and usage HID: uclogic: Fix regression of input name assignment HID: intel-thc-hid: Intel-quickspi: Fix some error codes HID: hid-lenovo-go-s: restore OS_TYPE after resume from s2idle HID: elan: Add support for ELAN SB974D touchpad HID: sony: add missing size validation for Rock Band 3 Pro instruments HID: sony: add missing size validation for SMK-Link remotes HID: sony: remove unneeded WARN_ON() in sony_leds_init() ...
2 parents 48f76a1 + 64ffa2e commit 70eda68

28 files changed

Lines changed: 279 additions & 88 deletions

drivers/hid/bpf/hid_bpf_dispatch.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ EXPORT_SYMBOL(hid_ops);
2424

2525
u8 *
2626
dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type, u8 *data,
27-
u32 *size, int interrupt, u64 source, bool from_bpf)
27+
size_t *buf_size, u32 *size, int interrupt, u64 source,
28+
bool from_bpf)
2829
{
2930
struct hid_bpf_ctx_kern ctx_kern = {
3031
.ctx = {
@@ -74,6 +75,7 @@ dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type
7475
*size = ret;
7576
}
7677

78+
*buf_size = ctx_kern.ctx.allocated_size;
7779
return ctx_kern.data;
7880
}
7981
EXPORT_SYMBOL_GPL(dispatch_hid_bpf_device_event);
@@ -505,7 +507,7 @@ __hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *b
505507
if (ret)
506508
return ret;
507509

508-
return hid_ops->hid_input_report(ctx->hid, type, buf, size, 0, (u64)(long)ctx, true,
510+
return hid_ops->hid_input_report(ctx->hid, type, buf, size, size, 0, (u64)(long)ctx, true,
509511
lock_already_taken);
510512
}
511513

drivers/hid/hid-appletb-kbd.c

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include <linux/module.h>
1818
#include <linux/string.h>
1919
#include <linux/backlight.h>
20-
#include <linux/timer.h>
20+
#include <linux/workqueue.h>
2121
#include <linux/input/sparse-keymap.h>
2222

2323
#include "hid-ids.h"
@@ -62,7 +62,8 @@ struct appletb_kbd {
6262
struct input_handle kbd_handle;
6363
struct input_handle tpd_handle;
6464
struct backlight_device *backlight_dev;
65-
struct timer_list inactivity_timer;
65+
struct delayed_work inactivity_work;
66+
struct work_struct restore_brightness_work;
6667
bool has_dimmed;
6768
bool has_turned_off;
6869
u8 saved_mode;
@@ -164,33 +165,44 @@ static int appletb_tb_key_to_slot(unsigned int code)
164165
}
165166
}
166167

167-
static void appletb_inactivity_timer(struct timer_list *t)
168+
static void appletb_inactivity_work(struct work_struct *work)
168169
{
169-
struct appletb_kbd *kbd = timer_container_of(kbd, t, inactivity_timer);
170+
struct appletb_kbd *kbd = container_of(to_delayed_work(work),
171+
struct appletb_kbd,
172+
inactivity_work);
170173

171174
if (kbd->backlight_dev && appletb_tb_autodim) {
172175
if (!kbd->has_dimmed) {
173176
backlight_device_set_brightness(kbd->backlight_dev, 1);
174177
kbd->has_dimmed = true;
175-
mod_timer(&kbd->inactivity_timer,
176-
jiffies + secs_to_jiffies(appletb_tb_idle_timeout));
178+
mod_delayed_work(system_wq, &kbd->inactivity_work,
179+
secs_to_jiffies(appletb_tb_idle_timeout));
177180
} else if (!kbd->has_turned_off) {
178181
backlight_device_set_brightness(kbd->backlight_dev, 0);
179182
kbd->has_turned_off = true;
180183
}
181184
}
182185
}
183186

187+
static void appletb_restore_brightness_work(struct work_struct *work)
188+
{
189+
struct appletb_kbd *kbd = container_of(work, struct appletb_kbd,
190+
restore_brightness_work);
191+
192+
if (kbd->backlight_dev)
193+
backlight_device_set_brightness(kbd->backlight_dev, 2);
194+
}
195+
184196
static void reset_inactivity_timer(struct appletb_kbd *kbd)
185197
{
186198
if (kbd->backlight_dev && appletb_tb_autodim) {
187199
if (kbd->has_dimmed || kbd->has_turned_off) {
188-
backlight_device_set_brightness(kbd->backlight_dev, 2);
189200
kbd->has_dimmed = false;
190201
kbd->has_turned_off = false;
202+
schedule_work(&kbd->restore_brightness_work);
191203
}
192-
mod_timer(&kbd->inactivity_timer,
193-
jiffies + secs_to_jiffies(appletb_tb_dim_timeout));
204+
mod_delayed_work(system_wq, &kbd->inactivity_work,
205+
secs_to_jiffies(appletb_tb_dim_timeout));
194206
}
195207
}
196208

@@ -408,9 +420,11 @@ static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id
408420
dev_err_probe(dev, -ENODEV, "Failed to get backlight device\n");
409421
} else {
410422
backlight_device_set_brightness(kbd->backlight_dev, 2);
411-
timer_setup(&kbd->inactivity_timer, appletb_inactivity_timer, 0);
412-
mod_timer(&kbd->inactivity_timer,
413-
jiffies + secs_to_jiffies(appletb_tb_dim_timeout));
423+
INIT_DELAYED_WORK(&kbd->inactivity_work, appletb_inactivity_work);
424+
INIT_WORK(&kbd->restore_brightness_work,
425+
appletb_restore_brightness_work);
426+
mod_delayed_work(system_wq, &kbd->inactivity_work,
427+
secs_to_jiffies(appletb_tb_dim_timeout));
414428
}
415429

416430
kbd->inp_handler.event = appletb_kbd_inp_event;
@@ -440,13 +454,14 @@ static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id
440454
unregister_handler:
441455
input_unregister_handler(&kbd->inp_handler);
442456
close_hw:
443-
if (kbd->backlight_dev) {
444-
put_device(&kbd->backlight_dev->dev);
445-
timer_delete_sync(&kbd->inactivity_timer);
446-
}
447457
hid_hw_close(hdev);
448458
stop_hw:
449459
hid_hw_stop(hdev);
460+
if (kbd->backlight_dev) {
461+
cancel_delayed_work_sync(&kbd->inactivity_work);
462+
cancel_work_sync(&kbd->restore_brightness_work);
463+
put_device(&kbd->backlight_dev->dev);
464+
}
450465
return ret;
451466
}
452467

@@ -457,13 +472,14 @@ static void appletb_kbd_remove(struct hid_device *hdev)
457472
appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_OFF);
458473

459474
input_unregister_handler(&kbd->inp_handler);
475+
hid_hw_close(hdev);
476+
hid_hw_stop(hdev);
477+
460478
if (kbd->backlight_dev) {
479+
cancel_delayed_work_sync(&kbd->inactivity_work);
480+
cancel_work_sync(&kbd->restore_brightness_work);
461481
put_device(&kbd->backlight_dev->dev);
462-
timer_delete_sync(&kbd->inactivity_timer);
463482
}
464-
465-
hid_hw_close(hdev);
466-
hid_hw_stop(hdev);
467483
}
468484

469485
static int appletb_kbd_suspend(struct hid_device *hdev, pm_message_t msg)

drivers/hid/hid-core.c

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2033,24 +2033,32 @@ int __hid_request(struct hid_device *hid, struct hid_report *report,
20332033
}
20342034
EXPORT_SYMBOL_GPL(__hid_request);
20352035

2036-
int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
2037-
int interrupt)
2036+
int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data,
2037+
size_t bufsize, u32 size, int interrupt)
20382038
{
20392039
struct hid_report_enum *report_enum = hid->report_enum + type;
20402040
struct hid_report *report;
20412041
struct hid_driver *hdrv;
20422042
int max_buffer_size = HID_MAX_BUFFER_SIZE;
20432043
u32 rsize, csize = size;
2044+
size_t bsize = bufsize;
20442045
u8 *cdata = data;
20452046
int ret = 0;
20462047

20472048
report = hid_get_report(report_enum, data);
20482049
if (!report)
2049-
goto out;
2050+
return 0;
2051+
2052+
if (unlikely(bsize < csize)) {
2053+
hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n",
2054+
report->id, csize, bsize);
2055+
return -EINVAL;
2056+
}
20502057

20512058
if (report_enum->numbered) {
20522059
cdata++;
20532060
csize--;
2061+
bsize--;
20542062
}
20552063

20562064
rsize = hid_compute_report_size(report);
@@ -2063,19 +2071,24 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
20632071
else if (rsize > max_buffer_size)
20642072
rsize = max_buffer_size;
20652073

2074+
if (bsize < rsize) {
2075+
hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n",
2076+
report->id, rsize, bsize);
2077+
return -EINVAL;
2078+
}
2079+
20662080
if (csize < rsize) {
2067-
hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %d)\n",
2068-
report->id, rsize, csize);
2069-
ret = -EINVAL;
2070-
goto out;
2081+
dbg_hid("report %d is too short, (%d < %d)\n", report->id,
2082+
csize, rsize);
2083+
memset(cdata + csize, 0, rsize - csize);
20712084
}
20722085

20732086
if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
20742087
hid->hiddev_report_event(hid, report);
20752088
if (hid->claimed & HID_CLAIMED_HIDRAW) {
20762089
ret = hidraw_report_event(hid, data, size);
20772090
if (ret)
2078-
goto out;
2091+
return ret;
20792092
}
20802093

20812094
if (hid->claimed != HID_CLAIMED_HIDRAW && report->maxfield) {
@@ -2087,15 +2100,15 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
20872100

20882101
if (hid->claimed & HID_CLAIMED_INPUT)
20892102
hidinput_report_event(hid, report);
2090-
out:
2103+
20912104
return ret;
20922105
}
20932106
EXPORT_SYMBOL_GPL(hid_report_raw_event);
20942107

20952108

20962109
static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
2097-
u8 *data, u32 size, int interrupt, u64 source, bool from_bpf,
2098-
bool lock_already_taken)
2110+
u8 *data, size_t bufsize, u32 size, int interrupt, u64 source,
2111+
bool from_bpf, bool lock_already_taken)
20992112
{
21002113
struct hid_report_enum *report_enum;
21012114
struct hid_driver *hdrv;
@@ -2120,7 +2133,8 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
21202133
report_enum = hid->report_enum + type;
21212134
hdrv = hid->driver;
21222135

2123-
data = dispatch_hid_bpf_device_event(hid, type, data, &size, interrupt, source, from_bpf);
2136+
data = dispatch_hid_bpf_device_event(hid, type, data, &bufsize, &size, interrupt,
2137+
source, from_bpf);
21242138
if (IS_ERR(data)) {
21252139
ret = PTR_ERR(data);
21262140
goto unlock;
@@ -2149,7 +2163,7 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
21492163
goto unlock;
21502164
}
21512165

2152-
ret = hid_report_raw_event(hid, type, data, size, interrupt);
2166+
ret = hid_report_raw_event(hid, type, data, bufsize, size, interrupt);
21532167

21542168
unlock:
21552169
if (!lock_already_taken)
@@ -2167,16 +2181,41 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
21672181
* @interrupt: distinguish between interrupt and control transfers
21682182
*
21692183
* This is data entry for lower layers.
2184+
* Legacy, please use hid_safe_input_report() instead.
21702185
*/
21712186
int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
21722187
int interrupt)
21732188
{
2174-
return __hid_input_report(hid, type, data, size, interrupt, 0,
2189+
return __hid_input_report(hid, type, data, size, size, interrupt, 0,
21752190
false, /* from_bpf */
21762191
false /* lock_already_taken */);
21772192
}
21782193
EXPORT_SYMBOL_GPL(hid_input_report);
21792194

2195+
/**
2196+
* hid_safe_input_report - report data from lower layer (usb, bt...)
2197+
*
2198+
* @hid: hid device
2199+
* @type: HID report type (HID_*_REPORT)
2200+
* @data: report contents
2201+
* @bufsize: allocated size of the data buffer
2202+
* @size: useful size of data parameter
2203+
* @interrupt: distinguish between interrupt and control transfers
2204+
*
2205+
* This is data entry for lower layers.
2206+
* Please use this function instead of the non safe version because we provide
2207+
* here the size of the buffer, allowing hid-core to make smarter decisions
2208+
* regarding the incoming buffer.
2209+
*/
2210+
int hid_safe_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data,
2211+
size_t bufsize, u32 size, int interrupt)
2212+
{
2213+
return __hid_input_report(hid, type, data, bufsize, size, interrupt, 0,
2214+
false, /* from_bpf */
2215+
false /* lock_already_taken */);
2216+
}
2217+
EXPORT_SYMBOL_GPL(hid_safe_input_report);
2218+
21802219
bool hid_match_one_id(const struct hid_device *hdev,
21812220
const struct hid_device_id *id)
21822221
{

drivers/hid/hid-elan.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ static const struct hid_device_id elan_devices[] = {
513513
{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER),
514514
.driver_data = ELAN_HAS_LED },
515515
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_TOSHIBA_CLICK_L9W) },
516+
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_SB974D) },
516517
{ }
517518
};
518519
MODULE_DEVICE_TABLE(hid, elan_devices);

drivers/hid/hid-ft260.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,10 +1068,22 @@ static int ft260_raw_event(struct hid_device *hdev, struct hid_report *report,
10681068
struct ft260_device *dev = hid_get_drvdata(hdev);
10691069
struct ft260_i2c_input_report *xfer = (void *)data;
10701070

1071+
if (size < offsetof(struct ft260_i2c_input_report, data)) {
1072+
hid_err(hdev, "short report %d\n", size);
1073+
return -1;
1074+
}
1075+
10711076
if (xfer->report >= FT260_I2C_REPORT_MIN &&
10721077
xfer->report <= FT260_I2C_REPORT_MAX) {
1073-
ft260_dbg("i2c resp: rep %#02x len %d\n", xfer->report,
1074-
xfer->length);
1078+
ft260_dbg("i2c resp: rep %#02x len %d size %d\n",
1079+
xfer->report, xfer->length, size);
1080+
1081+
if (xfer->length > size -
1082+
offsetof(struct ft260_i2c_input_report, data)) {
1083+
hid_err(hdev, "report %#02x: length %d exceeds HID report size\n",
1084+
xfer->report, xfer->length);
1085+
return -1;
1086+
}
10751087

10761088
if ((dev->read_buf == NULL) ||
10771089
(xfer->length > dev->read_len - dev->read_idx)) {

drivers/hid/hid-gfrm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,15 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
6666
switch (data[1]) {
6767
case GFRM100_SEARCH_KEY_DOWN:
6868
ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_dn,
69-
sizeof(search_key_dn), 1);
69+
sizeof(search_key_dn), sizeof(search_key_dn), 1);
7070
break;
7171

7272
case GFRM100_SEARCH_KEY_AUDIO_DATA:
7373
break;
7474

7575
case GFRM100_SEARCH_KEY_UP:
7676
ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_up,
77-
sizeof(search_key_up), 1);
77+
sizeof(search_key_up), sizeof(search_key_up), 1);
7878
break;
7979

8080
default:

drivers/hid/hid-google-hammer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ static int hammer_probe(struct hid_device *hdev,
496496
if (error)
497497
return error;
498498

499-
error = devm_add_action(&hdev->dev, hammer_stop, hdev);
499+
error = devm_add_action_or_reset(&hdev->dev, hammer_stop, hdev);
500500
if (error)
501501
return error;
502502

drivers/hid/hid-ids.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@
277277
#define USB_VENDOR_ID_BIGBEN 0x146b
278278
#define USB_DEVICE_ID_BIGBEN_PS3OFMINIPAD 0x0902
279279

280+
#define I2C_VENDOR_ID_BLTP 0x36b6
281+
#define I2C_PRODUCT_ID_BLTP7853 0xc001
282+
280283
#define USB_VENDOR_ID_BTC 0x046e
281284
#define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578
282285
#define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2 0x5577
@@ -455,6 +458,7 @@
455458
#define USB_DEVICE_ID_EDIFIER_QR30 0xa101 /* EDIFIER Hal0 2.0 SE */
456459

457460
#define USB_VENDOR_ID_ELAN 0x04f3
461+
#define USB_DEVICE_ID_SB974D 0x0400
458462
#define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401
459463
#define USB_DEVICE_ID_HP_X2 0x074d
460464
#define USB_DEVICE_ID_HP_X2_10_COVER 0x0755

0 commit comments

Comments
 (0)