diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-07-09 20:16:11 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-07-09 20:16:11 -0400 |
| commit | 092150a25cb7bd6a79aa00bb1ad131063f58073d (patch) | |
| tree | bc182ea7bb8f5b83c6853ce407483a8814076e21 | |
| parent | bdf33113d89f70186ffb6674e925fa9b8a0266b1 (diff) | |
| parent | 4f65245f2d178b9cba48350620d76faa4a098841 (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.c | 5 | ||||
| -rw-r--r-- | drivers/hid/hid-debug.c | 8 | ||||
| -rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.c | 2 | ||||
| -rw-r--r-- | drivers/hid/usbhid/hiddev.c | 11 | ||||
| -rw-r--r-- | drivers/hid/wacom_wac.c | 10 | ||||
| -rw-r--r-- | include/linux/hid.h | 3 |
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 | ||
| 515 | struct hid_input { | 516 | struct 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 */ |
