Commit 1a44fb38 authored by Hayes Wang's avatar Hayes Wang Committed by David S. Miller

r8152: check the informaton of the device

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: c2198943 ("r8152: search the configuration of vendor mode")
Signed-off-by: default avatarHayes Wang <hayeswang@realtek.com>
Reviewed-by: default avatarJohan Hovold <johan@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9b76eade
...@@ -8107,6 +8107,37 @@ static void r8156b_init(struct r8152 *tp) ...@@ -8107,6 +8107,37 @@ static void r8156b_init(struct r8152 *tp)
tp->coalesce = 15000; /* 15 us */ 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) static bool rtl_vendor_mode(struct usb_interface *intf)
{ {
struct usb_host_interface *alt = intf->cur_altsetting; struct usb_host_interface *alt = intf->cur_altsetting;
...@@ -8115,12 +8146,15 @@ static bool rtl_vendor_mode(struct usb_interface *intf) ...@@ -8115,12 +8146,15 @@ static bool rtl_vendor_mode(struct usb_interface *intf)
int i, num_configs; int i, num_configs;
if (alt->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) 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. */ /* The vendor mode is not always config #1, so to find it out. */
udev = interface_to_usbdev(intf); udev = interface_to_usbdev(intf);
c = udev->config; c = udev->config;
num_configs = udev->descriptor.bNumConfigurations; num_configs = udev->descriptor.bNumConfigurations;
if (num_configs < 2)
return false;
for (i = 0; i < num_configs; (i++, c++)) { for (i = 0; i < num_configs; (i++, c++)) {
struct usb_interface_descriptor *desc = NULL; struct usb_interface_descriptor *desc = NULL;
...@@ -8135,7 +8169,8 @@ static bool rtl_vendor_mode(struct usb_interface *intf) ...@@ -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; return false;
} }
...@@ -9381,9 +9416,6 @@ static int rtl8152_probe(struct usb_interface *intf, ...@@ -9381,9 +9416,6 @@ static int rtl8152_probe(struct usb_interface *intf,
if (!rtl_vendor_mode(intf)) if (!rtl_vendor_mode(intf))
return -ENODEV; return -ENODEV;
if (intf->cur_altsetting->desc.bNumEndpoints < 3)
return -ENODEV;
usb_reset_device(udev); usb_reset_device(udev);
netdev = alloc_etherdev(sizeof(struct r8152)); netdev = alloc_etherdev(sizeof(struct r8152));
if (!netdev) { if (!netdev) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment