Skip to content

Commit fc3abb5

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID fixes from Jiri Kosina: - data sanitization and validtion fixes for report descriptor parser from Marc Zyngier - memory leak fix for hid-elan driver from Dinghao Liu - two device-specific quirks * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: HID: core: Sanitize event code and type when mapping input HID: core: Correctly handle ReportSize being zero HID: elan: Fix memleak in elan_input_configured HID: microsoft: Add rumble support for the 8bitdo SN30 Pro+ controller HID: quirks: Set INCREMENT_USAGE_ON_DUPLICATE for all Saitek X52 devices
2 parents c3a1309 + 35556be commit fc3abb5

File tree

8 files changed

+57
-15
lines changed

8 files changed

+57
-15
lines changed

drivers/hid/hid-core.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,6 +1597,17 @@ static void hid_output_field(const struct hid_device *hid,
15971597
}
15981598
}
15991599

1600+
/*
1601+
* Compute the size of a report.
1602+
*/
1603+
static size_t hid_compute_report_size(struct hid_report *report)
1604+
{
1605+
if (report->size)
1606+
return ((report->size - 1) >> 3) + 1;
1607+
1608+
return 0;
1609+
}
1610+
16001611
/*
16011612
* Create a report. 'data' has to be allocated using
16021613
* hid_alloc_report_buf() so that it has proper size.
@@ -1609,7 +1620,7 @@ void hid_output_report(struct hid_report *report, __u8 *data)
16091620
if (report->id > 0)
16101621
*data++ = report->id;
16111622

1612-
memset(data, 0, ((report->size - 1) >> 3) + 1);
1623+
memset(data, 0, hid_compute_report_size(report));
16131624
for (n = 0; n < report->maxfield; n++)
16141625
hid_output_field(report->device, report->field[n], data);
16151626
}
@@ -1739,7 +1750,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
17391750
csize--;
17401751
}
17411752

1742-
rsize = ((report->size - 1) >> 3) + 1;
1753+
rsize = hid_compute_report_size(report);
17431754

17441755
if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE)
17451756
rsize = HID_MAX_BUFFER_SIZE - 1;

drivers/hid/hid-elan.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
188188
ret = input_mt_init_slots(input, ELAN_MAX_FINGERS, INPUT_MT_POINTER);
189189
if (ret) {
190190
hid_err(hdev, "Failed to init elan MT slots: %d\n", ret);
191+
input_free_device(input);
191192
return ret;
192193
}
193194

@@ -198,6 +199,7 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
198199
if (ret) {
199200
hid_err(hdev, "Failed to register elan input device: %d\n",
200201
ret);
202+
input_mt_destroy_slots(input);
201203
input_free_device(input);
202204
return ret;
203205
}

drivers/hid/hid-ids.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,7 @@
850850
#define USB_DEVICE_ID_MS_POWER_COVER 0x07da
851851
#define USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER 0x02fd
852852
#define USB_DEVICE_ID_MS_PIXART_MOUSE 0x00cb
853+
#define USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS 0x02e0
853854

854855
#define USB_VENDOR_ID_MOJO 0x8282
855856
#define USB_DEVICE_ID_RETRO_ADAPTER 0x3201
@@ -1015,6 +1016,8 @@
10151016
#define USB_DEVICE_ID_SAITEK_RAT9 0x0cfa
10161017
#define USB_DEVICE_ID_SAITEK_MMO7 0x0cd0
10171018
#define USB_DEVICE_ID_SAITEK_X52 0x075c
1019+
#define USB_DEVICE_ID_SAITEK_X52_2 0x0255
1020+
#define USB_DEVICE_ID_SAITEK_X52_PRO 0x0762
10181021

10191022
#define USB_VENDOR_ID_SAMSUNG 0x0419
10201023
#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001

drivers/hid/hid-input.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
11321132
}
11331133

11341134
mapped:
1135+
/* Mapping failed, bail out */
1136+
if (!bit)
1137+
return;
1138+
11351139
if (device->driver->input_mapped &&
11361140
device->driver->input_mapped(device, hidinput, field, usage,
11371141
&bit, &max) < 0) {

drivers/hid/hid-microsoft.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,8 @@ static const struct hid_device_id ms_devices[] = {
448448
.driver_data = MS_SURFACE_DIAL },
449449
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER),
450450
.driver_data = MS_QUIRK_FF },
451+
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS),
452+
.driver_data = MS_QUIRK_FF },
451453
{ }
452454
};
453455
MODULE_DEVICE_TABLE(hid, ms_devices);

