mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-21 23:16:50 +08:00
Merge tag 'hid-for-linus-2026031701' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID fixes from Jiri Kosina: - various fixes dealing with (intentionally) broken devices in HID core, logitech-hidpp and multitouch drivers (Lee Jones) - fix for OOB in wacom driver (Benoît Sevens) - fix for potentialy HID-bpf-induced buffer overflow in () (Benjamin Tissoires) - various other small fixes and device ID / quirk additions * tag 'hid-for-linus-2026031701' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: HID: multitouch: Check to ensure report responses match the request HID: logitech-hidpp: Prevent use-after-free on force feedback initialisation failure HID: bpf: prevent buffer overflow in hid_hw_request selftests/hid: fix compilation when bpf_wq and hid_device are not exported HID: core: Mitigate potential OOB by removing bogus memset() HID: intel-thc-hid: Set HID_PHYS with PCI BDF HID: appletb-kbd: add .resume method in PM HID: logitech-hidpp: Enable MX Master 4 over bluetooth HID: input: Add HID_BATTERY_QUIRK_DYNAMIC for Elan touchscreens HID: input: Drop Asus UX550* touchscreen ignore battery quirks HID: asus: add xg mobile 2022 external hardware support HID: wacom: fix out-of-bounds read in wacom_intuos_bt_irq
This commit is contained in:
@@ -444,6 +444,8 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
|
||||
(u64)(long)ctx,
|
||||
true); /* prevent infinite recursions */
|
||||
|
||||
if (ret > size)
|
||||
ret = size;
|
||||
if (ret > 0)
|
||||
memcpy(buf, dma_data, ret);
|
||||
|
||||
|
||||
@@ -476,7 +476,7 @@ static int appletb_kbd_suspend(struct hid_device *hdev, pm_message_t msg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int appletb_kbd_reset_resume(struct hid_device *hdev)
|
||||
static int appletb_kbd_resume(struct hid_device *hdev)
|
||||
{
|
||||
struct appletb_kbd *kbd = hid_get_drvdata(hdev);
|
||||
|
||||
@@ -500,7 +500,8 @@ static struct hid_driver appletb_kbd_hid_driver = {
|
||||
.event = appletb_kbd_hid_event,
|
||||
.input_configured = appletb_kbd_input_configured,
|
||||
.suspend = pm_ptr(appletb_kbd_suspend),
|
||||
.reset_resume = pm_ptr(appletb_kbd_reset_resume),
|
||||
.resume = pm_ptr(appletb_kbd_resume),
|
||||
.reset_resume = pm_ptr(appletb_kbd_resume),
|
||||
.driver.dev_groups = appletb_kbd_groups,
|
||||
};
|
||||
module_hid_driver(appletb_kbd_hid_driver);
|
||||
|
||||
@@ -1497,6 +1497,9 @@ static const struct hid_device_id asus_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
|
||||
USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X),
|
||||
QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_ALLY_XPAD },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
|
||||
USB_DEVICE_ID_ASUSTEK_XGM_2022),
|
||||
},
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
|
||||
USB_DEVICE_ID_ASUSTEK_XGM_2023),
|
||||
},
|
||||
|
||||
@@ -2057,9 +2057,10 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
|
||||
rsize = max_buffer_size;
|
||||
|
||||
if (csize < rsize) {
|
||||
dbg_hid("report %d is too short, (%d < %d)\n", report->id,
|
||||
csize, rsize);
|
||||
memset(cdata + csize, 0, rsize - csize);
|
||||
hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %d)\n",
|
||||
report->id, rsize, csize);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
|
||||
|
||||
@@ -229,6 +229,7 @@
|
||||
#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X 0x1b4c
|
||||
#define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b
|
||||
#define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869
|
||||
#define USB_DEVICE_ID_ASUSTEK_XGM_2022 0x1970
|
||||
#define USB_DEVICE_ID_ASUSTEK_XGM_2023 0x1a9a
|
||||
|
||||
#define USB_VENDOR_ID_ATEN 0x0557
|
||||
@@ -454,8 +455,6 @@
|
||||
#define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401
|
||||
#define USB_DEVICE_ID_HP_X2 0x074d
|
||||
#define USB_DEVICE_ID_HP_X2_10_COVER 0x0755
|
||||
#define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544
|
||||
#define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706
|
||||
#define I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM 0x2F81
|
||||
|
||||
#define USB_VENDOR_ID_ELECOM 0x056e
|
||||
|
||||
@@ -354,6 +354,7 @@ static enum power_supply_property hidinput_battery_props[] = {
|
||||
#define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */
|
||||
#define HID_BATTERY_QUIRK_IGNORE (1 << 2) /* completely ignore the battery */
|
||||
#define HID_BATTERY_QUIRK_AVOID_QUERY (1 << 3) /* do not query the battery */
|
||||
#define HID_BATTERY_QUIRK_DYNAMIC (1 << 4) /* report present only after life signs */
|
||||
|
||||
static const struct hid_device_id hid_battery_quirks[] = {
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
|
||||
@@ -386,10 +387,6 @@ static const struct hid_device_id hid_battery_quirks[] = {
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
|
||||
USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD),
|
||||
HID_BATTERY_QUIRK_IGNORE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN),
|
||||
HID_BATTERY_QUIRK_IGNORE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN),
|
||||
HID_BATTERY_QUIRK_IGNORE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L),
|
||||
HID_BATTERY_QUIRK_AVOID_QUERY },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW),
|
||||
@@ -402,8 +399,8 @@ static const struct hid_device_id hid_battery_quirks[] = {
|
||||
* Elan HID touchscreens seem to all report a non present battery,
|
||||
* set HID_BATTERY_QUIRK_IGNORE for all Elan I2C and USB HID devices.
|
||||
*/
|
||||
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_IGNORE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_IGNORE },
|
||||
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_DYNAMIC },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_DYNAMIC },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -460,11 +457,14 @@ static int hidinput_get_battery_property(struct power_supply *psy,
|
||||
int ret = 0;
|
||||
|
||||
switch (prop) {
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
val->intval = 1;
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
val->intval = dev->battery_present;
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_CAPACITY:
|
||||
if (dev->battery_status != HID_BATTERY_REPORTED &&
|
||||
!dev->battery_avoid_query) {
|
||||
@@ -577,6 +577,8 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
|
||||
if (quirks & HID_BATTERY_QUIRK_AVOID_QUERY)
|
||||
dev->battery_avoid_query = true;
|
||||
|
||||
dev->battery_present = (quirks & HID_BATTERY_QUIRK_DYNAMIC) ? false : true;
|
||||
|
||||
dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg);
|
||||
if (IS_ERR(dev->battery)) {
|
||||
error = PTR_ERR(dev->battery);
|
||||
@@ -632,6 +634,7 @@ static void hidinput_update_battery(struct hid_device *dev, unsigned int usage,
|
||||
return;
|
||||
|
||||
if (hidinput_update_battery_charge_status(dev, usage, value)) {
|
||||
dev->battery_present = true;
|
||||
power_supply_changed(dev->battery);
|
||||
return;
|
||||
}
|
||||
@@ -647,6 +650,7 @@ static void hidinput_update_battery(struct hid_device *dev, unsigned int usage,
|
||||
if (dev->battery_status != HID_BATTERY_REPORTED ||
|
||||
capacity != dev->battery_capacity ||
|
||||
ktime_after(ktime_get_coarse(), dev->battery_ratelimit_time)) {
|
||||
dev->battery_present = true;
|
||||
dev->battery_capacity = capacity;
|
||||
dev->battery_status = HID_BATTERY_REPORTED;
|
||||
dev->battery_ratelimit_time =
|
||||
|
||||
@@ -4487,10 +4487,12 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
if (!ret)
|
||||
ret = hidpp_ff_init(hidpp, &data);
|
||||
|
||||
if (ret)
|
||||
if (ret) {
|
||||
hid_warn(hidpp->hid_dev,
|
||||
"Unable to initialize force feedback support, errno %d\n",
|
||||
ret);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4668,6 +4670,8 @@ static const struct hid_device_id hidpp_devices[] = {
|
||||
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb038) },
|
||||
{ /* Slim Solar+ K980 Keyboard over Bluetooth */
|
||||
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb391) },
|
||||
{ /* MX Master 4 mouse over Bluetooth */
|
||||
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb042) },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -526,12 +526,19 @@ static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
|
||||
dev_warn(&hdev->dev, "failed to fetch feature %d\n",
|
||||
report->id);
|
||||
} else {
|
||||
/* The report ID in the request and the response should match */
|
||||
if (report->id != buf[0]) {
|
||||
hid_err(hdev, "Returned feature report did not match the request\n");
|
||||
goto free;
|
||||
}
|
||||
|
||||
ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf,
|
||||
size, 0);
|
||||
if (ret)
|
||||
dev_warn(&hdev->dev, "failed to report feature\n");
|
||||
}
|
||||
|
||||
free:
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
|
||||
@@ -127,6 +127,7 @@ int quicki2c_hid_probe(struct quicki2c_device *qcdev)
|
||||
hid->product = le16_to_cpu(qcdev->dev_desc.product_id);
|
||||
snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quicki2c-hid",
|
||||
hid->vendor, hid->product);
|
||||
strscpy(hid->phys, dev_name(qcdev->dev), sizeof(hid->phys));
|
||||
|
||||
ret = hid_add_device(hid);
|
||||
if (ret) {
|
||||
|
||||
@@ -118,6 +118,7 @@ int quickspi_hid_probe(struct quickspi_device *qsdev)
|
||||
hid->product = le16_to_cpu(qsdev->dev_desc.product_id);
|
||||
snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quickspi-hid",
|
||||
hid->vendor, hid->product);
|
||||
strscpy(hid->phys, dev_name(qsdev->dev), sizeof(hid->phys));
|
||||
|
||||
ret = hid_add_device(hid);
|
||||
if (ret) {
|
||||
|
||||
@@ -1208,10 +1208,20 @@ static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len)
|
||||
|
||||
switch (data[0]) {
|
||||
case 0x04:
|
||||
if (len < 32) {
|
||||
dev_warn(wacom->pen_input->dev.parent,
|
||||
"Report 0x04 too short: %zu bytes\n", len);
|
||||
break;
|
||||
}
|
||||
wacom_intuos_bt_process_data(wacom, data + i);
|
||||
i += 10;
|
||||
fallthrough;
|
||||
case 0x03:
|
||||
if (i == 1 && len < 22) {
|
||||
dev_warn(wacom->pen_input->dev.parent,
|
||||
"Report 0x03 too short: %zu bytes\n", len);
|
||||
break;
|
||||
}
|
||||
wacom_intuos_bt_process_data(wacom, data + i);
|
||||
i += 10;
|
||||
wacom_intuos_bt_process_data(wacom, data + i);
|
||||
|
||||
@@ -682,6 +682,7 @@ struct hid_device {
|
||||
__s32 battery_charge_status;
|
||||
enum hid_battery_status battery_status;
|
||||
bool battery_avoid_query;
|
||||
bool battery_present;
|
||||
ktime_t battery_ratelimit_time;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
#define __HID_BPF_HELPERS_H
|
||||
|
||||
/* "undefine" structs and enums in vmlinux.h, because we "override" them below */
|
||||
#define bpf_wq bpf_wq___not_used
|
||||
#define hid_bpf_ctx hid_bpf_ctx___not_used
|
||||
#define hid_bpf_ops hid_bpf_ops___not_used
|
||||
#define hid_device hid_device___not_used
|
||||
#define hid_report_type hid_report_type___not_used
|
||||
#define hid_class_request hid_class_request___not_used
|
||||
#define hid_bpf_attach_flags hid_bpf_attach_flags___not_used
|
||||
@@ -27,8 +29,10 @@
|
||||
|
||||
#include "vmlinux.h"
|
||||
|
||||
#undef bpf_wq
|
||||
#undef hid_bpf_ctx
|
||||
#undef hid_bpf_ops
|
||||
#undef hid_device
|
||||
#undef hid_report_type
|
||||
#undef hid_class_request
|
||||
#undef hid_bpf_attach_flags
|
||||
@@ -55,6 +59,14 @@ enum hid_report_type {
|
||||
HID_REPORT_TYPES,
|
||||
};
|
||||
|
||||
struct hid_device {
|
||||
unsigned int id;
|
||||
} __attribute__((preserve_access_index));
|
||||
|
||||
struct bpf_wq {
|
||||
__u64 __opaque[2];
|
||||
};
|
||||
|
||||
struct hid_bpf_ctx {
|
||||
struct hid_device *hid;
|
||||
__u32 allocated_size;
|
||||
|
||||
Reference in New Issue
Block a user