]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
USB: serial: add endpoint sanity check to core
authorJohan Hovold <johan@kernel.org>
Thu, 2 Mar 2017 11:51:19 +0000 (12:51 +0100)
committerJohan Hovold <johan@kernel.org>
Thu, 16 Mar 2017 09:33:41 +0000 (10:33 +0100)
Allow drivers to specify a minimum number of endpoints per type, which
USB serial core will verify after subdriver probe has returned (where
the current alternate setting may have been changed).

Signed-off-by: Johan Hovold <johan@kernel.org>
drivers/usb/serial/usb-serial.c
include/linux/usb/serial.h

index ccc729d17a896b02a5208c10ab13ff3c923502ed..747dd414bef9bc16fcdcc5bf50e8fc7ab58ea082 100644 (file)
@@ -848,21 +848,26 @@ static int usb_serial_probe(struct usb_interface *interface,
                if (epds->num_bulk_in == 0 || epds->num_bulk_out == 0) {
                        dev_info(ddev, "PL-2303 hack: descriptors matched but endpoints did not\n");
                        retval = -ENODEV;
-                       kfree(epds);
-                       goto err_put_serial;
+                       goto err_free_epds;
                }
        }
        /* END HORRIBLE HACK FOR PL2303 */
 #endif
-
+       if (epds->num_bulk_in < type->num_bulk_in ||
+                       epds->num_bulk_out < type->num_bulk_out ||
+                       epds->num_interrupt_in < type->num_interrupt_in ||
+                       epds->num_interrupt_out < type->num_interrupt_out) {
+               dev_err(ddev, "required endpoints missing\n");
+               retval = -ENODEV;
+               goto err_free_epds;
+       }
 #ifdef CONFIG_USB_SERIAL_GENERIC
        if (type == &usb_serial_generic_device) {
                num_ports = epds->num_bulk_out;
                if (num_ports == 0) {
                        dev_err(ddev, "Generic device with no bulk out, not allowed.\n");
                        retval = -EIO;
-                       kfree(epds);
-                       goto err_put_serial;
+                       goto err_free_epds;
                }
                dev_info(ddev, "The \"generic\" usb-serial driver is only for testing and one-off prototypes.\n");
                dev_info(ddev, "Tell linux-usb@vger.kernel.org to add your device to a proper driver.\n");
@@ -1085,6 +1090,8 @@ static int usb_serial_probe(struct usb_interface *interface,
 
 probe_error:
        retval = -EIO;
+err_free_epds:
+       kfree(epds);
 err_put_serial:
        usb_serial_put(serial);
 err_put_module:
index ee4394d8932f2eb94815f1bb785f0cdf37a31f5b..f1b8a84937626cc66fea2153c657889cd65c6c31 100644 (file)
@@ -188,6 +188,10 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
  * @id_table: pointer to a list of usb_device_id structures that define all
  *     of the devices this structure can support.
  * @num_ports: the number of different ports this device will have.
+ * @num_bulk_in: minimum number of bulk-in endpoints
+ * @num_bulk_out: minimum number of bulk-out endpoints
+ * @num_interrupt_in: minimum number of interrupt-in endpoints
+ * @num_interrupt_out: minimum number of interrupt-out endpoints
  * @bulk_in_size: minimum number of bytes to allocate for bulk-in buffer
  *     (0 = end-point size)
  * @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size)
@@ -235,6 +239,11 @@ struct usb_serial_driver {
 
        unsigned char           num_ports;
 
+       unsigned char           num_bulk_in;
+       unsigned char           num_bulk_out;
+       unsigned char           num_interrupt_in;
+       unsigned char           num_interrupt_out;
+
        size_t                  bulk_in_size;
        size_t                  bulk_out_size;