lkml.org 
[lkml]   [2017]   [Nov]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 16/31] USB: serial: garmin_gps: fix I/O after failed probe and remove
    Date
    4.14-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    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);

    \
     
     \ /
      Last update: 2017-11-19 16:06    [W:3.992 / U:0.092 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site