Skip to content

Commit

Permalink
USB: gadgetfs: fix checks of wTotalLength in config descriptors
Browse files Browse the repository at this point in the history
Andrey Konovalov's fuzz testing of gadgetfs showed that we should
improve the driver's checks for valid configuration descriptors passed
in by the user.  In particular, the driver needs to verify that the
wTotalLength value in the descriptor is not too short (smaller
than USB_DT_CONFIG_SIZE).  And the check for whether wTotalLength is
too large has to be changed, because the driver assumes there is
always enough room remaining in the buffer to hold a device descriptor
(at least USB_DT_DEVICE_SIZE bytes).

This patch adds the additional check and fixes the existing check.  It
may do a little more than strictly necessary, but one extra check
won't hurt.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
CC: Andrey Konovalov <andreyknvl@google.com>
CC: <stable@vger.kernel.org>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
  • Loading branch information
AlanStern authored and Felipe Balbi committed Jan 2, 2017
1 parent add333a commit 1c069b0
Showing 1 changed file with 7 additions and 3 deletions.
10 changes: 7 additions & 3 deletions drivers/usb/gadget/legacy/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1734,10 +1734,12 @@ static struct usb_gadget_driver gadgetfs_driver = {
* such as configuration notifications.
*/

static int is_valid_config (struct usb_config_descriptor *config)
static int is_valid_config(struct usb_config_descriptor *config,
unsigned int total)
{
return config->bDescriptorType == USB_DT_CONFIG
&& config->bLength == USB_DT_CONFIG_SIZE
&& total >= USB_DT_CONFIG_SIZE
&& config->bConfigurationValue != 0
&& (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0
&& (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 0;
Expand Down Expand Up @@ -1787,7 +1789,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
/* full or low speed config */
dev->config = (void *) kbuf;
total = le16_to_cpu(dev->config->wTotalLength);
if (!is_valid_config (dev->config) || total >= length)
if (!is_valid_config(dev->config, total) ||
total > length - USB_DT_DEVICE_SIZE)
goto fail;
kbuf += total;
length -= total;
Expand All @@ -1796,7 +1799,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
if (kbuf [1] == USB_DT_CONFIG) {
dev->hs_config = (void *) kbuf;
total = le16_to_cpu(dev->hs_config->wTotalLength);
if (!is_valid_config (dev->hs_config) || total >= length)
if (!is_valid_config(dev->hs_config, total) ||
total > length - USB_DT_DEVICE_SIZE)
goto fail;
kbuf += total;
length -= total;
Expand Down

0 comments on commit 1c069b0

Please sign in to comment.