USB-serial fixes for v4.0-rc3
Here are a few fixes for reported problems including a usb-debug device buffer overflow, potential use-after-free on failed probe, and a couple of issues with the USB console. Some new device IDs are also added. Signed-off-by: Johan Hovold <johan@kernel.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJU+Fy4AAoJEEEN5E/e4bSVxSIQAM/ekC0n6/v2BqF+RJ+1YmGs pELjhVxgiUJ+TqgncxhFkbSVVKhBJ7JN8qOj2wV9r55WX8OgoGVoqFopz+PHeHWC 2JvPYkGi0UhCxCLto/XFnS8KYT+ODCqDF3E9CJKZEl6X3TGmQJ0Lyka953vYRWO3 0g3DwHGVdAHCH1ZZFJB4R/45i6ACLWd5A7zlyfvjrDYWfTgfONIFbaOjNATJFjre 3FyUXM2TP/AZNAcPYt8IUrbrUIriKptmQJk0F2gZEyLvYwlmJvtutpMLUL+Xs0Hx rbQVsQfKt7Plo2nkUkJ+1B/Q15+0aTyA5dqdXeYG77R6O5Y9v1c6fpc5Jr+fIPI/ jMP9LBeAUqQpKsLvtN4LG93a19r+0lJfdZtNTComLmSvQXYIiqRPNBlLmrBUN+Tq KG7TYHCoDsxw6jgMRPNLGn3lMEHxWej1lhI3UYSAXks1qixHLm+5+hVcqbKqMeaQ 2gX/xEHIFgaHNvfl9Hr1ke2vMxHB/tSt7DcrQVgBsBQgEP6PgvG+fQajoIZ7YQJC K+ElAwUiGeYq2Kqp8ljqVd+q1LyQo0w9B3eJSG5URnmLkxzQ4PPVf2tnVxy+xq3q N10cp/6vKLFATF4+Gu2dMGuSbK5LsNvOAGpjr6VDAqb2wAFmaT+MaQKQlgo/6TQH L/Cj0mx7uyGwhtPBZES6 =0CrX -----END PGP SIGNATURE----- Merge tag 'usb-serial-4.0-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-linus Johan writes: USB-serial fixes for v4.0-rc3 Here are a few fixes for reported problems including a usb-debug device buffer overflow, potential use-after-free on failed probe, and a couple of issues with the USB console. Some new device IDs are also added. Signed-off-by: Johan Hovold <johan@kernel.org>
This commit is contained in:
commit
d3d5389475
|
@ -38,56 +38,51 @@ static int usb_serial_device_match(struct device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t port_number_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_serial_port *port = to_usb_serial_port(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", port->port_number);
|
||||
}
|
||||
static DEVICE_ATTR_RO(port_number);
|
||||
|
||||
static int usb_serial_device_probe(struct device *dev)
|
||||
{
|
||||
struct usb_serial_driver *driver;
|
||||
struct usb_serial_port *port;
|
||||
struct device *tty_dev;
|
||||
int retval = 0;
|
||||
int minor;
|
||||
|
||||
port = to_usb_serial_port(dev);
|
||||
if (!port) {
|
||||
retval = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
if (!port)
|
||||
return -ENODEV;
|
||||
|
||||
/* make sure suspend/resume doesn't race against port_probe */
|
||||
retval = usb_autopm_get_interface(port->serial->interface);
|
||||
if (retval)
|
||||
goto exit;
|
||||
return retval;
|
||||
|
||||
driver = port->serial->type;
|
||||
if (driver->port_probe) {
|
||||
retval = driver->port_probe(port);
|
||||
if (retval)
|
||||
goto exit_with_autopm;
|
||||
}
|
||||
|
||||
retval = device_create_file(dev, &dev_attr_port_number);
|
||||
if (retval) {
|
||||
if (driver->port_remove)
|
||||
retval = driver->port_remove(port);
|
||||
goto exit_with_autopm;
|
||||
goto err_autopm_put;
|
||||
}
|
||||
|
||||
minor = port->minor;
|
||||
tty_register_device(usb_serial_tty_driver, minor, dev);
|
||||
tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev);
|
||||
if (IS_ERR(tty_dev)) {
|
||||
retval = PTR_ERR(tty_dev);
|
||||
goto err_port_remove;
|
||||
}
|
||||
|
||||
usb_autopm_put_interface(port->serial->interface);
|
||||
|
||||
dev_info(&port->serial->dev->dev,
|
||||
"%s converter now attached to ttyUSB%d\n",
|
||||
driver->description, minor);
|
||||
|
||||
exit_with_autopm:
|
||||
return 0;
|
||||
|
||||
err_port_remove:
|
||||
if (driver->port_remove)
|
||||
driver->port_remove(port);
|
||||
err_autopm_put:
|
||||
usb_autopm_put_interface(port->serial->interface);
|
||||
exit:
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -114,8 +109,6 @@ static int usb_serial_device_remove(struct device *dev)
|
|||
minor = port->minor;
|
||||
tty_unregister_device(usb_serial_tty_driver, minor);
|
||||
|
||||
device_remove_file(&port->dev, &dev_attr_port_number);
|
||||
|
||||
driver = port->serial->type;
|
||||
if (driver->port_remove)
|
||||
retval = driver->port_remove(port);
|
||||
|
|
|
@ -84,6 +84,10 @@ struct ch341_private {
|
|||
u8 line_status; /* active status of modem control inputs */
|
||||
};
|
||||
|
||||
static void ch341_set_termios(struct tty_struct *tty,
|
||||
struct usb_serial_port *port,
|
||||
struct ktermios *old_termios);
|
||||
|
||||
static int ch341_control_out(struct usb_device *dev, u8 request,
|
||||
u16 value, u16 index)
|
||||
{
|
||||
|
@ -309,19 +313,12 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
struct ch341_private *priv = usb_get_serial_port_data(port);
|
||||
int r;
|
||||
|
||||
priv->baud_rate = DEFAULT_BAUD_RATE;
|
||||
|
||||
r = ch341_configure(serial->dev, priv);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
r = ch341_set_handshake(serial->dev, priv->line_control);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
r = ch341_set_baudrate(serial->dev, priv);
|
||||
if (r)
|
||||
goto out;
|
||||
if (tty)
|
||||
ch341_set_termios(tty, port, NULL);
|
||||
|
||||
dev_dbg(&port->dev, "%s - submitting interrupt urb\n", __func__);
|
||||
r = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/console.h>
|
||||
|
@ -144,6 +145,7 @@ static int usb_console_setup(struct console *co, char *options)
|
|||
init_ldsem(&tty->ldisc_sem);
|
||||
INIT_LIST_HEAD(&tty->tty_files);
|
||||
kref_get(&tty->driver->kref);
|
||||
__module_get(tty->driver->owner);
|
||||
tty->ops = &usb_console_fake_tty_ops;
|
||||
if (tty_init_termios(tty)) {
|
||||
retval = -ENOMEM;
|
||||
|
|
|
@ -147,6 +147,8 @@ static const struct usb_device_id id_table[] = {
|
|||
{ USB_DEVICE(0x166A, 0x0305) }, /* Clipsal C-5000CT2 C-Bus Spectrum Colour Touchscreen */
|
||||
{ USB_DEVICE(0x166A, 0x0401) }, /* Clipsal L51xx C-Bus Architectural Dimmer */
|
||||
{ USB_DEVICE(0x166A, 0x0101) }, /* Clipsal 5560884 C-Bus Multi-room Audio Matrix Switcher */
|
||||
{ USB_DEVICE(0x16C0, 0x09B0) }, /* Lunatico Seletek */
|
||||
{ USB_DEVICE(0x16C0, 0x09B1) }, /* Lunatico Seletek */
|
||||
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
|
||||
{ USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */
|
||||
{ USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
|
||||
|
|
|
@ -799,6 +799,8 @@ static const struct usb_device_id id_table_combined[] = {
|
|||
{ USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID),
|
||||
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
|
||||
{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
|
||||
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
|
||||
{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID),
|
||||
|
@ -978,6 +980,23 @@ static const struct usb_device_id id_table_combined[] = {
|
|||
{ USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) },
|
||||
/* GE Healthcare devices */
|
||||
{ USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) },
|
||||
/* Active Research (Actisense) devices */
|
||||
{ USB_DEVICE(FTDI_VID, ACTISENSE_NDC_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, ACTISENSE_USG_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, ACTISENSE_NGT_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, ACTISENSE_NGW_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, ACTISENSE_D9AC_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, ACTISENSE_D9AD_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, ACTISENSE_D9AE_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, ACTISENSE_D9AF_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, CHETCO_SEAGAUGE_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, CHETCO_SEASWITCH_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, CHETCO_SEASMART_NMEA2000_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ETHERNET_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, CHETCO_SEASMART_WIFI_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
|
|
@ -38,6 +38,9 @@
|
|||
|
||||
#define FTDI_LUMEL_PD12_PID 0x6002
|
||||
|
||||
/* Cyber Cortex AV by Fabulous Silicon (http://fabuloussilicon.com) */
|
||||
#define CYBER_CORTEX_AV_PID 0x8698
|
||||
|
||||
/*
|
||||
* Marvell OpenRD Base, Client
|
||||
* http://www.open-rd.org
|
||||
|
@ -1438,3 +1441,23 @@
|
|||
*/
|
||||
#define GE_HEALTHCARE_VID 0x1901
|
||||
#define GE_HEALTHCARE_NEMO_TRACKER_PID 0x0015
|
||||
|
||||
/*
|
||||
* Active Research (Actisense) devices
|
||||
*/
|
||||
#define ACTISENSE_NDC_PID 0xD9A8 /* NDC USB Serial Adapter */
|
||||
#define ACTISENSE_USG_PID 0xD9A9 /* USG USB Serial Adapter */
|
||||
#define ACTISENSE_NGT_PID 0xD9AA /* NGT NMEA2000 Interface */
|
||||
#define ACTISENSE_NGW_PID 0xD9AB /* NGW NMEA2000 Gateway */
|
||||
#define ACTISENSE_D9AC_PID 0xD9AC /* Actisense Reserved */
|
||||
#define ACTISENSE_D9AD_PID 0xD9AD /* Actisense Reserved */
|
||||
#define ACTISENSE_D9AE_PID 0xD9AE /* Actisense Reserved */
|
||||
#define ACTISENSE_D9AF_PID 0xD9AF /* Actisense Reserved */
|
||||
#define CHETCO_SEAGAUGE_PID 0xA548 /* SeaGauge USB Adapter */
|
||||
#define CHETCO_SEASWITCH_PID 0xA549 /* SeaSwitch USB Adapter */
|
||||
#define CHETCO_SEASMART_NMEA2000_PID 0xA54A /* SeaSmart NMEA2000 Gateway */
|
||||
#define CHETCO_SEASMART_ETHERNET_PID 0xA54B /* SeaSmart Ethernet Gateway */
|
||||
#define CHETCO_SEASMART_WIFI_PID 0xA5AC /* SeaSmart Wifi Gateway */
|
||||
#define CHETCO_SEASMART_DISPLAY_PID 0xA5AD /* SeaSmart NMEA2000 Display */
|
||||
#define CHETCO_SEASMART_LITE_PID 0xA5AE /* SeaSmart Lite USB Adapter */
|
||||
#define CHETCO_SEASMART_ANALOG_PID 0xA5AF /* SeaSmart Analog Adapter */
|
||||
|
|
|
@ -1284,7 +1284,8 @@ static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
}
|
||||
|
||||
/* Initial port termios */
|
||||
mxuport_set_termios(tty, port, NULL);
|
||||
if (tty)
|
||||
mxuport_set_termios(tty, port, NULL);
|
||||
|
||||
/*
|
||||
* TODO: use RQ_VENDOR_GET_MSR, once we know what it
|
||||
|
|
|
@ -132,6 +132,7 @@ MODULE_DEVICE_TABLE(usb, id_table);
|
|||
#define UART_OVERRUN_ERROR 0x40
|
||||
#define UART_CTS 0x80
|
||||
|
||||
static void pl2303_set_break(struct usb_serial_port *port, bool enable);
|
||||
|
||||
enum pl2303_type {
|
||||
TYPE_01, /* Type 0 and 1 (difference unknown) */
|
||||
|
@ -615,6 +616,7 @@ static void pl2303_close(struct usb_serial_port *port)
|
|||
{
|
||||
usb_serial_generic_close(port);
|
||||
usb_kill_urb(port->interrupt_in_urb);
|
||||
pl2303_set_break(port, false);
|
||||
}
|
||||
|
||||
static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
|
@ -741,17 +743,16 @@ static int pl2303_ioctl(struct tty_struct *tty,
|
|||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
|
||||
static void pl2303_set_break(struct usb_serial_port *port, bool enable)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct usb_serial *serial = port->serial;
|
||||
u16 state;
|
||||
int result;
|
||||
|
||||
if (break_state == 0)
|
||||
state = BREAK_OFF;
|
||||
else
|
||||
if (enable)
|
||||
state = BREAK_ON;
|
||||
else
|
||||
state = BREAK_OFF;
|
||||
|
||||
dev_dbg(&port->dev, "%s - turning break %s\n", __func__,
|
||||
state == BREAK_OFF ? "off" : "on");
|
||||
|
@ -763,6 +764,13 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
|
|||
dev_err(&port->dev, "error sending break = %d\n", result);
|
||||
}
|
||||
|
||||
static void pl2303_break_ctl(struct tty_struct *tty, int state)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
|
||||
pl2303_set_break(port, state);
|
||||
}
|
||||
|
||||
static void pl2303_update_line_status(struct usb_serial_port *port,
|
||||
unsigned char *data,
|
||||
unsigned int actual_length)
|
||||
|
|
|
@ -687,6 +687,21 @@ static void serial_port_dtr_rts(struct tty_port *port, int on)
|
|||
drv->dtr_rts(p, on);
|
||||
}
|
||||
|
||||
static ssize_t port_number_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct usb_serial_port *port = to_usb_serial_port(dev);
|
||||
|
||||
return sprintf(buf, "%u\n", port->port_number);
|
||||
}
|
||||
static DEVICE_ATTR_RO(port_number);
|
||||
|
||||
static struct attribute *usb_serial_port_attrs[] = {
|
||||
&dev_attr_port_number.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(usb_serial_port);
|
||||
|
||||
static const struct tty_port_operations serial_port_ops = {
|
||||
.carrier_raised = serial_port_carrier_raised,
|
||||
.dtr_rts = serial_port_dtr_rts,
|
||||
|
@ -902,6 +917,7 @@ static int usb_serial_probe(struct usb_interface *interface,
|
|||
port->dev.driver = NULL;
|
||||
port->dev.bus = &usb_serial_bus_type;
|
||||
port->dev.release = &usb_serial_port_release;
|
||||
port->dev.groups = usb_serial_port_groups;
|
||||
device_initialize(&port->dev);
|
||||
}
|
||||
|
||||
|
@ -940,8 +956,9 @@ static int usb_serial_probe(struct usb_interface *interface,
|
|||
port = serial->port[i];
|
||||
if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
|
||||
goto probe_error;
|
||||
buffer_size = max_t(int, serial->type->bulk_out_size,
|
||||
usb_endpoint_maxp(endpoint));
|
||||
buffer_size = serial->type->bulk_out_size;
|
||||
if (!buffer_size)
|
||||
buffer_size = usb_endpoint_maxp(endpoint);
|
||||
port->bulk_out_size = buffer_size;
|
||||
port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
|
||||
|
||||
|
|
|
@ -190,8 +190,7 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
|
|||
* @num_ports: the number of different ports this device will have.
|
||||
* @bulk_in_size: minimum number of bytes to allocate for bulk-in buffer
|
||||
* (0 = end-point size)
|
||||
* @bulk_out_size: minimum number of bytes to allocate for bulk-out buffer
|
||||
* (0 = end-point size)
|
||||
* @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size)
|
||||
* @calc_num_ports: pointer to a function to determine how many ports this
|
||||
* device has dynamically. It will be called after the probe()
|
||||
* callback is called, but before attach()
|
||||
|
|
Loading…
Reference in New Issue