aboutsummaryrefslogtreecommitdiffstats
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-17 05:53:02 -0400
commitbec444cd1c94c48df409a35ad4e5b143c245c3f7 (patch)
tree0ac8f95b7677441adafef1e513c2d56955e08586
parent2c25a2c818023df64463aac3288a9f969491e507 (diff)
USB: hub: fix non-SS hub-descriptor handling
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") Cc: stable <stable@vger.kernel.org> # 2.6.12 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>
-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 3ff1e9f89f2d..f77a4ebde7d5 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -362,7 +362,8 @@ static void usb_set_lpm_parameters(struct usb_device *udev)
362} 362}
363 363
364/* USB 2.0 spec Section 11.24.4.5 */ 364/* USB 2.0 spec Section 11.24.4.5 */
365static int get_hub_descriptor(struct usb_device *hdev, void *data) 365static int get_hub_descriptor(struct usb_device *hdev,
366 struct usb_hub_descriptor *desc)
366{ 367{
367 int i, ret, size; 368 int i, ret, size;
368 unsigned dtype; 369 unsigned dtype;
@@ -378,12 +379,16 @@ static int get_hub_descriptor(struct usb_device *hdev, void *data)
378 for (i = 0; i < 3; i++) { 379 for (i = 0; i < 3; i++) {
379 ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), 380 ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
380 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, 381 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
381 dtype << 8, 0, data, size, 382 dtype << 8, 0, desc, size,
382 USB_CTRL_GET_TIMEOUT); 383 USB_CTRL_GET_TIMEOUT);
383 if (hub_is_superspeed(hdev)) { 384 if (hub_is_superspeed(hdev)) {
384 if (ret == size) 385 if (ret == size)
385 return ret; 386 return ret;
386 } else if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2)) { 387 } else if (ret >= USB_DT_HUB_NONVAR_SIZE + 2) {
388 /* Make sure we have the DeviceRemovable field. */
389 size = USB_DT_HUB_NONVAR_SIZE + desc->bNbrPorts / 8 + 1;
390 if (ret < size)
391 return -EMSGSIZE;
387 return ret; 392 return ret;
388 } 393 }
389 } 394 }
@@ -1317,7 +1322,7 @@ static int hub_configure(struct usb_hub *hub,
1317 } 1322 }
1318 mutex_init(&hub->status_mutex); 1323 mutex_init(&hub->status_mutex);
1319 1324
1320 hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); 1325 hub->descriptor = kzalloc(sizeof(*hub->descriptor), GFP_KERNEL);
1321 if (!hub->descriptor) { 1326 if (!hub->descriptor) {
1322 ret = -ENOMEM; 1327 ret = -ENOMEM;
1323 goto fail; 1328 goto fail;