Skip to content

Commit

Permalink
r8152: check the informaton of the device
Browse files Browse the repository at this point in the history
Verify some fields of the USB descriptor to make sure the driver
could be used by the device.

Besides, remove the check of endpoint number in rtl8152_probe().
usb_find_common_endpoints() includes it.

BugLink: https://syzkaller.appspot.com/bug?id=912c9c373656996801b4de61f1e3cb326fe940aa
Reported-by: syzbot+95afd23673f5dd295c57@syzkaller.appspotmail.com
Fixes: c219894 ("r8152: search the configuration of vendor mode")
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
Reviewed-by: Johan Hovold <johan@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Hayes Wang authored and David S. Miller committed May 24, 2021
1 parent 9b76ead commit 1a44fb3
Showing 1 changed file with 37 additions and 5 deletions.
42 changes: 37 additions & 5 deletions drivers/net/usb/r8152.c
Original file line number Diff line number Diff line change
Expand Up @@ -8107,6 +8107,37 @@ static void r8156b_init(struct r8152 *tp)
tp->coalesce = 15000; /* 15 us */
}

static bool rtl_check_vendor_ok(struct usb_interface *intf)
{
struct usb_host_interface *alt = intf->cur_altsetting;
struct usb_endpoint_descriptor *in, *out, *intr;

if (usb_find_common_endpoints(alt, &in, &out, &intr, NULL) < 0) {
dev_err(&intf->dev, "Expected endpoints are not found\n");
return false;
}

/* Check Rx endpoint address */
if (usb_endpoint_num(in) != 1) {
dev_err(&intf->dev, "Invalid Rx endpoint address\n");
return false;
}

/* Check Tx endpoint address */
if (usb_endpoint_num(out) != 2) {
dev_err(&intf->dev, "Invalid Tx endpoint address\n");
return false;
}

/* Check interrupt endpoint address */
if (usb_endpoint_num(intr) != 3) {
dev_err(&intf->dev, "Invalid interrupt endpoint address\n");
return false;
}

return true;
}

static bool rtl_vendor_mode(struct usb_interface *intf)
{
struct usb_host_interface *alt = intf->cur_altsetting;
Expand All @@ -8115,12 +8146,15 @@ static bool rtl_vendor_mode(struct usb_interface *intf)
int i, num_configs;

if (alt->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC)
return true;
return rtl_check_vendor_ok(intf);

/* The vendor mode is not always config #1, so to find it out. */
udev = interface_to_usbdev(intf);
c = udev->config;
num_configs = udev->descriptor.bNumConfigurations;
if (num_configs < 2)
return false;

for (i = 0; i < num_configs; (i++, c++)) {
struct usb_interface_descriptor *desc = NULL;

Expand All @@ -8135,7 +8169,8 @@ static bool rtl_vendor_mode(struct usb_interface *intf)
}
}

WARN_ON_ONCE(i == num_configs);
if (i == num_configs)
dev_err(&intf->dev, "Unexpected Device\n");

return false;
}
Expand Down Expand Up @@ -9381,9 +9416,6 @@ static int rtl8152_probe(struct usb_interface *intf,
if (!rtl_vendor_mode(intf))
return -ENODEV;

if (intf->cur_altsetting->desc.bNumEndpoints < 3)
return -ENODEV;

usb_reset_device(udev);
netdev = alloc_etherdev(sizeof(struct r8152));
if (!netdev) {
Expand Down

0 comments on commit 1a44fb3

Please sign in to comment.