| From c7ab34984e996eab21806bebca059a434070d042 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 12 Feb 2026 21:41:54 +0000 |
| Subject: net: usb: catc: enable basic endpoint checking |
| |
| From: Ziyi Guo <n7l8m4@u.northwestern.edu> |
| |
| [ Upstream commit 9e7021d2aeae57c323a6f722ed7915686cdcc123 ] |
| |
| 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> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/usb/catc.c | 37 +++++++++++++++++++++++++++++++------ |
| 1 file changed, 31 insertions(+), 6 deletions(-) |
| |
| diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c |
| index ff439ef535ac9..98346cb4ece01 100644 |
| --- a/drivers/net/usb/catc.c |
| +++ b/drivers/net/usb/catc.c |
| @@ -64,6 +64,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. |
| */ |
| @@ -772,6 +782,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) |
| @@ -784,6 +801,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; |
| @@ -828,14 +853,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; |
| -- |
| 2.51.0 |
| |