]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: usb: catc: enable basic endpoint checking
authorZiyi Guo <n7l8m4@u.northwestern.edu>
Thu, 12 Feb 2026 21:41:54 +0000 (21:41 +0000)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 17 Feb 2026 10:53:36 +0000 (11:53 +0100)
catc_probe() fills three URBs with hardcoded endpoint pipes without
verifying the endpoint descriptors:

  - usb_sndbulkpipe(usbdev, 1) and usb_rcvbulkpipe(usbdev, 1) for TX/RX
  - usb_rcvintpipe(usbdev, 2) for interrupt status

A malformed USB device can present these endpoints with transfer types
that differ from what the driver assumes.

Add a catc_usb_ep enum for endpoint numbers, replacing magic constants
throughout. Add usb_check_bulk_endpoints() and usb_check_int_endpoints()
calls after usb_set_interface() to verify endpoint types before use,
rejecting devices with mismatched descriptors at probe time.

Similar to
- commit 90b7f2961798 ("net: usb: rtl8150: enable basic endpoint checking")
which fixed the issue in rtl8150.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Suggested-by: Simon Horman <horms@kernel.org>
Signed-off-by: Ziyi Guo <n7l8m4@u.northwestern.edu>
Link: https://patch.msgid.link/20260212214154.3609844-1-n7l8m4@u.northwestern.edu
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/usb/catc.c

index 5c7f19cbacf619bee958a98a672962afefb2077f..96e82f94edcf818fc6ce9f7b548a543dde6dc0e3 100644 (file)
@@ -58,6 +58,16 @@ static const char driver_name[] = "catc";
 #define CTRL_QUEUE             16      /* Max control requests in flight (power of two) */
 #define RX_PKT_SZ              1600    /* Max size of receive packet for F5U011 */
 
+/*
+ * USB endpoints.
+ */
+
+enum catc_usb_ep {
+       CATC_USB_EP_CONTROL     = 0,
+       CATC_USB_EP_BULK        = 1,
+       CATC_USB_EP_INT_IN      = 2,
+};
+
 /*
  * Control requests.
  */
@@ -765,6 +775,13 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
        u8 broadcast[ETH_ALEN];
        u8 *macbuf;
        int pktsz, ret = -ENOMEM;
+       static const u8 bulk_ep_addr[] = {
+               CATC_USB_EP_BULK | USB_DIR_OUT,
+               CATC_USB_EP_BULK | USB_DIR_IN,
+               0};
+       static const u8 int_ep_addr[] = {
+               CATC_USB_EP_INT_IN | USB_DIR_IN,
+               0};
 
        macbuf = kmalloc(ETH_ALEN, GFP_KERNEL);
        if (!macbuf)
@@ -777,6 +794,14 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
                goto fail_mem;
        }
 
+       /* Verify that all required endpoints are present */
+       if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) ||
+           !usb_check_int_endpoints(intf, int_ep_addr)) {
+               dev_err(dev, "Missing or invalid endpoints\n");
+               ret = -ENODEV;
+               goto fail_mem;
+       }
+
        netdev = alloc_etherdev(sizeof(struct catc));
        if (!netdev)
                goto fail_mem;
@@ -821,14 +846,14 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
        usb_fill_control_urb(catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0),
                NULL, NULL, 0, catc_ctrl_done, catc);
 
-       usb_fill_bulk_urb(catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, 1),
-               NULL, 0, catc_tx_done, catc);
+       usb_fill_bulk_urb(catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, CATC_USB_EP_BULK),
+                         NULL, 0, catc_tx_done, catc);
 
-       usb_fill_bulk_urb(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1),
-               catc->rx_buf, pktsz, catc_rx_done, catc);
+       usb_fill_bulk_urb(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, CATC_USB_EP_BULK),
+                         catc->rx_buf, pktsz, catc_rx_done, catc);
 
-       usb_fill_int_urb(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2),
-                catc->irq_buf, 2, catc_irq_done, catc, 1);
+       usb_fill_int_urb(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, CATC_USB_EP_INT_IN),
+                        catc->irq_buf, 2, catc_irq_done, catc, 1);
 
        if (!catc->is_f5u011) {
                u32 *buf;