Skip to content

Commit cee5aa1

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID fixes from Jiri Kosina: - fixes for a couple potential memory corruption problems (the HW would have to be manufactured to be deliberately evil to trigger those) found by Ben Hawkes - fix for potential infinite loop when using sysfs interface of logitech driver, from Simon Wood - a couple more simple driver fixes * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: HID: fix a couple of off-by-ones HID: logitech: perform bounds checking on device_id early enough HID: logitech: fix bounds checking on LED report size HID: logitech: Prevent possibility of infinite loop when using /sys interface HID: rmi: print an error if F11 is not found instead of stopping the device HID: hid-sensor-hub: use devm_ functions consistently HID: huion: Use allocated buffer for DMA HID: huion: Fail on parameter retrieval errors
2 parents e9d99a1 + 4ab2578 commit cee5aa1

File tree

11 files changed

+114
-93
lines changed

11 files changed

+114
-93
lines changed

drivers/hid/hid-cherry.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc,
2929
unsigned int *rsize)
3030
{
31-
if (*rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
31+
if (*rsize >= 18 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
3232
hid_info(hdev, "fixing up Cherry Cymotion report descriptor\n");
3333
rdesc[11] = rdesc[16] = 0xff;
3434
rdesc[12] = rdesc[17] = 0x03;

drivers/hid/hid-huion.c

Lines changed: 78 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@ static const __u8 huion_tablet_rdesc_template[] = {
8484
0xC0 /* End Collection */
8585
};
8686

87+
/* Parameter indices */
88+
enum huion_prm {
89+
HUION_PRM_X_LM = 1,
90+
HUION_PRM_Y_LM = 2,
91+
HUION_PRM_PRESSURE_LM = 4,
92+
HUION_PRM_RESOLUTION = 5,
93+
HUION_PRM_NUM
94+
};
95+
8796
/* Driver data */
8897
struct huion_drvdata {
8998
__u8 *rdesc;
@@ -115,73 +124,92 @@ static int huion_tablet_enable(struct hid_device *hdev)
115124
int rc;
116125
struct usb_device *usb_dev = hid_to_usb_dev(hdev);
117126
struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
118-
__le16 buf[6];
127+
__le16 *buf = NULL;
128+
size_t len;
129+
s32 params[HUION_PH_ID_NUM];
130+
s32 resolution;
131+
__u8 *p;
132+
s32 v;
119133

120134
/*
121135
* Read string descriptor containing tablet parameters. The specific
122136
* string descriptor and data were discovered by sniffing the Windows
123137
* driver traffic.
124138
* NOTE: This enables fully-functional tablet mode.
125139
*/
140+
len = HUION_PRM_NUM * sizeof(*buf);
141+
buf = kmalloc(len, GFP_KERNEL);
142+
if (buf == NULL) {
143+
hid_err(hdev, "failed to allocate parameter buffer\n");
144+
rc = -ENOMEM;
145+
goto cleanup;
146+
}
126147
rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
127148
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
128149
(USB_DT_STRING << 8) + 0x64,
129-
0x0409, buf, sizeof(buf),
150+
0x0409, buf, len,
130151
USB_CTRL_GET_TIMEOUT);
131-
if (rc == -EPIPE)
132-
hid_warn(hdev, "device parameters not found\n");
133-
else if (rc < 0)
134-
hid_warn(hdev, "failed to get device parameters: %d\n", rc);
135-
else if (rc != sizeof(buf))
136-
hid_warn(hdev, "invalid device parameters\n");
137-
else {
138-
s32 params[HUION_PH_ID_NUM];
139-
s32 resolution;
140-
__u8 *p;
141-
s32 v;
152+
if (rc == -EPIPE) {
153+
hid_err(hdev, "device parameters not found\n");
154+
rc = -ENODEV;
155+
goto cleanup;
156+
} else if (rc < 0) {
157+
hid_err(hdev, "failed to get device parameters: %d\n", rc);
158+
rc = -ENODEV;
159+
goto cleanup;
160+
} else if (rc != len) {
161+
hid_err(hdev, "invalid device parameters\n");
162+
rc = -ENODEV;
163+
goto cleanup;
164+
}
142165

143-
/* Extract device parameters */
144-
params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[1]);
145-
params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[2]);
146-
params[HUION_PH_ID_PRESSURE_LM] = le16_to_cpu(buf[4]);
147-
resolution = le16_to_cpu(buf[5]);
148-
if (resolution == 0) {
149-
params[HUION_PH_ID_X_PM] = 0;
150-
params[HUION_PH_ID_Y_PM] = 0;
151-
} else {
152-
params[HUION_PH_ID_X_PM] = params[HUION_PH_ID_X_LM] *
153-
1000 / resolution;
154-
params[HUION_PH_ID_Y_PM] = params[HUION_PH_ID_Y_LM] *
155-
1000 / resolution;
156-
}
166+
/* Extract device parameters */
167+
params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[HUION_PRM_X_LM]);
168+
params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[HUION_PRM_Y_LM]);
169+
params[HUION_PH_ID_PRESSURE_LM] =
170+
le16_to_cpu(buf[HUION_PRM_PRESSURE_LM]);
171+
resolution = le16_to_cpu(buf[HUION_PRM_RESOLUTION]);
172+
if (resolution == 0) {
173+
params[HUION_PH_ID_X_PM] = 0;
174+
params[HUION_PH_ID_Y_PM] = 0;
175+
} else {
176+
params[HUION_PH_ID_X_PM] = params[HUION_PH_ID_X_LM] *
177+
1000 / resolution;
178+
params[HUION_PH_ID_Y_PM] = params[HUION_PH_ID_Y_LM] *
179+
1000 / resolution;
180+
}
157181

