aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-07-09 20:16:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-07-09 20:16:11 -0400
commit092150a25cb7bd6a79aa00bb1ad131063f58073d (patch)
treebc182ea7bb8f5b83c6853ce407483a8814076e21
parentbdf33113d89f70186ffb6674e925fa9b8a0266b1 (diff)
parent4f65245f2d178b9cba48350620d76faa4a098841 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID fixes from Jiri Kosina: - spectrev1 pattern fix in hiddev from Gustavo A. R. Silva - bounds check fix for hid-debug from Daniel Rosenberg - regression fix for HID autobinding from Benjamin Tissoires - removal of excessive logging from i2c-hid driver from Jason Andryuk - fix specific to 2nd generation of Wacom Intuos devices from Jason Gerecke * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: HID: hiddev: fix potential Spectre v1 HID: i2c-hid: Fix "incomplete report" noise HID: wacom: Correct touch maximum XY of 2nd-gen Intuos HID: debug: check length before copy_to_user() HID: core: allow concurrent registration of drivers
-rw-r--r--drivers/hid/hid-core.c5
-rw-r--r--drivers/hid/hid-debug.c8
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c2
-rw-r--r--drivers/hid/usbhid/hiddev.c11
-rw-r--r--drivers/hid/wacom_wac.c10
-rw-r--r--include/linux/hid.h3
6 files changed, 33 insertions, 6 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f858cc72011d..3942ee61bd1c 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1952,6 +1952,8 @@ static int hid_device_probe(struct device *dev)
1952 } 1952 }
1953 hdev->io_started = false; 1953 hdev->io_started = false;
1954 1954
1955 clear_bit(ffs(HID_STAT_REPROBED), &hdev->status);
1956
1955 if (!hdev->driver) { 1957 if (!hdev->driver) {
1956 id = hid_match_device(hdev, hdrv); 1958 id = hid_match_device(hdev, hdrv);
1957 if (id == NULL) { 1959 if (id == NULL) {
@@ -2215,7 +2217,8 @@ static int __hid_bus_reprobe_drivers(struct device *dev, void *data)
2215 struct hid_device *hdev = to_hid_device(dev); 2217 struct hid_device *hdev = to_hid_device(dev);
2216 2218
2217 if (hdev->driver == hdrv && 2219 if (hdev->driver == hdrv &&
2218 !hdrv->match(hdev, hid_ignore_special_drivers)) 2220 !hdrv->match(hdev, hid_ignore_special_drivers) &&
2221 !test_and_set_bit(ffs(HID_STAT_REPROBED), &hdev->status))
2219 return device_reprobe(dev); 2222 return device_reprobe(dev);
2220 2223
2221 return 0; 2224 return 0;
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 8469b6964ff6..b48100236df8 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -1154,6 +1154,8 @@ copy_rest:
1154 goto out; 1154 goto out;
1155 if (list->tail > list->head) { 1155 if (list->tail > list->head) {
1156 len = list->tail - list->head; 1156 len = list->tail - list->head;
1157 if (len > count)
1158 len = count;
1157 1159
1158 if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) { 1160 if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) {
1159 ret = -EFAULT; 1161 ret = -EFAULT;
@@ -1163,6 +1165,8 @@ copy_rest:
1163 list->head += len; 1165 list->head += len;
1164 } else { 1166 } else {
1165 len = HID_DEBUG_BUFSIZE - list->head; 1167 len = HID_DEBUG_BUFSIZE - list->head;
1168 if (len > count)
1169 len = count;
1166 1170
1167 if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) { 1171 if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) {
1168 ret = -EFAULT; 1172 ret = -EFAULT;
@@ -1170,7 +1174,9 @@ copy_rest:
1170 } 1174 }
1171 list->head = 0; 1175 list->head = 0;
1172 ret += len; 1176 ret += len;
1173 goto copy_rest; 1177 count -= len;
1178 if (count > 0)
1179 goto copy_rest;
1174 } 1180 }
1175 1181
1176 } 1182 }
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index c1652bb7bd15..eae0cb3ddec6 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -484,7 +484,7 @@ static void i2c_hid_get_input(struct i2c_hid *ihid)
484 return; 484 return;
485 } 485 }
486 486
487 if ((ret_size > size) || (ret_size <= 2)) { 487 if ((ret_size > size) || (ret_size < 2)) {
488 dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n", 488 dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
489 __func__, size, ret_size); 489 __func__, size, ret_size);
490 return; 490 return;
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index e3ce233f8bdc..23872d08308c 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -36,6 +36,7 @@
36#include <linux/hiddev.h> 36#include <linux/hiddev.h>
37#include <linux/compat.h> 37#include <linux/compat.h>
38#include <linux/vmalloc.h> 38#include <linux/vmalloc.h>
39#include <linux/nospec.h>
39#include "usbhid.h" 40#include "usbhid.h"
40 41
41#ifdef CONFIG_USB_DYNAMIC_MINORS 42#ifdef CONFIG_USB_DYNAMIC_MINORS
@@ -469,10 +470,14 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
469 470
470 if (uref->field_index >= report->maxfield) 471 if (uref->field_index >= report->maxfield)
471 goto inval; 472 goto inval;
473 uref->field_index = array_index_nospec(uref->field_index,
474 report->maxfield);
472 475
473 field = report->field[uref->field_index]; 476 field = report->field[uref->field_index];
474 if (uref->usage_index >= field->maxusage) 477 if (uref->usage_index >= field->maxusage)
475 goto inval; 478 goto inval;
479 uref->usage_index = array_index_nospec(uref->usage_index,
480 field->maxusage);
476 481
477 uref->usage_code = field->usage[uref->usage_index].hid; 482 uref->usage_code = field->usage[uref->usage_index].hid;
478 483
@@ -499,6 +504,8 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
499 504
500 if (uref->field_index >= report->maxfield) 505 if (uref->field_index >= report->maxfield)
501 goto inval; 506 goto inval;
507 uref->field_index = array_index_nospec(uref->field_index,
508 report->maxfield);
502 509
503 field = report->field[uref->field_index]; 510 field = report->field[uref->field_index];
504 511
@@ -753,6 +760,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
753 760
754 if (finfo.field_index >= report->maxfield) 761 if (finfo.field_index >= report->maxfield)
755 break; 762 break;
763 finfo.field_index = array_index_nospec(finfo.field_index,
764 report->maxfield);
756 765
757 field = report->field[finfo.field_index]; 766 field = report->field[finfo.field_index];
758 memset(&finfo, 0, sizeof(finfo)); 767 memset(&finfo, 0, sizeof(finfo));
@@ -797,6 +806,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
797 806
798 if (cinfo.index >= hid->maxcollection) 807 if (cinfo.index >= hid->maxcollection)
799 break; 808 break;
809 cinfo.index = array_index_nospec(cinfo.index,
810 hid->maxcollection);
800 811
801 cinfo.type = hid->collection[cinfo.index].type; 812 cinfo.type = hid->collection[cinfo.index].type;
802 cinfo.usage = hid->collection[cinfo.index].usage; 813 cinfo.usage = hid->collection[cinfo.index].usage;
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 0bb44d0088ed..ad7afa74d365 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -3365,8 +3365,14 @@ void wacom_setup_device_quirks(struct wacom *wacom)
3365 if (features->type >= INTUOSHT && features->type <= BAMBOO_PT) 3365 if (features->type >= INTUOSHT && features->type <= BAMBOO_PT)
3366 features->device_type |= WACOM_DEVICETYPE_PAD; 3366 features->device_type |= WACOM_DEVICETYPE_PAD;
3367 3367
3368 features->x_max = 4096; 3368 if (features->type == INTUOSHT2) {
3369 features->y_max = 4096; 3369 features->x_max = features->x_max / 10;
3370 features->y_max = features->y_max / 10;
3371 }
3372 else {
3373 features->x_max = 4096;
3374 features->y_max = 4096;
3375 }
3370 } 3376 }
3371 else if (features->pktlen == WACOM_PKGLEN_BBTOUCH) { 3377 else if (features->pktlen == WACOM_PKGLEN_BBTOUCH) {
3372 features->device_type |= WACOM_DEVICETYPE_PAD; 3378 features->device_type |= WACOM_DEVICETYPE_PAD;
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 41a3d5775394..773bcb1d4044 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -511,6 +511,7 @@ struct hid_output_fifo {
511#define HID_STAT_ADDED BIT(0) 511#define HID_STAT_ADDED BIT(0)
512#define HID_STAT_PARSED BIT(1) 512#define HID_STAT_PARSED BIT(1)
513#define HID_STAT_DUP_DETECTED BIT(2) 513#define HID_STAT_DUP_DETECTED BIT(2)
514#define HID_STAT_REPROBED BIT(3)
514 515
515struct hid_input { 516struct hid_input {
516 struct list_head list; 517 struct list_head list;
@@ -579,7 +580,7 @@ struct hid_device { /* device report descriptor */
579 bool battery_avoid_query; 580 bool battery_avoid_query;
580#endif 581#endif
581 582
582 unsigned int status; /* see STAT flags above */ 583 unsigned long status; /* see STAT flags above */
583 unsigned claimed; /* Claimed by hidinput, hiddev? */ 584 unsigned claimed; /* Claimed by hidinput, hiddev? */
584 unsigned quirks; /* Various quirks the device can pull on us */ 585 unsigned quirks; /* Various quirks the device can pull on us */
585 bool io_started; /* If IO has started */ 586 bool io_started; /* If IO has started */