Skip to content

Commit 8b36209

Browse files
jhovoldgregkh
authored andcommitted
USB: serial: garmin_gps: fix I/O after failed probe and remove
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: 1da177e ("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>
1 parent 5cd9385 commit 8b36209

1 file changed

Lines changed: 13 additions & 3 deletions

File tree

drivers/usb/serial/garmin_gps.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ struct garmin_data {
138138
__u8 privpkt[4*6];
139139
spinlock_t lock;
140140
struct list_head pktlist;
141+
struct usb_anchor write_urbs;
141142
};
142143

143144

@@ -906,13 +907,19 @@ static int garmin_init_session(struct usb_serial_port *port)
906907
sizeof(GARMIN_START_SESSION_REQ), 0);
907908

908909
if (status < 0)
909-
break;
910+
goto err_kill_urbs;
910911
}
911912

912913
if (status > 0)
913914
status = 0;
914915
}
915916

917+
return status;
918+
919+
err_kill_urbs:
920+
usb_kill_anchored_urbs(&garmin_data_p->write_urbs);
921+
usb_kill_urb(port->interrupt_in_urb);
922+
916923
return status;
917924
}
918925

@@ -931,7 +938,6 @@ static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port)
931938
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
932939

933940
/* shutdown any bulk reads that might be going on */
934-
usb_kill_urb(port->write_urb);
935941
usb_kill_urb(port->read_urb);
936942

937943
if (garmin_data_p->state == STATE_RESET)
@@ -954,7 +960,7 @@ static void garmin_close(struct usb_serial_port *port)
954960

955961
/* shutdown our urbs */
956962
usb_kill_urb(port->read_urb);
957-
usb_kill_urb(port->write_urb);
963+
usb_kill_anchored_urbs(&garmin_data_p->write_urbs);
958964

959965
/* keep reset state so we know that we must start a new session */
960966
if (garmin_data_p->state != STATE_RESET)
@@ -1038,12 +1044,14 @@ static int garmin_write_bulk(struct usb_serial_port *port,
10381044
}
10391045

10401046
/* send it down the pipe */
1047+
usb_anchor_urb(urb, &garmin_data_p->write_urbs);
10411048
status = usb_submit_urb(urb, GFP_ATOMIC);
10421049
if (status) {
10431050
dev_err(&port->dev,
10441051
"%s - usb_submit_urb(write bulk) failed with status = %d\n",
10451052
__func__, status);
10461053
count = status;
1054+
usb_unanchor_urb(urb);
10471055
kfree(buffer);
10481056
}
10491057

@@ -1402,6 +1410,7 @@ static int garmin_port_probe(struct usb_serial_port *port)
14021410
garmin_data_p->state = 0;
14031411
garmin_data_p->flags = 0;
14041412
garmin_data_p->count = 0;
1413+
init_usb_anchor(&garmin_data_p->write_urbs);
14051414
usb_set_serial_port_data(port, garmin_data_p);
14061415

14071416
status = garmin_init_session(port);
@@ -1414,6 +1423,7 @@ static int garmin_port_remove(struct usb_serial_port *port)
14141423
{
14151424
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
14161425

1426+
usb_kill_anchored_urbs(&garmin_data_p->write_urbs);
14171427
usb_kill_urb(port->interrupt_in_urb);
14181428
del_timer_sync(&garmin_data_p->timer);
14191429
kfree(garmin_data_p);

0 commit comments

Comments
 (0)