This is a note to let you know that I've just added the patch titled
USB: serial: garmin_gps: fix I/O after failed probe and remove
to the 4.9-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git%3Ba=su...
The filename of the patch is: usb-serial-garmin_gps-fix-i-o-after-failed-probe-and-remove.patch and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let stable@vger.kernel.org know about it.
From 19a565d9af6e0d828bd0d521d3bafd5017f4ce52 Mon Sep 17 00:00:00 2001
From: Johan Hovold johan@kernel.org Date: Wed, 11 Oct 2017 14:02:57 +0200 Subject: USB: serial: garmin_gps: fix I/O after failed probe and remove
From: Johan Hovold johan@kernel.org
commit 19a565d9af6e0d828bd0d521d3bafd5017f4ce52 upstream.
Make sure to stop any submitted interrupt and bulk-out URBs before returning after failed probe and when the port is being unbound to avoid later NULL-pointer dereferences in the completion callbacks.
Also fix up the related and broken I/O cancellation on failed open and on close. (Note that port->write_urb was never submitted.)
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reviewed-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Johan Hovold johan@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/usb/serial/garmin_gps.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
--- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -138,6 +138,7 @@ struct garmin_data { __u8 privpkt[4*6]; spinlock_t lock; struct list_head pktlist; + struct usb_anchor write_urbs; };
@@ -905,7 +906,7 @@ static int garmin_init_session(struct us sizeof(GARMIN_START_SESSION_REQ), 0);
if (status < 0) - break; + goto err_kill_urbs; }
if (status > 0) @@ -913,6 +914,12 @@ static int garmin_init_session(struct us }
return status; + +err_kill_urbs: + usb_kill_anchored_urbs(&garmin_data_p->write_urbs); + usb_kill_urb(port->interrupt_in_urb); + + return status; }
@@ -930,7 +937,6 @@ static int garmin_open(struct tty_struct spin_unlock_irqrestore(&garmin_data_p->lock, flags);
/* shutdown any bulk reads that might be going on */ - usb_kill_urb(port->write_urb); usb_kill_urb(port->read_urb);
if (garmin_data_p->state == STATE_RESET) @@ -953,7 +959,7 @@ static void garmin_close(struct usb_seri
/* shutdown our urbs */ usb_kill_urb(port->read_urb); - usb_kill_urb(port->write_urb); + usb_kill_anchored_urbs(&garmin_data_p->write_urbs);
/* keep reset state so we know that we must start a new session */ if (garmin_data_p->state != STATE_RESET) @@ -1037,12 +1043,14 @@ static int garmin_write_bulk(struct usb_ }
/* send it down the pipe */ + usb_anchor_urb(urb, &garmin_data_p->write_urbs); status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", __func__, status); count = status; + usb_unanchor_urb(urb); kfree(buffer); }
@@ -1401,6 +1409,7 @@ static int garmin_port_probe(struct usb_ garmin_data_p->state = 0; garmin_data_p->flags = 0; garmin_data_p->count = 0; + init_usb_anchor(&garmin_data_p->write_urbs); usb_set_serial_port_data(port, garmin_data_p);
status = garmin_init_session(port); @@ -1413,6 +1422,7 @@ static int garmin_port_remove(struct usb { struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
+ usb_kill_anchored_urbs(&garmin_data_p->write_urbs); usb_kill_urb(port->interrupt_in_urb); del_timer_sync(&garmin_data_p->timer); kfree(garmin_data_p);
Patches currently in stable-queue which might be from johan@kernel.org are
queue-4.9/usb-serial-qcserial-add-pid-vid-for-sierra-wireless-em7355-fw-update.patch queue-4.9/staging-greybus-add-host-device-function-pointer-checks.patch queue-4.9/usb-serial-garmin_gps-fix-i-o-after-failed-probe-and-remove.patch queue-4.9/usb-serial-garmin_gps-fix-memory-leak-on-probe-errors.patch