Commit 9e7021d2 authored by Ziyi Guo's avatar Ziyi Guo Committed by Paolo Abeni
Browse files

net: usb: catc: enable basic endpoint checking



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 90b7f296 ("net: usb: rtl8150: enable basic endpoint checking")
which fixed the issue in rtl8150.

Fixes: 1da177e4 ("Linux-2.6.12-rc2")
Suggested-by: default avatarSimon Horman <horms@kernel.org>
Signed-off-by: default avatarZiyi Guo <n7l8m4@u.northwestern.edu>
Link: https://patch.msgid.link/20260212214154.3609844-1-n7l8m4@u.northwestern.edu


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 94560267
Loading
Loading
Loading
Loading
+31 −6
Original line number Diff line number Diff line
@@ -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,13 +846,13 @@ 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),
	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),
	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),
	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) {