diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2012-10-10 14:10:21 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-16 13:25:55 -0400 |
commit | db5c8b524444d4fc6b1f32d368a50a3729e50002 (patch) | |
tree | ed09dfb961fd6c505dc292cf26335e7110db5fe3 | |
parent | 8bf769eb5f6efc33f95088850f33fcc05d28b508 (diff) |
USB: fix port probing and removal in garmin_gps
This patch (as1615) fixes a bug in the Garmin USB serial driver. It
uses attach, disconnect, and release routines to carry out actions
that should be handled by port_probe and port_remove routines, because
they access port-specific data.
The bug causes an oops when the device in unplugged, because the
private data for each port structure now gets erased when the port is
unbound from the driver, resulting in a null-pointer dereference.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Reported--by: Markus Schauler <mschauler@gmail.com>
Tested-by: Markus Schauler <mschauler@gmail.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/usb/serial/garmin_gps.c | 24 |
1 files changed, 7 insertions, 17 deletions
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 3ee92648c02d..203358d7e7bc 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c | |||
@@ -1405,11 +1405,10 @@ static void timeout_handler(unsigned long data) | |||
1405 | 1405 | ||
1406 | 1406 | ||
1407 | 1407 | ||
1408 | static int garmin_attach(struct usb_serial *serial) | 1408 | static int garmin_port_probe(struct usb_serial_port *port) |
1409 | { | 1409 | { |
1410 | int status = 0; | 1410 | int status; |
1411 | struct usb_serial_port *port = serial->port[0]; | 1411 | struct garmin_data *garmin_data_p; |
1412 | struct garmin_data *garmin_data_p = NULL; | ||
1413 | 1412 | ||
1414 | garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL); | 1413 | garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL); |
1415 | if (garmin_data_p == NULL) { | 1414 | if (garmin_data_p == NULL) { |
@@ -1434,22 +1433,14 @@ static int garmin_attach(struct usb_serial *serial) | |||
1434 | } | 1433 | } |
1435 | 1434 | ||
1436 | 1435 | ||
1437 | static void garmin_disconnect(struct usb_serial *serial) | 1436 | static int garmin_port_remove(struct usb_serial_port *port) |
1438 | { | 1437 | { |
1439 | struct usb_serial_port *port = serial->port[0]; | ||
1440 | struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); | 1438 | struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); |
1441 | 1439 | ||
1442 | usb_kill_urb(port->interrupt_in_urb); | 1440 | usb_kill_urb(port->interrupt_in_urb); |
1443 | del_timer_sync(&garmin_data_p->timer); | 1441 | del_timer_sync(&garmin_data_p->timer); |
1444 | } | ||
1445 | |||
1446 | |||
1447 | static void garmin_release(struct usb_serial *serial) | ||
1448 | { | ||
1449 | struct usb_serial_port *port = serial->port[0]; | ||
1450 | struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); | ||
1451 | |||
1452 | kfree(garmin_data_p); | 1442 | kfree(garmin_data_p); |
1443 | return 0; | ||
1453 | } | 1444 | } |
1454 | 1445 | ||
1455 | 1446 | ||
@@ -1466,9 +1457,8 @@ static struct usb_serial_driver garmin_device = { | |||
1466 | .close = garmin_close, | 1457 | .close = garmin_close, |
1467 | .throttle = garmin_throttle, | 1458 | .throttle = garmin_throttle, |
1468 | .unthrottle = garmin_unthrottle, | 1459 | .unthrottle = garmin_unthrottle, |
1469 | .attach = garmin_attach, | 1460 | .port_probe = garmin_port_probe, |
1470 | .disconnect = garmin_disconnect, | 1461 | .port_remove = garmin_port_remove, |
1471 | .release = garmin_release, | ||
1472 | .write = garmin_write, | 1462 | .write = garmin_write, |
1473 | .write_room = garmin_write_room, | 1463 | .write_room = garmin_write_room, |
1474 | .write_bulk_callback = garmin_write_bulk_callback, | 1464 | .write_bulk_callback = garmin_write_bulk_callback, |