drivers/hid/hid-multitouch.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,8 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
856856
code = BTN_0 + ((usage->hid - 1) & HID_USAGE);
857857

858858
hid_map_usage(hi, usage, bit, max, EV_KEY, code);
859+
if (!*bit)
860+
return -1;
859861
input_set_capability(hi->input, EV_KEY, code);
860862
return 1;
861863

drivers/hid/hid-quirks.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ static const struct hid_device_id hid_quirks[] = {
150150
{ HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPORT), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
151151
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD), HID_QUIRK_BADPAD },
152152
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
153+
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52_2), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
154+
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52_PRO), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
153155
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2), HID_QUIRK_NO_INIT_REPORTS },
154156
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS },
155157
{ HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB), HID_QUIRK_NOGET },

include/linux/hid.h

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -959,34 +959,49 @@ static inline void hid_device_io_stop(struct hid_device *hid) {
959959
* @max: maximal valid usage->code to consider later (out parameter)
960960
* @type: input event type (EV_KEY, EV_REL, ...)
961961
* @c: code which corresponds to this usage and type
962+
*
963+
* The value pointed to by @bit will be set to NULL if either @type is
964+
* an unhandled event type, or if @c is out of range for @type. This
965+
* can be used as an error condition.
962966
*/
963967
static inline void hid_map_usage(struct hid_input *hidinput,
964968
struct hid_usage *usage, unsigned long **bit, int *max,
965-
__u8 type, __u16 c)
969+
__u8 type, unsigned int c)
966970
{
967971
struct input_dev *input = hidinput->input;
968-
969-
usage->type = type;
970-
usage->code = c;
972+
unsigned long *bmap = NULL;
973+
unsigned int limit = 0;
971974

972975
switch (type) {
973976
case EV_ABS:
974-
*bit = input->absbit;
975-
*max = ABS_MAX;
977+
bmap = input->absbit;
978+
limit = ABS_MAX;
976979
break;
977980
case EV_REL:
978-
*bit = input->relbit;
979-
*max = REL_MAX;
981+
bmap = input->relbit;
982+
limit = REL_MAX;
980983
break;
981984
case EV_KEY:
982-
*bit = input->keybit;
983-
*max = KEY_MAX;
985+
bmap = input->keybit;
986+
limit = KEY_MAX;
984987
break;
985988
case EV_LED:
986-
*bit = input->ledbit;
987-
*max = LED_MAX;
989+
bmap = input->ledbit;
990+
limit = LED_MAX;
988991
break;
989992
}
993+
994+
if (unlikely(c > limit || !bmap)) {
995+
pr_warn_ratelimited("%s: Invalid code %d type %d\n",
996+
input->name, c, type);
997+
*bit = NULL;
998+
return;
999+
}
1000+
1001+
usage->type = type;
1002+
usage->code = c;
1003+
*max = limit;
1004+
*bit = bmap;
9901005
}
9911006

9921007
/**
@@ -1000,7 +1015,8 @@ static inline void hid_map_usage_clear(struct hid_input *hidinput,
10001015
__u8 type, __u16 c)
10011016
{
10021017
hid_map_usage(hidinput, usage, bit, max, type, c);
1003-
clear_bit(c, *bit);
1018+
if (*bit)
1019+
clear_bit(usage->code, *bit);
10041020
}
10051021

10061022
/**

0 commit comments

Comments
 (0)