• Alan Stern's avatar
    USB: fix deadlock in bConfigurationValue attribute method · 8963c487
    Alan Stern authored
    This patch (as154) fixes a self-deadlock that occurs when userspace
    writes to the bConfigurationValue sysfs attribute for a hub with
    children.  The task tries to lock the bandwidth_mutex at a time when
    it already owns the lock:
    
    	The attribute's method calls usb_set_configuration(),
    	which calls usb_disable_device() with the bandwidth_mutex
    	held.
    
    	usb_disable_device() unregisters the existing interfaces,
    	which causes the hub driver to be unbound.
    
    	The hub_disconnect() routine calls hub_quiesce(), which
    	calls usb_disconnect() for each of the hub's children.
    
    	usb_disconnect() attempts to acquire the bandwidth_mutex
    	around a call to usb_disable_device().
    
    The solution is to make usb_disable_device() acquire the mutex for
    itself instead of requiring the caller to hold it.  Then the mutex can
    cover only the bandwidth deallocation operation and not the region
    where the interfaces are unregistered.
    
    This has the potential to change system behavior slightly when a
    config change races with another config or altsetting change.  Some of
    the bandwidth released from the old config might get claimed by the
    other config or altsetting, make it impossible to restore the old
    config in case of a failure.  But since we don't try to recover from
    config-change failures anyway, this doesn't matter.
    
    [This should be marked for stable kernels that contain the commit
    fccf4e86 "USB: Free bandwidth when
    usb_disable_device is called."
    That commit was marked for stable kernels as old as 2.6.32.]
    Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
    Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
    Cc: stable <stable@vger.kernel.org>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    8963c487
hub.c 120 KB