lkml.org 
[lkml]   [2020]   [Dec]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 148/175] USB: serial: keyspan_pda: fix write-wakeup use-after-free
    Date
    From: Johan Hovold <johan@kernel.org>

    commit 37faf50615412947868c49aee62f68233307f4e4 upstream.

    The driver's deferred write wakeup was never flushed on disconnect,
    something which could lead to the driver port data being freed while the
    wakeup work is still scheduled.

    Fix this by using the usb-serial write wakeup which gets cancelled
    properly on disconnect.

    Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
    Cc: stable@vger.kernel.org
    Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
    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/keyspan_pda.c | 17 +++--------------
    1 file changed, 3 insertions(+), 14 deletions(-)

    --- a/drivers/usb/serial/keyspan_pda.c
    +++ b/drivers/usb/serial/keyspan_pda.c
    @@ -47,8 +47,7 @@
    struct keyspan_pda_private {
    int tx_room;
    int tx_throttled;
    - struct work_struct wakeup_work;
    - struct work_struct unthrottle_work;
    + struct work_struct unthrottle_work;
    struct usb_serial *serial;
    struct usb_serial_port *port;
    };
    @@ -101,15 +100,6 @@ static const struct usb_device_id id_tab
    };
    #endif

    -static void keyspan_pda_wakeup_write(struct work_struct *work)
    -{
    - struct keyspan_pda_private *priv =
    - container_of(work, struct keyspan_pda_private, wakeup_work);
    - struct usb_serial_port *port = priv->port;
    -
    - tty_port_tty_wakeup(&port->port);
    -}
    -
    static void keyspan_pda_request_unthrottle(struct work_struct *work)
    {
    struct keyspan_pda_private *priv =
    @@ -187,7 +177,7 @@ static void keyspan_pda_rx_interrupt(str
    case 2: /* tx unthrottle interrupt */
    priv->tx_throttled = 0;
    /* queue up a wakeup at scheduler time */
    - schedule_work(&priv->wakeup_work);
    + usb_serial_port_softint(port);
    break;
    default:
    break;
    @@ -567,7 +557,7 @@ static void keyspan_pda_write_bulk_callb
    priv = usb_get_serial_port_data(port);

    /* queue up a wakeup at scheduler time */
    - schedule_work(&priv->wakeup_work);
    + usb_serial_port_softint(port);
    }


    @@ -733,7 +723,6 @@ static int keyspan_pda_port_probe(struct
    if (!priv)
    return -ENOMEM;

    - INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write);
    INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle);
    priv->serial = port->serial;
    priv->port = port;

    \
     
     \ /
      Last update: 2020-12-28 14:08    [W:4.775 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site