diff options
author | Johan Hovold <johan@kernel.org> | 2017-01-03 10:39:59 -0500 |
---|---|---|
committer | Johan Hovold <johan@kernel.org> | 2017-01-04 04:43:48 -0500 |
commit | 5afeef2366db14587b65558bbfd5a067542e07fb (patch) | |
tree | 0992e2a3fea460f1738ed0935be9e5b02e82f124 /drivers/usb | |
parent | a5bc01949e3b19d8a23b5eabc6fc71bb50dc820e (diff) |
USB: serial: oti6858: fix NULL-deref at open
Fix NULL-pointer dereference in open() should the device lack the
expected endpoints:
Unable to handle kernel NULL pointer dereference at virtual address 00000030
...
PC is at oti6858_open+0x30/0x1d0 [oti6858]
Note that a missing interrupt-in endpoint would have caused open() to
fail.
Fixes: 49cdee0ed0fc ("USB: oti6858 usb-serial driver (in Nokia CA-42
cable)")
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/oti6858.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index a4b88bc038b6..b8bf52bf7a94 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c | |||
@@ -134,6 +134,7 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty); | |||
134 | static int oti6858_tiocmget(struct tty_struct *tty); | 134 | static int oti6858_tiocmget(struct tty_struct *tty); |
135 | static int oti6858_tiocmset(struct tty_struct *tty, | 135 | static int oti6858_tiocmset(struct tty_struct *tty, |
136 | unsigned int set, unsigned int clear); | 136 | unsigned int set, unsigned int clear); |
137 | static int oti6858_attach(struct usb_serial *serial); | ||
137 | static int oti6858_port_probe(struct usb_serial_port *port); | 138 | static int oti6858_port_probe(struct usb_serial_port *port); |
138 | static int oti6858_port_remove(struct usb_serial_port *port); | 139 | static int oti6858_port_remove(struct usb_serial_port *port); |
139 | 140 | ||
@@ -158,6 +159,7 @@ static struct usb_serial_driver oti6858_device = { | |||
158 | .write_bulk_callback = oti6858_write_bulk_callback, | 159 | .write_bulk_callback = oti6858_write_bulk_callback, |
159 | .write_room = oti6858_write_room, | 160 | .write_room = oti6858_write_room, |
160 | .chars_in_buffer = oti6858_chars_in_buffer, | 161 | .chars_in_buffer = oti6858_chars_in_buffer, |
162 | .attach = oti6858_attach, | ||
161 | .port_probe = oti6858_port_probe, | 163 | .port_probe = oti6858_port_probe, |
162 | .port_remove = oti6858_port_remove, | 164 | .port_remove = oti6858_port_remove, |
163 | }; | 165 | }; |
@@ -324,6 +326,20 @@ static void send_data(struct work_struct *work) | |||
324 | usb_serial_port_softint(port); | 326 | usb_serial_port_softint(port); |
325 | } | 327 | } |
326 | 328 | ||
329 | static int oti6858_attach(struct usb_serial *serial) | ||
330 | { | ||
331 | unsigned char num_ports = serial->num_ports; | ||
332 | |||
333 | if (serial->num_bulk_in < num_ports || | ||
334 | serial->num_bulk_out < num_ports || | ||
335 | serial->num_interrupt_in < num_ports) { | ||
336 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
337 | return -ENODEV; | ||
338 | } | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
327 | static int oti6858_port_probe(struct usb_serial_port *port) | 343 | static int oti6858_port_probe(struct usb_serial_port *port) |
328 | { | 344 | { |
329 | struct oti6858_private *priv; | 345 | struct oti6858_private *priv; |