lkml.org 
[lkml]   [2014]   [Jul]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.11 065/198] USB: cdc-acm: fix write and suspend race
    Date
    3.11.10.13 -stable review patch.  If anyone has any objections, please let me know.

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

    From: Johan Hovold <jhovold@gmail.com>

    commit 5a345c20c17d87099224a4be12e69e5bd7023dca upstream.

    Fix race between write() and suspend() which could lead to writes being
    dropped (or I/O while suspended) if the device is runtime suspended
    while a write request is being processed.

    Specifically, suspend() releases the write_lock after determining the
    device is idle but before incrementing the susp_count, thus leaving a
    window where a concurrent write() can submit an urb.

    Fixes: 11ea859d64b6 ("USB: additional power savings for cdc-acm devices
    that support remote wakeup")

    Signed-off-by: Johan Hovold <jhovold@gmail.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
    ---
    drivers/usb/class/cdc-acm.c | 15 ++++++---------
    1 file changed, 6 insertions(+), 9 deletions(-)

    diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
    index 8b8236fd24cf..6ebcd38dfb06 100644
    --- a/drivers/usb/class/cdc-acm.c
    +++ b/drivers/usb/class/cdc-acm.c
    @@ -1420,18 +1420,15 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
    struct acm *acm = usb_get_intfdata(intf);
    int cnt;

    + spin_lock_irq(&acm->read_lock);
    + spin_lock(&acm->write_lock);
    if (PMSG_IS_AUTO(message)) {
    - int b;
    -
    - spin_lock_irq(&acm->write_lock);
    - b = acm->transmitting;
    - spin_unlock_irq(&acm->write_lock);
    - if (b)
    + if (acm->transmitting) {
    + spin_unlock(&acm->write_lock);
    + spin_unlock_irq(&acm->read_lock);
    return -EBUSY;
    + }
    }
    -
    - spin_lock_irq(&acm->read_lock);
    - spin_lock(&acm->write_lock);
    cnt = acm->susp_count++;
    spin_unlock(&acm->write_lock);
    spin_unlock_irq(&acm->read_lock);
    --
    1.9.1


    \
     
     \ /
      Last update: 2014-07-03 13:01    [W:3.619 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site