Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1740784 > unrolled thread
| Started by | Alan Stern <stern@rowland.harvard.edu> |
|---|---|
| First post | 2017-09-27 16:30 +0200 |
| Last post | 2017-09-28 12:20 +0200 |
| Articles | 3 — 2 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: [PATCH] HID: usbhid: fix out-of-bounds bug Alan Stern <stern@rowland.harvard.edu> - 2017-09-27 16:30 +0200
Re: [PATCH] HID: usbhid: fix out-of-bounds bug Jaejoong Kim <climbbb.kim@gmail.com> - 2017-09-28 10:50 +0200
[PATCH v2] HID: usbhid: fix out-of-bounds bug Jaejoong Kim <climbbb.kim@gmail.com> - 2017-09-28 12:20 +0200
| From | Alan Stern <stern@rowland.harvard.edu> |
|---|---|
| Date | 2017-09-27 16:30 +0200 |
| Subject | Re: [PATCH] HID: usbhid: fix out-of-bounds bug |
| Message-ID | <uulvA-4kL-17@gated-at.bofh.it> |
On Wed, 27 Sep 2017, Michel Hermier wrote: > Le 27 sept. 2017 07:42, "Alan Stern" <stern@rowland.harvard.edu> a écrit : > > - for (n = 0; n < hdesc->bNumDescriptors; n++) > > + num_descriptors = min_t(int, hdesc->bNumDescriptors, > > + (hdesc->bLength - 6) / 3); > > + for (n = 0; n < num_descriptors; n++) > > if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) > > rsize = le16_to_cpu(hdesc->desc[n]. > wDescriptorLength); > > Yes, this is a lot better. > > > Is it possible to explicit the magic number 6 and 3 in the code. Currently, > it looks like it comes from no where. Yes, it is possible. The 6 is equal to offsetof(struct hid_descriptor, desc) and the 3 is equal to sizeof(struct hid_class_descriptor) (at least, I think it is -- the structure is marked as packed so its size should be 3). In this case I found the numbers to be more readable, but other people may have different opinions. > I'm also wondering if this change will not affect some devices in the wild, > by rejecting hid descriptors with num descriptors == 0 ? It's possible, but I doubt it. If such devices do exist, they should never have worked in the first place. Certainly they would generate warnings or errors during enumeration because of their invalid descriptors. Alan Stern
[toc] | [next] | [standalone]
| From | Jaejoong Kim <climbbb.kim@gmail.com> |
|---|---|
| Date | 2017-09-28 10:50 +0200 |
| Message-ID | <uuCG6-6IC-13@gated-at.bofh.it> |
| In reply to | #1740784 |
2017-09-27 23:29 GMT+09:00 Alan Stern <stern@rowland.harvard.edu>: > On Wed, 27 Sep 2017, Michel Hermier wrote: > >> Le 27 sept. 2017 07:42, "Alan Stern" <stern@rowland.harvard.edu> a écrit : > >> > - for (n = 0; n < hdesc->bNumDescriptors; n++) >> > + num_descriptors = min_t(int, hdesc->bNumDescriptors, >> > + (hdesc->bLength - 6) / 3); >> > + for (n = 0; n < num_descriptors; n++) >> > if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) >> > rsize = le16_to_cpu(hdesc->desc[n]. >> wDescriptorLength); >> >> Yes, this is a lot better. OK. >> >> >> Is it possible to explicit the magic number 6 and 3 in the code. Currently, >> it looks like it comes from no where. I gree with you. > > Yes, it is possible. The 6 is equal to > > offsetof(struct hid_descriptor, desc) > > and the 3 is equal to > > sizeof(struct hid_class_descriptor) > > (at least, I think it is -- the structure is marked as packed so its > size should be 3). > > In this case I found the numbers to be more readable, but other people > may have different opinions. I will post V2 shortly. > >> I'm also wondering if this change will not affect some devices in the wild, >> by rejecting hid descriptors with num descriptors == 0 ? > > It's possible, but I doubt it. If such devices do exist, they should > never have worked in the first place. Certainly they would generate > warnings or errors during enumeration because of their invalid > descriptors. > > Alan Stern > Jaejoong
[toc] | [prev] | [next] | [standalone]
| From | Jaejoong Kim <climbbb.kim@gmail.com> |
|---|---|
| Date | 2017-09-28 12:20 +0200 |
| Subject | [PATCH v2] HID: usbhid: fix out-of-bounds bug |
| Message-ID | <uuE5c-7Jz-9@gated-at.bofh.it> |
| In reply to | #1741301 |
The hid descriptor identifies the length and type of subordinate
descriptors for a device. If the received hid descriptor is smaller than
the size of the struct hid_descriptor, it is possible to cause
out-of-bounds.
In addition, if bNumDescriptors of the hid descriptor have an incorrect
value, this can also cause out-of-bounds while approaching hdesc->desc[n].
So check the size of hid descriptor and bNumDescriptors.
BUG: KASAN: slab-out-of-bounds in usbhid_parse+0x9b1/0xa20
Read of size 1 at addr ffff88006c5f8edf by task kworker/1:2/1261
CPU: 1 PID: 1261 Comm: kworker/1:2 Not tainted
4.14.0-rc1-42251-gebb2c2437d80 #169
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Workqueue: usb_hub_wq hub_event
Call Trace:
__dump_stack lib/dump_stack.c:16
dump_stack+0x292/0x395 lib/dump_stack.c:52
print_address_description+0x78/0x280 mm/kasan/report.c:252
kasan_report_error mm/kasan/report.c:351
kasan_report+0x22f/0x340 mm/kasan/report.c:409
__asan_report_load1_noabort+0x19/0x20 mm/kasan/report.c:427
usbhid_parse+0x9b1/0xa20 drivers/hid/usbhid/hid-core.c:1004
hid_add_device+0x16b/0xb30 drivers/hid/hid-core.c:2944
usbhid_probe+0xc28/0x1100 drivers/hid/usbhid/hid-core.c:1369
usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
really_probe drivers/base/dd.c:413
driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
__device_attach_driver+0x230/0x290 drivers/base/dd.c:653
bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
__device_attach+0x26e/0x3d0 drivers/base/dd.c:710
device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
device_add+0xd0b/0x1660 drivers/base/core.c:1835
usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932
generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174
usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266
really_probe drivers/base/dd.c:413
driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
__device_attach_driver+0x230/0x290 drivers/base/dd.c:653
bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
__device_attach+0x26e/0x3d0 drivers/base/dd.c:710
device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
device_add+0xd0b/0x1660 drivers/base/core.c:1835
usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457
hub_port_connect drivers/usb/core/hub.c:4903
hub_port_connect_change drivers/usb/core/hub.c:5009
port_event drivers/usb/core/hub.c:5115
hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195
process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119
worker_thread+0x221/0x1850 kernel/workqueue.c:2253
kthread+0x3a1/0x470 kernel/kthread.c:231
ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
Reported-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Jaejoong Kim <climbbb.kim@gmail.com>
---
Changes in v2:
- write a new commit message because orginal version is wrong approach
- add check hid descriptor size
- get proper value for bNumDescriptors as suggested by Alan Stern
- fix the Reported-by
drivers/hid/usbhid/hid-core.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 089bad8..045b5da 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -975,6 +975,8 @@ static int usbhid_parse(struct hid_device *hid)
unsigned int rsize = 0;
char *rdesc;
int ret, n;
+ int num_descriptors;
+ size_t offset = offsetof(struct hid_descriptor, desc);
quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
le16_to_cpu(dev->descriptor.idProduct));
@@ -997,10 +999,18 @@ static int usbhid_parse(struct hid_device *hid)
return -ENODEV;
}
+ if (hdesc->bLength < sizeof(struct hid_descriptor)) {
+ dbg_hid("hid descriptor is too short\n");
+ return -EINVAL;
+ }
+
hid->version = le16_to_cpu(hdesc->bcdHID);
hid->country = hdesc->bCountryCode;
- for (n = 0; n < hdesc->bNumDescriptors; n++)
+ num_descriptors = min_t(int, hdesc->bNumDescriptors,
+ (hdesc->bLength - offset) / sizeof(struct hid_class_descriptor));
+
+ for (n = 0; n < num_descriptors; n++)
if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)
rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
--
2.7.4
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web