Patch "wifi: mac80211: use two-phase skb reclamation in ieee80211_do_stop()" has been added to the 4.19-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

    wifi: mac80211: use two-phase skb reclamation in ieee80211_do_stop()

to the 4.19-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:
     wifi-mac80211-use-two-phase-skb-reclamation-in-ieee8.patch
and it can be found in the queue-4.19 subdirectory.

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



commit 8fcde46e3027cebc731d8ab070ab6a6de4dc2cb3
Author: Dmitry Antipov <dmantipov@xxxxxxxxx>
Date:   Fri Sep 6 15:31:51 2024 +0300

    wifi: mac80211: use two-phase skb reclamation in ieee80211_do_stop()
    
    [ Upstream commit 9d301de12da6e1bb069a9835c38359b8e8135121 ]
    
    Since '__dev_queue_xmit()' should be called with interrupts enabled,
    the following backtrace:
    
    ieee80211_do_stop()
     ...
     spin_lock_irqsave(&local->queue_stop_reason_lock, flags)
     ...
     ieee80211_free_txskb()
      ieee80211_report_used_skb()
       ieee80211_report_ack_skb()
        cfg80211_mgmt_tx_status_ext()
         nl80211_frame_tx_status()
          genlmsg_multicast_netns()
           genlmsg_multicast_netns_filtered()
            nlmsg_multicast_filtered()
             netlink_broadcast_filtered()
              do_one_broadcast()
               netlink_broadcast_deliver()
                __netlink_sendskb()
                 netlink_deliver_tap()
                  __netlink_deliver_tap_skb()
                   dev_queue_xmit()
                    __dev_queue_xmit() ; with IRQS disabled
     ...
     spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags)
    
    issues the warning (as reported by syzbot reproducer):
    
    WARNING: CPU: 2 PID: 5128 at kernel/softirq.c:362 __local_bh_enable_ip+0xc3/0x120
    
    Fix this by implementing a two-phase skb reclamation in
    'ieee80211_do_stop()', where actual work is performed
    outside of a section with interrupts disabled.
    
    Fixes: 5061b0c2b906 ("mac80211: cooperate more with network namespaces")
    Reported-by: syzbot+1a3986bbd3169c307819@xxxxxxxxxxxxxxxxxxxxxxxxx
    Closes: https://syzkaller.appspot.com/bug?extid=1a3986bbd3169c307819
    Signed-off-by: Dmitry Antipov <dmantipov@xxxxxxxxx>
    Link: https://patch.msgid.link/20240906123151.351647-1-dmantipov@xxxxxxxxx
    Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 358028a09ce4d..433083cc15331 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -798,6 +798,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 {
 	struct ieee80211_local *local = sdata->local;
 	unsigned long flags;
+	struct sk_buff_head freeq;
 	struct sk_buff *skb, *tmp;
 	u32 hw_reconf_flags = 0;
 	int i, flushed;
@@ -996,18 +997,32 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 		skb_queue_purge(&sdata->skb_queue);
 	}
 
+	/*
+	 * Since ieee80211_free_txskb() may issue __dev_queue_xmit()
+	 * which should be called with interrupts enabled, reclamation
+	 * is done in two phases:
+	 */
+	__skb_queue_head_init(&freeq);
+
+	/* unlink from local queues... */
 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
 	for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
 		skb_queue_walk_safe(&local->pending[i], skb, tmp) {
 			struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 			if (info->control.vif == &sdata->vif) {
 				__skb_unlink(skb, &local->pending[i]);
-				ieee80211_free_txskb(&local->hw, skb);
+				__skb_queue_tail(&freeq, skb);
 			}
 		}
 	}
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 
+	/* ... and perform actual reclamation with interrupts enabled. */
+	skb_queue_walk_safe(&freeq, skb, tmp) {
+		__skb_unlink(skb, &freeq);
+		ieee80211_free_txskb(&local->hw, skb);
+	}
+
 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 		ieee80211_txq_remove_vlan(local, sdata);
 




[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