158-
/* Allocate fixed report descriptor */
159-
drvdata->rdesc = devm_kmalloc(&hdev->dev,
160-
sizeof(huion_tablet_rdesc_template),
161-
GFP_KERNEL);
162-
if (drvdata->rdesc == NULL) {
163-
hid_err(hdev, "failed to allocate fixed rdesc\n");
164-
return -ENOMEM;
165-
}
166-
drvdata->rsize = sizeof(huion_tablet_rdesc_template);
182+
/* Allocate fixed report descriptor */
183+
drvdata->rdesc = devm_kmalloc(&hdev->dev,
184+
sizeof(huion_tablet_rdesc_template),
185+
GFP_KERNEL);
186+
if (drvdata->rdesc == NULL) {
187+
hid_err(hdev, "failed to allocate fixed rdesc\n");
188+
rc = -ENOMEM;
189+
goto cleanup;
190+
}
191+
drvdata->rsize = sizeof(huion_tablet_rdesc_template);
167192

168-
/* Format fixed report descriptor */
169-
memcpy(drvdata->rdesc, huion_tablet_rdesc_template,
170-
drvdata->rsize);
171-
for (p = drvdata->rdesc;
172-
p <= drvdata->rdesc + drvdata->rsize - 4;) {
173-
if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
174-
p[3] < sizeof(params)) {
175-
v = params[p[3]];
176-
put_unaligned(cpu_to_le32(v), (s32 *)p);
177-
p += 4;
178-
} else {
179-
p++;
180-
}
193+
/* Format fixed report descriptor */
194+
memcpy(drvdata->rdesc, huion_tablet_rdesc_template,
195+
drvdata->rsize);
196+
for (p = drvdata->rdesc;
197+
p <= drvdata->rdesc + drvdata->rsize - 4;) {
198+
if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
199+
p[3] < sizeof(params)) {
200+
v = params[p[3]];
201+
put_unaligned(cpu_to_le32(v), (s32 *)p);
202+
p += 4;
203+
} else {
204+
p++;
181205
}
182206
}
183207

184-
return 0;
208+
rc = 0;
209+
210+
cleanup:
211+
kfree(buf);
212+
return rc;
185213
}
186214

187215
static int huion_probe(struct hid_device *hdev, const struct hid_device_id *id)

