lkml.org 
[lkml]   [2016]   [Jan]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.19.y-ckt 041/160] usb: core : hub: Fix BOS 'NULL pointer' kernel panic
    Date
    3.19.8-ckt13 -stable review patch.  If anyone has any objections, please let me know.

    ---8<------------------------------------------------------------

    From: Hans Yang <hansy@nvidia.com>

    commit 464ad8c43a9ead98c2b0eaed86bea727f2ad106e upstream.

    When a USB 3.0 mass storage device is disconnected in transporting
    state, storage device driver may handle it as a transport error and
    reset the device by invoking usb_reset_and_verify_device()
    and following could happen:

    in usb_reset_and_verify_device():
    udev->bos = NULL;

    For U1/U2 enabled devices, driver will disable LPM, and in some
    conditions:
    from usb_unlocked_disable_lpm()
    --> usb_disable_lpm()
    --> usb_enable_lpm()
    udev->bos->ss_cap->bU1devExitLat;

    And it causes 'NULL pointer' and 'kernel panic':

    [ 157.976257] Unable to handle kernel NULL pointer dereference
    at virtual address 00000010
    ...
    [ 158.026400] PC is at usb_enable_link_state+0x34/0x2e0
    [ 158.031442] LR is at usb_enable_lpm+0x98/0xac
    ...
    [ 158.137368] [<ffffffc0006a1cac>] usb_enable_link_state+0x34/0x2e0
    [ 158.143451] [<ffffffc0006a1fec>] usb_enable_lpm+0x94/0xac
    [ 158.148840] [<ffffffc0006a20e8>] usb_disable_lpm+0xa8/0xb4
    ...
    [ 158.214954] Kernel panic - not syncing: Fatal exception

    This commit moves 'udev->bos = NULL' behind usb_unlocked_disable_lpm()
    to prevent from NULL pointer access.

    Issue can be reproduced by following setup:
    1) A SS pen drive behind a SS hub connected to the host.
    2) Transporting data between the pen drive and the host.
    3) Abruptly disconnect hub and pen drive from host.
    4) With a chance it crashes.

    Signed-off-by: Hans Yang <hansy@nvidia.com>
    Acked-by: Alan Stern <stern@rowland.harvard.edu>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Kamal Mostafa <kamal@canonical.com>
    ---
    drivers/usb/core/hub.c | 15 ++++++++-------
    1 file changed, 8 insertions(+), 7 deletions(-)

    diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
    index 3445773..501edda 100644
    --- a/drivers/usb/core/hub.c
    +++ b/drivers/usb/core/hub.c
    @@ -5322,9 +5322,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
    if (udev->usb2_hw_lpm_enabled == 1)
    usb_set_usb2_hardware_lpm(udev, 0);

    - bos = udev->bos;
    - udev->bos = NULL;
    -
    /* Disable LPM and LTM while we reset the device and reinstall the alt
    * settings. Device-initiated LPM settings, and system exit latency
    * settings are cleared when the device is reset, so we have to set
    @@ -5333,15 +5330,18 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
    ret = usb_unlocked_disable_lpm(udev);
    if (ret) {
    dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__);
    - goto re_enumerate;
    + goto re_enumerate_no_bos;
    }
    ret = usb_disable_ltm(udev);
    if (ret) {
    dev_err(&udev->dev, "%s Failed to disable LTM\n.",
    __func__);
    - goto re_enumerate;
    + goto re_enumerate_no_bos;
    }

    + bos = udev->bos;
    + udev->bos = NULL;
    +
    for (i = 0; i < SET_CONFIG_TRIES; ++i) {

    /* ep0 maxpacket size may change; let the HCD know about it.
    @@ -5438,10 +5438,11 @@ done:
    return 0;

    re_enumerate:
    - /* LPM state doesn't matter when we're about to destroy the device. */
    - hub_port_logical_disconnect(parent_hub, port1);
    usb_release_bos_descriptor(udev);
    udev->bos = bos;
    +re_enumerate_no_bos:
    + /* LPM state doesn't matter when we're about to destroy the device. */
    + hub_port_logical_disconnect(parent_hub, port1);
    return -ENODEV;
    }

    --
    1.9.1

    \
     
     \ /
      Last update: 2016-01-20 03:01    [W:4.026 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site