Skip to content

Commit d3d5389

Browse files
committed
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 <[email protected]>
2 parents b20b161 + c7d373c commit d3d5389

File tree

10 files changed

+106
-45
lines changed

10 files changed

+106
-45
lines changed

drivers/usb/serial/bus.c

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -38,56 +38,51 @@ static int usb_serial_device_match(struct device *dev,
3838
return 0;
3939
}
4040

41-
static ssize_t port_number_show(struct device *dev,
42-
struct device_attribute *attr, char *buf)
43-
{
44-
struct usb_serial_port *port = to_usb_serial_port(dev);
45-
46-
return sprintf(buf, "%d\n", port->port_number);
47-
}
48-
static DEVICE_ATTR_RO(port_number);
49-
5041
static int usb_serial_device_probe(struct device *dev)
5142
{
5243
struct usb_serial_driver *driver;
5344
struct usb_serial_port *port;
45+
struct device *tty_dev;
5446
int retval = 0;
5547
int minor;
5648

5749
port = to_usb_serial_port(dev);
58-
if (!port) {
59-
retval = -ENODEV;
60-
goto exit;
61-
}
50+
if (!port)
51+
return -ENODEV;
6252

6353
/* make sure suspend/resume doesn't race against port_probe */
6454
retval = usb_autopm_get_interface(port->serial->interface);
6555
if (retval)
66-
goto exit;
56+
return retval;
6757

6858
driver = port->serial->type;
6959
if (driver->port_probe) {
7060
retval = driver->port_probe(port);
7161
if (retval)
72-
goto exit_with_autopm;
62+
goto err_autopm_put;
7363
}
7464

75-
retval = device_create_file(dev, &dev_attr_port_number);
76-
if (retval) {
77-
if (driver->port_remove)
78-
retval = driver->port_remove(port);
79-
goto exit_with_autopm;
65+
minor = port->minor;
66+
tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev);
67+
if (IS_ERR(tty_dev)) {
68+
retval = PTR_ERR(tty_dev);
69+
goto err_port_remove;
8070
}
8171

82-
minor = port->minor;
83-
tty_register_device(usb_serial_tty_driver, minor, dev);
72+
usb_autopm_put_interface(port->serial->interface);
73+
8474
dev_info(&port->serial->dev->dev,
8575
"%s converter now attached to ttyUSB%d\n",
8676
driver->description, minor);
8777

88-
exit_with_autopm:
78+
return 0;
79+
80+
err_port_remove:
81+
if (driver->port_remove)
82+
driver->port_remove(port);
83+
err_autopm_put:
8984
usb_autopm_put_interface(port->serial->interface);
90-
exit:
85+
9186
return retval;
9287
}
9388

@@ -114,8 +109,6 @@ static int usb_serial_device_remove(struct device *dev)
114109
minor = port->minor;
115110
tty_unregister_device(usb_serial_tty_driver, minor);
116111

117-
device_remove_file(&port->dev, &dev_attr_port_number);
118-
119112
driver = port->serial->type;
120113
if (driver->port_remove)
121114
retval = driver->port_remove(port);

drivers/usb/serial/ch341.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ struct ch341_private {
8484
u8 line_status; /* active status of modem control inputs */
8585
};
8686

87+
static void ch341_set_termios(struct tty_struct *tty,
88+
struct usb_serial_port *port,
89+
struct ktermios *old_termios);
90+
8791
static int ch341_control_out(struct usb_device *dev, u8 request,
8892
u16 value, u16 index)
8993
{
@@ -309,19 +313,12 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
309313
struct ch341_private *priv = usb_get_serial_port_data(port);
310314
int r;
311315

312-
priv->baud_rate = DEFAULT_BAUD_RATE;
313-
314316
r = ch341_configure(serial->dev, priv);
315317
if (r)
316318
goto out;
317319

318-
r = ch341_set_handshake(serial->dev, priv->line_control);
319-
if (r)
320-
goto out;
321-
322-
r = ch341_set_baudrate(serial->dev, priv);
323-
if (r)
324-
goto out;
320+
if (tty)
321+
ch341_set_termios(tty, port, NULL);
325322

326323
dev_dbg(&port->dev, "%s - submitting interrupt urb\n", __func__);
327324
r = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);

drivers/usb/serial/console.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1515

