Skip to content

Commit 2653e3f

Browse files
committed
Merge tag 'for-linus-2023030901' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID fixes from Benjamin Tissoires: - fix potential out of bound write of zeroes in HID core with a specially crafted uhid device (Lee Jones) - fix potential use-after-free in work function in intel-ish-hid (Reka Norman) - selftests config fixes (Benjamin Tissoires) - few device small fixes and support * tag 'for-linus-2023030901' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: HID: intel-ish-hid: ipc: Fix potential use-after-free in work function HID: logitech-hidpp: Add support for Logitech MX Master 3S mouse HID: cp2112: Fix driver not registering GPIO IRQ chip as threaded selftest: hid: fix hid_bpf not set in config HID: uhid: Over-ride the default maximum data buffer value with our own HID: core: Provide new max_buffer_size attribute to over-ride the default
2 parents c70e9b8 + 8ae2f2b commit 2653e3f

File tree

7 files changed

+41
-8
lines changed

7 files changed

+41
-8
lines changed

drivers/hid/hid-core.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
256256
{
257257
struct hid_report *report;
258258
struct hid_field *field;
259+
unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE;
259260
unsigned int usages;
260261
unsigned int offset;
261262
unsigned int i;
@@ -286,8 +287,11 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
286287
offset = report->size;
287288
report->size += parser->global.report_size * parser->global.report_count;
288289

290+
if (parser->device->ll_driver->max_buffer_size)
291+
max_buffer_size = parser->device->ll_driver->max_buffer_size;
292+
289293
/* Total size check: Allow for possible report index byte */
290-
if (report->size > (HID_MAX_BUFFER_SIZE - 1) << 3) {
294+
if (report->size > (max_buffer_size - 1) << 3) {
291295
hid_err(parser->device, "report is too long\n");
292296
return -1;
293297
}
@@ -1963,6 +1967,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
19631967
struct hid_report_enum *report_enum = hid->report_enum + type;
19641968
struct hid_report *report;
19651969
struct hid_driver *hdrv;
1970+
int max_buffer_size = HID_MAX_BUFFER_SIZE;
19661971
u32 rsize, csize = size;
19671972
u8 *cdata = data;
19681973
int ret = 0;
@@ -1978,10 +1983,13 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
19781983

19791984
rsize = hid_compute_report_size(report);
19801985

1981-
if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE)
1982-
rsize = HID_MAX_BUFFER_SIZE - 1;
1983-
else if (rsize > HID_MAX_BUFFER_SIZE)
1984-
rsize = HID_MAX_BUFFER_SIZE;
1986+
if (hid->ll_driver->max_buffer_size)
1987+
max_buffer_size = hid->ll_driver->max_buffer_size;
1988+
1989+
if (report_enum->numbered && rsize >= max_buffer_size)
1990+
rsize = max_buffer_size - 1;
1991+
else if (rsize > max_buffer_size)
1992+
rsize = max_buffer_size;
19851993

19861994
if (csize < rsize) {
19871995
dbg_hid("report %d is too short, (%d < %d)\n", report->id,
@@ -2396,7 +2404,12 @@ int hid_hw_raw_request(struct hid_device *hdev,
23962404
unsigned char reportnum, __u8 *buf,
23972405
size_t len, enum hid_report_type rtype, enum hid_class_request reqtype)
23982406
{
2399-
if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf)
2407+
unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE;
2408+
2409+
if (hdev->ll_driver->max_buffer_size)
2410+
max_buffer_size = hdev->ll_driver->max_buffer_size;
2411+
2412+
if (len < 1 || len > max_buffer_size || !buf)
24002413
return -EINVAL;
24012414

24022415
return hdev->ll_driver->raw_request(hdev, reportnum, buf, len,
@@ -2415,7 +2428,12 @@ EXPORT_SYMBOL_GPL(hid_hw_raw_request);
24152428
*/
24162429
int hid_hw_output_report(struct hid_device *hdev, __u8 *buf, size_t len)
24172430
{
2418-
if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf)
2431+
unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE;
2432+
2433+
if (hdev->ll_driver->max_buffer_size)
2434+
max_buffer_size = hdev->ll_driver->max_buffer_size;
2435+
2436+
if (len < 1 || len > max_buffer_size || !buf)
24192437
return -EINVAL;
24202438

24212439
if (hdev->ll_driver->output_report)

drivers/hid/hid-cp2112.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,6 +1354,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
13541354
girq->parents = NULL;
13551355
girq->default_type = IRQ_TYPE_NONE;
13561356
girq->handler = handle_simple_irq;
1357+
girq->threaded = true;
13571358

13581359
ret = gpiochip_add_data(&dev->gc, dev);
13591360
if (ret < 0) {

drivers/hid/hid-logitech-hidpp.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4399,6 +4399,8 @@ static const struct hid_device_id hidpp_devices[] = {
43994399
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb02a) },
44004400
{ /* MX Master 3 mouse over Bluetooth */
44014401
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb023) },
4402+
{ /* MX Master 3S mouse over Bluetooth */
4403+
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb034) },
44024404
{}
44034405
};
44044406

drivers/hid/intel-ish-hid/ipc/ipc.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Copyright (c) 2014-2016, Intel Corporation.
66
*/
77

8+
#include <linux/devm-helpers.h>
89
#include <linux/sched.h>
910
#include <linux/spinlock.h>
1011
#include <linux/delay.h>
@@ -621,7 +622,6 @@ static void recv_ipc(struct ishtp_device *dev, uint32_t doorbell_val)
621622
case MNG_RESET_NOTIFY:
622623
if (!ishtp_dev) {
623624
ishtp_dev = dev;
624-
INIT_WORK(&fw_reset_work, fw_reset_work_fn);
625625
}
626626
schedule_work(&fw_reset_work);
627627
break;
@@ -940,6 +940,7 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
940940
{
941941
struct ishtp_device *dev;
942942
int i;
943+
int ret;
943944

944945
dev = devm_kzalloc(&pdev->dev,
945946
sizeof(struct ishtp_device) + sizeof(struct ish_hw),
@@ -975,6 +976,12 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
975976
list_add_tail(&tx_buf->link, &dev->wr_free_list);
976977
}
977978

979+
ret = devm_work_autocancel(&pdev->dev, &fw_reset_work, fw_reset_work_fn);
980+
if (ret) {
981+
dev_err(dev->devc, "Failed to initialise FW reset work\n");
982+
return NULL;
983+
}
984+
978985
dev->ops = &ish_hw_ops;
979986
dev->devc = &pdev->dev;
980987
dev->mtu = IPC_PAYLOAD_SIZE - sizeof(struct ishtp_msg_hdr);

drivers/hid/uhid.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ static const struct hid_ll_driver uhid_hid_driver = {
395395
.parse = uhid_hid_parse,
396396
.raw_request = uhid_hid_raw_request,
397397
.output_report = uhid_hid_output_report,
398+
.max_buffer_size = UHID_DATA_MAX,
398399
};
399400

400401
#ifdef CONFIG_COMPAT

include/linux/hid.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,7 @@ struct hid_driver {
834834
* @output_report: send output report to device
835835
* @idle: send idle request to device
836836
* @may_wakeup: return if device may act as a wakeup source during system-suspend
837+
* @max_buffer_size: over-ride maximum data buffer size (default: HID_MAX_BUFFER_SIZE)
837838
*/
838839
struct hid_ll_driver {
839840
int (*start)(struct hid_device *hdev);
@@ -859,6 +860,8 @@ struct hid_ll_driver {
859860

860861
int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype);
861862
bool (*may_wakeup)(struct hid_device *hdev);
863+
864+
unsigned int max_buffer_size;
862865
};
863866

864867
extern bool hid_is_usb(const struct hid_device *hdev);

tools/testing/selftests/hid/config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ CONFIG_FTRACE_SYSCALLS=y
1717
CONFIG_FUNCTION_TRACER=y
1818
CONFIG_HIDRAW=y
1919
CONFIG_HID=y
20+
CONFIG_HID_BPF=y
2021
CONFIG_INPUT_EVDEV=y
2122
CONFIG_UHID=y

0 commit comments

Comments
 (0)