diff options
author | 2025-07-31 22:43:21 +0200 | |
---|---|---|
committer | 2025-07-31 22:43:21 +0200 | |
commit | bfb0195705f23568b77744cefc1cb81fd7a94d59 (patch) | |
tree | 70b30731c91c48c15a3c33465aaa0336b62cf558 | |
parent | Merge branch 'for-6.17/battery-timer-fixes' into for-linus (diff) | |
parent | HID: core: Harden s32ton() against conversion to 0 bits (diff) | |
download | wireguard-linux-bfb0195705f23568b77744cefc1cb81fd7a94d59.tar.xz wireguard-linux-bfb0195705f23568b77744cefc1cb81fd7a94d59.zip |
Merge branch 'for-6.17/core' into for-linus
- hardening of HID core parser against conversion to 0 bits in s32ton()
by buggy/malicious devices (Alan Stern)
-rw-r--r-- | drivers/hid/hid-core.c | 12 | ||||
-rw-r--r-- | drivers/hid/hid-debug.c | 2 | ||||
-rw-r--r-- | drivers/hid/hid-lg4ff.c | 6 | ||||
-rw-r--r-- | include/linux/hid.h | 8 |
4 files changed, 19 insertions, 9 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index b31b8a2fd540..2781fb7d968c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -66,8 +66,12 @@ static s32 snto32(__u32 value, unsigned int n) static u32 s32ton(__s32 value, unsigned int n) { - s32 a = value >> (n - 1); + s32 a; + if (!value || !n) + return 0; + + a = value >> (n - 1); if (a && a != -1) return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1; return value & ((1 << n) - 1); @@ -659,9 +663,9 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item) default: if (item->tag >= HID_MAIN_ITEM_TAG_RESERVED_MIN && item->tag <= HID_MAIN_ITEM_TAG_RESERVED_MAX) - hid_warn(parser->device, "reserved main item tag 0x%x\n", item->tag); + hid_warn_ratelimited(parser->device, "reserved main item tag 0x%x\n", item->tag); else - hid_warn(parser->device, "unknown main item tag 0x%x\n", item->tag); + hid_warn_ratelimited(parser->device, "unknown main item tag 0x%x\n", item->tag); ret = 0; } @@ -2806,7 +2810,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a, { struct hid_device *hdev = container_of(dev, struct hid_device, dev); - return scnprintf(buf, PAGE_SIZE, "hid:b%04Xg%04Xv%08Xp%08X\n", + return sysfs_emit(buf, "hid:b%04Xg%04Xv%08Xp%08X\n", hdev->bus, hdev->group, hdev->vendor, hdev->product); } static DEVICE_ATTR_RO(modalias); diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 4424c0512bae..e86bda0dab9b 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -3726,7 +3726,7 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer, */ if (!list->hdev || !list->hdev->debug) { ret = -EIO; - set_current_state(TASK_RUNNING); + __set_current_state(TASK_RUNNING); goto out; } diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 445623dd1bd6..32b711723f2a 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -956,7 +956,7 @@ static ssize_t lg4ff_combine_show(struct device *dev, struct device_attribute *a return 0; } - count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->wdata.combine); + count = sysfs_emit(buf, "%u\n", entry->wdata.combine); return count; } @@ -1009,7 +1009,7 @@ static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *att return 0; } - count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->wdata.range); + count = sysfs_emit(buf, "%u\n", entry->wdata.range); return count; } @@ -1073,7 +1073,7 @@ static ssize_t lg4ff_real_id_show(struct device *dev, struct device_attribute *a return 0; } - count = scnprintf(buf, PAGE_SIZE, "%s: %s\n", entry->wdata.real_tag, entry->wdata.real_name); + count = sysfs_emit(buf, "%s: %s\n", entry->wdata.real_tag, entry->wdata.real_name); return count; } diff --git a/include/linux/hid.h b/include/linux/hid.h index 568a9d8c749b..2cc4f1e4ea96 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -1216,7 +1216,11 @@ static inline void hid_hw_wait(struct hid_device *hdev) /** * hid_report_len - calculate the report length * - * @report: the report we want to know the length + * @report: the report whose length we want to know + * + * The length counts the report ID byte, but only if the ID is nonzero + * and therefore is included in the report. Reports whose ID is zero + * never include an ID byte. */ static inline u32 hid_report_len(struct hid_report *report) { @@ -1239,6 +1243,8 @@ void hid_quirks_exit(__u16 bus); dev_notice(&(hid)->dev, fmt, ##__VA_ARGS__) #define hid_warn(hid, fmt, ...) \ dev_warn(&(hid)->dev, fmt, ##__VA_ARGS__) +#define hid_warn_ratelimited(hid, fmt, ...) \ + dev_warn_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) #define hid_info(hid, fmt, ...) \ dev_info(&(hid)->dev, fmt, ##__VA_ARGS__) #define hid_dbg(hid, fmt, ...) \ |