1616
#include <linux/kernel.h>
17+
#include <linux/module.h>
1718
#include <linux/slab.h>
1819
#include <linux/tty.h>
1920
#include <linux/console.h>
@@ -144,6 +145,7 @@ static int usb_console_setup(struct console *co, char *options)
144145
init_ldsem(&tty->ldisc_sem);
145146
INIT_LIST_HEAD(&tty->tty_files);
146147
kref_get(&tty->driver->kref);
148+
__module_get(tty->driver->owner);
147149
tty->ops = &usb_console_fake_tty_ops;
148150
if (tty_init_termios(tty)) {
149151
retval = -ENOMEM;

drivers/usb/serial/cp210x.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ static const struct usb_device_id id_table[] = {
147147
{ USB_DEVICE(0x166A, 0x0305) }, /* Clipsal C-5000CT2 C-Bus Spectrum Colour Touchscreen */
148148
{ USB_DEVICE(0x166A, 0x0401) }, /* Clipsal L51xx C-Bus Architectural Dimmer */
149149
{ USB_DEVICE(0x166A, 0x0101) }, /* Clipsal 5560884 C-Bus Multi-room Audio Matrix Switcher */
150+
{ USB_DEVICE(0x16C0, 0x09B0) }, /* Lunatico Seletek */
151+
{ USB_DEVICE(0x16C0, 0x09B1) }, /* Lunatico Seletek */
150152
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
151153
{ USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */
152154
{ USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */

drivers/usb/serial/ftdi_sio.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,8 @@ static const struct usb_device_id id_table_combined[] = {
799799
{ USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
800800
{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) },
801801
{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) },
802+
{ USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID),
803+
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
802804
{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
803805
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
804806
{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID),
@@ -978,6 +980,23 @@ static const struct usb_device_id id_table_combined[] = {
978980
{ USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) },
979981
/* GE Healthcare devices */
980982
{ USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) },
983+
/* Active Research (Actisense) devices */
984+
{ USB_DEVICE(FTDI_VID, ACTISENSE_NDC_PID) },
985+
{ USB_DEVICE(FTDI_VID, ACTISENSE_USG_PID) },
986+
{ USB_DEVICE(FTDI_VID, ACTISENSE_NGT_PID) },
987+
{ USB_DEVICE(FTDI_VID, ACTISENSE_NGW_PID) },
988+
{ USB_DEVICE(FTDI_VID, ACTISENSE_D9AC_PID) },
989+
{ USB_DEVICE(FTDI_VID, ACTISENSE_D9AD_PID) },
990+
{ USB_DEVICE(FTDI_VID, ACTISENSE_D9AE_PID) },
991+
{ USB_DEVICE(FTDI_VID, ACTISENSE_D9AF_PID) },
992+
{ USB_DEVICE(FTDI_VID, CHETCO_SEAGAUGE_PID) },
993+
{ USB_DEVICE(FTDI_VID, CHETCO_SEASWITCH_PID) },
994+
{ USB_DEVICE(FTDI_VID, CHETCO_SEASMART_NMEA2000_PID) },
995+
{ USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ETHERNET_PID) },
996+
{ USB_DEVICE(FTDI_VID, CHETCO_SEASMART_WIFI_PID) },
997+
{ USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) },
998+
{ USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) },
999+
{ USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) },
9811000
{ } /* Terminating entry */
9821001
};
9831002

drivers/usb/serial/ftdi_sio_ids.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838

3939
#define FTDI_LUMEL_PD12_PID 0x6002
4040

41+
/* Cyber Cortex AV by Fabulous Silicon (http://fabuloussilicon.com) */
42+
#define CYBER_CORTEX_AV_PID 0x8698
43+
4144
/*
4245
* Marvell OpenRD Base, Client
4346
* http://www.open-rd.org
@@ -1438,3 +1441,23 @@
14381441
*/
14391442
#define GE_HEALTHCARE_VID 0x1901
14401443
#define GE_HEALTHCARE_NEMO_TRACKER_PID 0x0015
1444+
1445+
/*
1446+
* Active Research (Actisense) devices
1447+
*/
1448+
#define ACTISENSE_NDC_PID 0xD9A8 /* NDC USB Serial Adapter */
1449+
#define ACTISENSE_USG_PID 0xD9A9 /* USG USB Serial Adapter */
1450+
#define ACTISENSE_NGT_PID 0xD9AA /* NGT NMEA2000 Interface */
1451+
#define ACTISENSE_NGW_PID 0xD9AB /* NGW NMEA2000 Gateway */
1452+
#define ACTISENSE_D9AC_PID 0xD9AC /* Actisense Reserved */
1453+
#define ACTISENSE_D9AD_PID 0xD9AD /* Actisense Reserved */
1454+
#define ACTISENSE_D9AE_PID 0xD9AE /* Actisense Reserved */
1455+
#define ACTISENSE_D9AF_PID 0xD9AF /* Actisense Reserved */
1456+
#define CHETCO_SEAGAUGE_PID 0xA548 /* SeaGauge USB Adapter */
1457+
#define CHETCO_SEASWITCH_PID 0xA549 /* SeaSwitch USB Adapter */
1458+
#define CHETCO_SEASMART_NMEA2000_PID 0xA54A /* SeaSmart NMEA2000 Gateway */
1459+
#define CHETCO_SEASMART_ETHERNET_PID 0xA54B /* SeaSmart Ethernet Gateway */
1460+
#define CHETCO_SEASMART_WIFI_PID 0xA5AC /* SeaSmart Wifi Gateway */
1461+
#define CHETCO_SEASMART_DISPLAY_PID 0xA5AD /* SeaSmart NMEA2000 Display */
1462+
#define CHETCO_SEASMART_LITE_PID 0xA5AE /* SeaSmart Lite USB Adapter */
1463+
#define CHETCO_SEASMART_ANALOG_PID 0xA5AF /* SeaSmart Analog Adapter */

