Skip to content

Commit

Permalink
USB: Gadget: dummy-hcd: Fix shift-out-of-bounds bug
Browse files Browse the repository at this point in the history
commit c318840 upstream.

The dummy-hcd driver was written under the assumption that all the
parameters in URBs sent to its root hub would be valid.  With URBs
sent from userspace via usbfs, that assumption can be violated.

In particular, the driver doesn't fully check the port-feature values
stored in the wValue entry of Clear-Port-Feature and Set-Port-Feature
requests.  Values that are too large can cause the driver to perform
an invalid left shift of more than 32 bits.  Ironically, two of those
left shifts are unnecessary, because they implement Set-Port-Feature
requests that hubs are not required to support, according to section
11.24.2.13 of the USB-2.0 spec.

This patch adds the appropriate checks for the port feature selector
values and removes the unnecessary feature settings.  It also rejects
requests to set the TEST feature or to set or clear the INDICATOR and
C_OVERCURRENT features, as none of these are relevant to dummy-hcd's
root-hub emulation.

CC: <stable@vger.kernel.org>
Reported-and-tested-by: syzbot+5925509f78293baa7331@syzkaller.appspotmail.com
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Link: https://lore.kernel.org/r/20201230162044.GA727759@rowland.harvard.edu
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
AlanStern authored and gregkh committed Jan 12, 2021
1 parent 2cd6988 commit e7f2c25
Showing 1 changed file with 23 additions and 12 deletions.
35 changes: 23 additions & 12 deletions drivers/usb/gadget/udc/dummy_hcd.c
Expand Up @@ -2114,9 +2114,21 @@ static int dummy_hub_control(
dum_hcd->port_status &= ~USB_PORT_STAT_POWER;
set_link_state(dum_hcd);
break;
default:
case USB_PORT_FEAT_ENABLE:
case USB_PORT_FEAT_C_ENABLE:
case USB_PORT_FEAT_C_SUSPEND:
/* Not allowed for USB-3 */
if (hcd->speed == HCD_USB3)
goto error;
fallthrough;
case USB_PORT_FEAT_C_CONNECTION:
case USB_PORT_FEAT_C_RESET:
dum_hcd->port_status &= ~(1 << wValue);
set_link_state(dum_hcd);
break;
default:
/* Disallow INDICATOR and C_OVER_CURRENT */
goto error;
}
break;
case GetHubDescriptor:
Expand Down Expand Up @@ -2277,18 +2289,17 @@ static int dummy_hub_control(
*/
dum_hcd->re_timeout = jiffies + msecs_to_jiffies(50);
fallthrough;
case USB_PORT_FEAT_C_CONNECTION:
case USB_PORT_FEAT_C_RESET:
case USB_PORT_FEAT_C_ENABLE:
case USB_PORT_FEAT_C_SUSPEND:
/* Not allowed for USB-3, and ignored for USB-2 */
if (hcd->speed == HCD_USB3)
goto error;
break;
default:
if (hcd->speed == HCD_USB3) {
if ((dum_hcd->port_status &
USB_SS_PORT_STAT_POWER) != 0) {
dum_hcd->port_status |= (1 << wValue);
}
} else
if ((dum_hcd->port_status &
USB_PORT_STAT_POWER) != 0) {
dum_hcd->port_status |= (1 << wValue);
}
set_link_state(dum_hcd);
/* Disallow TEST, INDICATOR, and C_OVER_CURRENT */
goto error;
}
break;
case GetPortErrorCount:
Expand Down

0 comments on commit e7f2c25

Please sign in to comment.