drivers/hid/hid-kye.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
300300
* - change the button usage range to 4-7 for the extra
301301
* buttons
302302
*/
303-
if (*rsize >= 74 &&
303+
if (*rsize >= 75 &&
304304
rdesc[61] == 0x05 && rdesc[62] == 0x08 &&
305305
rdesc[63] == 0x19 && rdesc[64] == 0x08 &&
306306
rdesc[65] == 0x29 && rdesc[66] == 0x0f &&

drivers/hid/hid-lg.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,14 +345,14 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
345345
struct usb_device_descriptor *udesc;
346346
__u16 bcdDevice, rev_maj, rev_min;
347347

348-
if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 &&
348+
if ((drv_data->quirks & LG_RDESC) && *rsize >= 91 && rdesc[83] == 0x26 &&
349349
rdesc[84] == 0x8c && rdesc[85] == 0x02) {
350350
hid_info(hdev,
351351
"fixing up Logitech keyboard report descriptor\n");
352352
rdesc[84] = rdesc[89] = 0x4d;
353353
rdesc[85] = rdesc[90] = 0x10;
354354
}
355-
if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 50 &&
355+
if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 51 &&
356356
rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
357357
rdesc[49] == 0x81 && rdesc[50] == 0x06) {
358358
hid_info(hdev,

drivers/hid/hid-lg4ff.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,13 +451,13 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at
451451
drv_data = hid_get_drvdata(hid);
452452
if (!drv_data) {
453453
hid_err(hid, "Private driver data not found!\n");
454-
return 0;
454+
return -EINVAL;
455455
}
456456

457457
entry = drv_data->device_props;
458458
if (!entry) {
459459
hid_err(hid, "Device properties not found!\n");
460-
return 0;
460+
return -EINVAL;
461461
}
462462

463463
if (range == 0)

drivers/hid/hid-logitech-dj.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -238,13 +238,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
238238
return;
239239
}
240240

241-
if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
242-
(dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
243-
dev_err(&djrcv_hdev->dev, "%s: invalid device index:%d\n",
244-
__func__, dj_report->device_index);
245-
return;
246-
}
247-
248241
if (djrcv_dev->paired_dj_devices[dj_report->device_index]) {
249242
/* The device is already known. No need to reallocate it. */
250243
dbg_hid("%s: device is already known\n", __func__);
@@ -557,7 +550,7 @@ static int logi_dj_ll_raw_request(struct hid_device *hid,
557550
if (!out_buf)
558551
return -ENOMEM;
559552

560-
if (count < DJREPORT_SHORT_LENGTH - 2)
553+
if (count > DJREPORT_SHORT_LENGTH - 2)
561554
count = DJREPORT_SHORT_LENGTH - 2;
562555

563556
out_buf[0] = REPORT_ID_DJ_SHORT;
@@ -690,6 +683,12 @@ static int logi_dj_raw_event(struct hid_device *hdev,
690683
* device (via hid_input_report() ) and return 1 so hid-core does not do
691684
* anything else with it.
692685
*/
686+
if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
687+
(dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
688+
dev_err(&hdev->dev, "%s: invalid device index:%d\n",
689+
__func__, dj_report->device_index);
690+
return false;
691+
}
693692

694693
spin_lock_irqsave(&djrcv_dev->lock, flags);
695694
if (dj_report->report_id == REPORT_ID_DJ_SHORT) {

drivers/hid/hid-monterey.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
static __u8 *mr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
2525
unsigned int *rsize)
2626
{
27-
if (*rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) {
27+
if (*rsize >= 31 && rdesc[29] == 0x05 && rdesc[30] == 0x09) {
2828
hid_info(hdev, "fixing up button/consumer in HID report descriptor\n");
2929
rdesc[30] = 0x0c;
3030
}

drivers/hid/hid-petalynx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
static __u8 *pl_report_fixup(struct hid_device *hdev, __u8 *rdesc,
2626
unsigned int *rsize)
2727
{
28-
if (*rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 &&
28+
if (*rsize >= 62 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 &&
2929
rdesc[41] == 0x00 && rdesc[59] == 0x26 &&
3030
rdesc[60] == 0xf9 && rdesc[61] == 0x00) {
3131
hid_info(hdev, "fixing up Petalynx Maxter Remote report descriptor\n");

drivers/hid/hid-rmi.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -909,10 +909,15 @@ static int rmi_probe(struct hid_device *hdev, const struct hid_device_id *id)
909909
return ret;
910910
}
911911

912-
if (!test_bit(RMI_STARTED, &data->flags)) {
913-
hid_hw_stop(hdev);
914-
return -EIO;
915-
}
912+
if (!test_bit(RMI_STARTED, &data->flags))
913+
/*
914+
* The device maybe in the bootloader if rmi_input_configured
915+
* failed to find F11 in the PDT. Print an error, but don't
916+
* return an error from rmi_probe so that hidraw will be
917+
* accessible from userspace. That way a userspace tool
918+
* can be used to reload working firmware on the touchpad.
919+
*/
920+
hid_err(hdev, "Device failed to be properly configured\n");
916921

917922
return 0;
918923
}

drivers/hid/hid-sensor-hub.c

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -604,9 +604,9 @@ static int sensor_hub_probe(struct hid_device *hdev,
604604
ret = -EINVAL;
605605
goto err_stop_hw;
606606
}
607-
sd->hid_sensor_hub_client_devs = kzalloc(dev_cnt *
608-
sizeof(struct mfd_cell),
609-
GFP_KERNEL);
607+
sd->hid_sensor_hub_client_devs = devm_kzalloc(&hdev->dev, dev_cnt *
608+
sizeof(struct mfd_cell),
609+
GFP_KERNEL);
610610
if (sd->hid_sensor_hub_client_devs == NULL) {
611611
hid_err(hdev, "Failed to allocate memory for mfd cells\n");
612612
ret = -ENOMEM;
@@ -618,11 +618,12 @@ static int sensor_hub_probe(struct hid_device *hdev,
618618

619619
if (collection->type == HID_COLLECTION_PHYSICAL) {
620620

621-
hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL);
621+
hsdev = devm_kzalloc(&hdev->dev, sizeof(*hsdev),
622+
GFP_KERNEL);
622623
if (!hsdev) {
623624
hid_err(hdev, "cannot allocate hid_sensor_hub_device\n");
624625
ret = -ENOMEM;
625-
goto err_no_mem;
626+
goto err_stop_hw;
626627
}
627628
hsdev->hdev = hdev;
628629
hsdev->vendor_id = hdev->vendor;
@@ -631,13 +632,13 @@ static int sensor_hub_probe(struct hid_device *hdev,
631632
if (last_hsdev)
632633
last_hsdev->end_collection_index = i;
633634
last_hsdev = hsdev;
634-
name = kasprintf(GFP_KERNEL, "HID-SENSOR-%x",
635-
collection->usage);
635+
name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
636+
"HID-SENSOR-%x",
637+
collection->usage);
636638
if (name == NULL) {
637639
hid_err(hdev, "Failed MFD device name\n");
638640
ret = -ENOMEM;
639-
kfree(hsdev);
640-
goto err_no_mem;
641+
goto err_stop_hw;
641642
}
642643
sd->hid_sensor_hub_client_devs[
643644
sd->hid_sensor_client_cnt].id =
@@ -661,16 +662,10 @@ static int sensor_hub_probe(struct hid_device *hdev,
661662
ret = mfd_add_devices(&hdev->dev, 0, sd->hid_sensor_hub_client_devs,
662663
sd->hid_sensor_client_cnt, NULL, 0, NULL);
663664
if (ret < 0)
664-
goto err_no_mem;
665+
goto err_stop_hw;
665666

666667
return ret;
667668

668-
err_no_mem:
669-
for (i = 0; i < sd->hid_sensor_client_cnt; ++i) {
670-
kfree(sd->hid_sensor_hub_client_devs[i].name);
671-
kfree(sd->hid_sensor_hub_client_devs[i].platform_data);
672-
}
673-
kfree(sd->hid_sensor_hub_client_devs);
674669
err_stop_hw:
675670
hid_hw_stop(hdev);
676671

@@ -681,7 +676,6 @@ static void sensor_hub_remove(struct hid_device *hdev)
681676
{
682677
struct sensor_hub_data *data = hid_get_drvdata(hdev);
683678
unsigned long flags;
684-
int i;
685679

686680
hid_dbg(hdev, " hardware removed\n");
687681
hid_hw_close(hdev);
@@ -691,11 +685,6 @@ static void sensor_hub_remove(struct hid_device *hdev)
691685
complete(&data->pending.ready);
692686
spin_unlock_irqrestore(&data->lock, flags);
693687
mfd_remove_devices(&hdev->dev);
694-
for (i = 0; i < data->hid_sensor_client_cnt; ++i) {
695-
kfree(data->hid_sensor_hub_client_devs[i].name);
696-
kfree(data->hid_sensor_hub_client_devs[i].platform_data);
697-
}
698-
kfree(data->hid_sensor_hub_client_devs);
699688
hid_set_drvdata(hdev, NULL);
700689
mutex_destroy(&data->mutex);
701690
}

drivers/hid/hid-sunplus.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
static __u8 *sp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
2525
unsigned int *rsize)
2626
{
27-
if (*rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 &&
27+
if (*rsize >= 112 && rdesc[104] == 0x26 && rdesc[105] == 0x80 &&
2828
rdesc[106] == 0x03) {
2929
hid_info(hdev, "fixing up Sunplus Wireless Desktop report descriptor\n");
3030
rdesc[105] = rdesc[110] = 0x03;

0 commit comments

Comments
 (0)