drivers/usb/serial/mxuport.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1284,7 +1284,8 @@ static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port)
12841284
}
12851285

12861286
/* Initial port termios */
1287-
mxuport_set_termios(tty, port, NULL);
1287+
if (tty)
1288+
mxuport_set_termios(tty, port, NULL);
12881289

12891290
/*
12901291
* TODO: use RQ_VENDOR_GET_MSR, once we know what it

drivers/usb/serial/pl2303.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ MODULE_DEVICE_TABLE(usb, id_table);
132132
#define UART_OVERRUN_ERROR 0x40
133133
#define UART_CTS 0x80
134134

135+
static void pl2303_set_break(struct usb_serial_port *port, bool enable);
135136

136137
enum pl2303_type {
137138
TYPE_01, /* Type 0 and 1 (difference unknown) */
@@ -615,6 +616,7 @@ static void pl2303_close(struct usb_serial_port *port)
615616
{
616617
usb_serial_generic_close(port);
617618
usb_kill_urb(port->interrupt_in_urb);
619+
pl2303_set_break(port, false);
618620
}
619621

620622
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,
741743
return -ENOIOCTLCMD;
742744
}
743745

744-
static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
746+
static void pl2303_set_break(struct usb_serial_port *port, bool enable)
745747
{
746-
struct usb_serial_port *port = tty->driver_data;
747748
struct usb_serial *serial = port->serial;
748749
u16 state;
749750
int result;
750751

751-
if (break_state == 0)
752-
state = BREAK_OFF;
753-
else
752+
if (enable)
754753
state = BREAK_ON;
754+
else
755+
state = BREAK_OFF;
755756

756757
dev_dbg(&port->dev, "%s - turning break %s\n", __func__,
757758
state == BREAK_OFF ? "off" : "on");
@@ -763,6 +764,13 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
763764
dev_err(&port->dev, "error sending break = %d\n", result);
764765
}
765766

767+
static void pl2303_break_ctl(struct tty_struct *tty, int state)
768+
{
769+
struct usb_serial_port *port = tty->driver_data;
770+
771+
pl2303_set_break(port, state);
772+
}
773+
766774
static void pl2303_update_line_status(struct usb_serial_port *port,
767775
unsigned char *data,
768776
unsigned int actual_length)

drivers/usb/serial/usb-serial.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,21 @@ static void serial_port_dtr_rts(struct tty_port *port, int on)
687687
drv->dtr_rts(p, on);
688688
}
689689

690+
static ssize_t port_number_show(struct device *dev,
691+
struct device_attribute *attr, char *buf)
692+
{
693+
struct usb_serial_port *port = to_usb_serial_port(dev);
694+
695+
return sprintf(buf, "%u\n", port->port_number);
696+
}
697+
static DEVICE_ATTR_RO(port_number);
698+
699+
static struct attribute *usb_serial_port_attrs[] = {
700+
&dev_attr_port_number.attr,
701+
NULL
702+
};
703+
ATTRIBUTE_GROUPS(usb_serial_port);
704+
690705
static const struct tty_port_operations serial_port_ops = {
691706
.carrier_raised = serial_port_carrier_raised,
692707
.dtr_rts = serial_port_dtr_rts,
@@ -902,6 +917,7 @@ static int usb_serial_probe(struct usb_interface *interface,
902917
port->dev.driver = NULL;
903918
port->dev.bus = &usb_serial_bus_type;
904919
port->dev.release = &usb_serial_port_release;
920+
port->dev.groups = usb_serial_port_groups;
905921
device_initialize(&port->dev);
906922
}
907923

@@ -940,8 +956,9 @@ static int usb_serial_probe(struct usb_interface *interface,
940956
port = serial->port[i];
941957
if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
942958
goto probe_error;
943-
buffer_size = max_t(int, serial->type->bulk_out_size,
944-
usb_endpoint_maxp(endpoint));
959+
buffer_size = serial->type->bulk_out_size;
960+
if (!buffer_size)
961+
buffer_size = usb_endpoint_maxp(endpoint);
945962
port->bulk_out_size = buffer_size;
946963
port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
947964

include/linux/usb/serial.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,7 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
190190
* @num_ports: the number of different ports this device will have.
191191
* @bulk_in_size: minimum number of bytes to allocate for bulk-in buffer
192192
* (0 = end-point size)
193-
* @bulk_out_size: minimum number of bytes to allocate for bulk-out buffer
194-
* (0 = end-point size)
193+
* @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size)
195194
* @calc_num_ports: pointer to a function to determine how many ports this
196195
* device has dynamically. It will be called after the probe()
197196
* callback is called, but before attach()

0 commit comments

Comments
 (0)