aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJohan Hovold <johan@kernel.org>2017-05-10 12:18:28 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-25 09:44:41 -0400
commitc67e87a22dd8b39ea1c9864336f7c17175053744 (patch)
tree9785912fbdb2720945993b32449697ecdc6201c1 /drivers
parent3e4a4e68df087008be9686a9d5cefd90d5341587 (diff)
USB: hub: fix non-SS hub-descriptor handling
commit bec444cd1c94c48df409a35ad4e5b143c245c3f7 upstream. Add missing sanity check on the non-SuperSpeed hub-descriptor length in order to avoid parsing and leaking two bytes of uninitialised slab data through sysfs removable-attributes (or a compound-device debug statement). Note that we only make sure that the DeviceRemovable field is always present (and specifically ignore the unused PortPwrCtrlMask field) in order to continue support any hubs with non-compliant descriptors. As a further safeguard, the descriptor buffer is also cleared. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Johan Hovold <johan@kernel.org> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/core/hub.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 8c59bc857a4b..8714b352e57f 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -360,7 +360,8 @@ static void usb_set_lpm_parameters(struct usb_device *udev)
360} 360}
361 361
362/* USB 2.0 spec Section 11.24.4.5 */ 362/* USB 2.0 spec Section 11.24.4.5 */
363static int get_hub_descriptor(struct usb_device *hdev, void *data) 363static int get_hub_descriptor(struct usb_device *hdev,
364 struct usb_hub_descriptor *desc)
364{ 365{
365 int i, ret, size; 366 int i, ret, size;
366 unsigned dtype; 367 unsigned dtype;
@@ -376,12 +377,16 @@ static int get_hub_descriptor(struct usb_device *hdev, void *data)
376 for (i = 0; i < 3; i++) { 377 for (i = 0; i < 3; i++) {
377 ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), 378 ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
378 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, 379 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
379 dtype << 8, 0, data, size, 380 dtype << 8, 0, desc, size,
380 USB_CTRL_GET_TIMEOUT); 381 USB_CTRL_GET_TIMEOUT);
381 if (hub_is_superspeed(hdev)) { 382 if (hub_is_superspeed(hdev)) {
382 if (ret == size) 383 if (ret == size)
383 return ret; 384 return ret;
384 } else if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2)) { 385 } else if (ret >= USB_DT_HUB_NONVAR_SIZE + 2) {
386 /* Make sure we have the DeviceRemovable field. */
387 size = USB_DT_HUB_NONVAR_SIZE + desc->bNbrPorts / 8 + 1;
388 if (ret < size)
389 return -EMSGSIZE;
385 return ret; 390 return ret;
386 } 391 }
387 } 392 }
@@ -1315,7 +1320,7 @@ static int hub_configure(struct usb_hub *hub,
1315 } 1320 }
1316 mutex_init(&hub->status_mutex); 1321 mutex_init(&hub->status_mutex);
1317 1322
1318 hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); 1323 hub->descriptor = kzalloc(sizeof(*hub->descriptor), GFP_KERNEL);
1319 if (!hub->descriptor) { 1324 if (!hub->descriptor) {
1320 ret = -ENOMEM; 1325 ret = -ENOMEM;
1321 goto fail; 1326 goto fail;