On 15.11.21 08:28, syzbot wrote: > Hello, > > syzbot found the following issue on: > > HEAD commit: 048ff8629e11 Merge tag 'usb-5.16-rc1' of git://git.kernel... > git tree: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing > console output: https://syzkaller.appspot.com/x/log.txt?x=1480ade1b00000 > kernel config: https://syzkaller.appspot.com/x/.config?x=d6b387bc5d3e50f3 > dashboard link: https://syzkaller.appspot.com/bug?extid=63ee658b9a100ffadbe2 > compiler: gcc (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for Debian) 2.35.2 > syz repro: https://syzkaller.appspot.com/x/repro.syz?x=1313cb7cb00000 > C reproducer: https://syzkaller.appspot.com/x/repro.c?x=16a2f676b00000 > > IMPORTANT: if you fix the issue, please add the following tag to the commit: > Reported-by: syzbot+63ee658b9a100ffadbe2@xxxxxxxxxxxxxxxxxxxxxxxxx > #syz test https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git 048ff8629e11
>From 853e421630f82fb3b7005ad0b294c091a064ac39 Mon Sep 17 00:00:00 2001 From: Oliver Neukum <oneukum@xxxxxxxx> Date: Thu, 18 Nov 2021 18:15:03 +0100 Subject: [PATCH] usbnet: sanity check for endpoint types A malicious device can pretend to be a device with a known configuration of endpoints yet present endpoints of the wrong type or too few or none at all. Signed-off-by: Oliver Neukum <oneukum@xxxxxxxx> --- drivers/net/usb/usbnet.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 9a6450f796dc..b1f93810a6f3 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -91,6 +91,31 @@ static const char * const usbnet_event_names[] = { [EVENT_NO_IP_ALIGN] = "EVENT_NO_IP_ALIGN", }; +bool usbnet_validate_endpoints(struct usbnet *dev, struct usb_interface *intf, const struct driver_info *info) +{ + struct usb_host_interface *alt = intf->cur_altsetting; + struct usb_host_endpoint *e; + int num_endpoints = alt->desc.bNumEndpoints; + + if (info->in > num_endpoints) + return false; + e = alt->endpoint + info->in; + if (!e) + return false; + if (!usb_endpoint_is_bulk_in(&e->desc)) + return false; + + if (info->out > num_endpoints) + return false; + e = alt->endpoint + info->out; + if (!e) + return false; + if (!usb_endpoint_is_bulk_out(&e->desc)) + return false; + + return true; +} + /* handles CDC Ethernet and many other network "bulk data" interfaces */ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf) { @@ -1772,6 +1797,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) } else if (!info->in || !info->out) status = usbnet_get_endpoints (dev, udev); else { + if (!usbnet_validate_endpoints(dev, udev, info)) + goto out3; dev->in = usb_rcvbulkpipe (xdev, info->in); dev->out = usb_sndbulkpipe (xdev, info->out); if (!(info->flags & FLAG_NO_SETINT)) -- 2.26.2