Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 579cf722 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman
Browse files

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: 1da177e4 ("Linux-2.6.12-rc2")
Reviewed-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarJohan Hovold <johan@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1f9688d5
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -138,6 +138,7 @@ struct garmin_data {
	__u8   privpkt[4*6];
	spinlock_t lock;
	struct list_head pktlist;
	struct usb_anchor write_urbs;
};


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

			if (status < 0)
				break;
				goto err_kill_urbs;
		}

		if (status > 0)
			status = 0;
	}

	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 *tty, struct usb_serial_port *port)
	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_serial_port *port)

	/* 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_serial_port *port,
	}

	/* 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_serial_port *port)
	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_serial_port *port)
{
	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);