Patch "r8152: Hold the rtnl_lock for all of reset" has been added to the 6.6-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    r8152: Hold the rtnl_lock for all of reset

to the 6.6-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     r8152-hold-the-rtnl_lock-for-all-of-reset.patch
and it can be found in the queue-6.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 518d5772caf005bdb58681a7cacc0020cc65c648
Author: Douglas Anderson <dianders@xxxxxxxxxxxx>
Date:   Wed Nov 29 13:25:20 2023 -0800

    r8152: Hold the rtnl_lock for all of reset
    
    [ Upstream commit e62adaeecdc6a1e8ae86e7f3f9f8223a3ede94f5 ]
    
    As of commit d9962b0d4202 ("r8152: Block future register access if
    register access fails") there is a race condition that can happen
    between the USB device reset thread and napi_enable() (not) getting
    called during rtl8152_open(). Specifically:
    * While rtl8152_open() is running we get a register access error
      that's _not_ -ENODEV and queue up a USB reset.
    * rtl8152_open() exits before calling napi_enable() due to any reason
      (including usb_submit_urb() returning an error).
    
    In that case:
    * Since the USB reset is perform in a separate thread asynchronously,
      it can run at anytime USB device lock is not held - even before
      rtl8152_open() has exited with an error and caused __dev_open() to
      clear the __LINK_STATE_START bit.
    * The rtl8152_pre_reset() will notice that the netif_running() returns
      true (since __LINK_STATE_START wasn't cleared) so it won't exit
      early.
    * rtl8152_pre_reset() will then hang in napi_disable() because
      napi_enable() was never called.
    
    We can fix the race by making sure that the r8152 reset routines don't
    run at the same time as we're opening the device. Specifically we need
    the reset routines in their entirety rely on the return value of
    netif_running(). The only way to reliably depend on that is for them
    to hold the rntl_lock() mutex for the duration of reset.
    
    Grabbing the rntl_lock() mutex for the duration of reset seems like a
    long time, but reset is not expected to be common and the rtnl_lock()
    mutex is already held for long durations since the core grabs it
    around the open/close calls.
    
    Fixes: d9962b0d4202 ("r8152: Block future register access if register access fails")
    Reviewed-by: Grant Grundler <grundler@xxxxxxxxxxxx>
    Signed-off-by: Douglas Anderson <dianders@xxxxxxxxxxxx>
    Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index be18d72cefcce..77408265e612a 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -8364,6 +8364,8 @@ static int rtl8152_pre_reset(struct usb_interface *intf)
 	struct r8152 *tp = usb_get_intfdata(intf);
 	struct net_device *netdev;
 
+	rtnl_lock();
+
 	if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags))
 		return 0;
 
@@ -8395,20 +8397,17 @@ static int rtl8152_post_reset(struct usb_interface *intf)
 	struct sockaddr sa;
 
 	if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags))
-		return 0;
+		goto exit;
 
 	rtl_set_accessible(tp);
 
 	/* reset the MAC address in case of policy change */
-	if (determine_ethernet_addr(tp, &sa) >= 0) {
-		rtnl_lock();
+	if (determine_ethernet_addr(tp, &sa) >= 0)
 		dev_set_mac_address (tp->netdev, &sa, NULL);
-		rtnl_unlock();
-	}
 
 	netdev = tp->netdev;
 	if (!netif_running(netdev))
-		return 0;
+		goto exit;
 
 	set_bit(WORK_ENABLE, &tp->flags);
 	if (netif_carrier_ok(netdev)) {
@@ -8427,6 +8426,8 @@ static int rtl8152_post_reset(struct usb_interface *intf)
 	if (!list_empty(&tp->rx_done))
 		napi_schedule(&tp->napi);
 
+exit:
+	rtnl_unlock();
 	return 0;
 }
 




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux