]> www.infradead.org Git - linux.git/commitdiff
char: xillybus: Check USB endpoints when probing device
authorEli Billauer <eli.billauer@gmail.com>
Fri, 16 Aug 2024 07:02:00 +0000 (10:02 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 16 Aug 2024 07:57:56 +0000 (09:57 +0200)
Ensure, as the driver probes the device, that all endpoints that the
driver may attempt to access exist and are of the correct type.

All XillyUSB devices must have a Bulk IN and Bulk OUT endpoint at
address 1. This is verified in xillyusb_setup_base_eps().

On top of that, a XillyUSB device may have additional Bulk OUT
endpoints. The information about these endpoints' addresses is deduced
from a data structure (the IDT) that the driver fetches from the device
while probing it. These endpoints are checked in setup_channels().

A XillyUSB device never has more than one IN endpoint, as all data
towards the host is multiplexed in this single Bulk IN endpoint. This is
why setup_channels() only checks OUT endpoints.

Reported-by: syzbot+eac39cba052f2e750dbe@syzkaller.appspotmail.com
Cc: stable <stable@kernel.org>
Closes: https://lore.kernel.org/all/0000000000001d44a6061f7a54ee@google.com/T/
Fixes: a53d1202aef1 ("char: xillybus: Add driver for XillyUSB (Xillybus variant for USB)").
Signed-off-by: Eli Billauer <eli.billauer@gmail.com>
Link: https://lore.kernel.org/r/20240816070200.50695-2-eli.billauer@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/char/xillybus/xillyusb.c

index e12d359194f89db78aaa5bc0f7e18c8ef2a138d7..45771b1a3716a2ae3fc3c0d558d757841ff0df39 100644 (file)
@@ -1903,6 +1903,13 @@ static const struct file_operations xillyusb_fops = {
 
 static int xillyusb_setup_base_eps(struct xillyusb_dev *xdev)
 {
+       struct usb_device *udev = xdev->udev;
+
+       /* Verify that device has the two fundamental bulk in/out endpoints */
+       if (usb_pipe_type_check(udev, usb_sndbulkpipe(udev, MSG_EP_NUM)) ||
+           usb_pipe_type_check(udev, usb_rcvbulkpipe(udev, IN_EP_NUM)))
+               return -ENODEV;
+
        xdev->msg_ep = endpoint_alloc(xdev, MSG_EP_NUM | USB_DIR_OUT,
                                      bulk_out_work, 1, 2);
        if (!xdev->msg_ep)
@@ -1932,14 +1939,15 @@ static int setup_channels(struct xillyusb_dev *xdev,
                          __le16 *chandesc,
                          int num_channels)
 {
-       struct xillyusb_channel *chan;
+       struct usb_device *udev = xdev->udev;
+       struct xillyusb_channel *chan, *new_channels;
        int i;
 
        chan = kcalloc(num_channels, sizeof(*chan), GFP_KERNEL);
        if (!chan)
                return -ENOMEM;
 
-       xdev->channels = chan;
+       new_channels = chan;
 
        for (i = 0; i < num_channels; i++, chan++) {
                unsigned int in_desc = le16_to_cpu(*chandesc++);
@@ -1968,6 +1976,15 @@ static int setup_channels(struct xillyusb_dev *xdev,
                 */
 
                if ((out_desc & 0x80) && i < 14) { /* Entry is valid */
+                       if (usb_pipe_type_check(udev,
+                                               usb_sndbulkpipe(udev, i + 2))) {
+                               dev_err(xdev->dev,
+                                       "Missing BULK OUT endpoint %d\n",
+                                       i + 2);
+                               kfree(new_channels);
+                               return -ENODEV;
+                       }
+
                        chan->writable = 1;
                        chan->out_synchronous = !!(out_desc & 0x40);
                        chan->out_seekable = !!(out_desc & 0x20);
@@ -1977,6 +1994,7 @@ static int setup_channels(struct xillyusb_dev *xdev,
                }
        }
 
+       xdev->channels = new_channels;
        return 0;
 }