Skip to content

Commit 4ae1efc

Browse files
jhovoldgregkh
authored andcommitted
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: 1da177e ("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>
1 parent af4e234 commit 4ae1efc

1 file changed

Lines changed: 9 additions & 4 deletions

File tree

drivers/usb/core/hub.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,8 @@ static void usb_set_lpm_parameters(struct usb_device *udev)
358358
}
359359

360360
/* USB 2.0 spec Section 11.24.4.5 */
361-
static int get_hub_descriptor(struct usb_device *hdev, void *data)
361+
static int get_hub_descriptor(struct usb_device *hdev,
362+
struct usb_hub_descriptor *desc)
362363
{
363364
int i, ret, size;
364365
unsigned dtype;
@@ -374,12 +375,16 @@ static int get_hub_descriptor(struct usb_device *hdev, void *data)
374375
for (i = 0; i < 3; i++) {
375376
ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
376377
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
377-
dtype << 8, 0, data, size,
378+
dtype << 8, 0, desc, size,
378379
USB_CTRL_GET_TIMEOUT);
379380
if (hub_is_superspeed(hdev)) {
380381
if (ret == size)
381382
return ret;
382-
} else if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2)) {
383+
} else if (ret >= USB_DT_HUB_NONVAR_SIZE + 2) {
384+
/* Make sure we have the DeviceRemovable field. */
385+
size = USB_DT_HUB_NONVAR_SIZE + desc->bNbrPorts / 8 + 1;
386+
if (ret < size)
387+
return -EMSGSIZE;
383388
return ret;
384389
}
385390
}
@@ -1299,7 +1304,7 @@ static int hub_configure(struct usb_hub *hub,
12991304
}
13001305
mutex_init(&hub->status_mutex);
13011306

1302-
hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
1307+
hub->descriptor = kzalloc(sizeof(*hub->descriptor), GFP_KERNEL);
13031308
if (!hub->descriptor) {
13041309
ret = -ENOMEM;
13051310
goto fail;

0 commit comments

Comments
 (0)