diff mbox series

mac80211: check skb_shared in ieee80211_8023_xmit()

Message ID 1ef9b892cc93a36b1e62a6dda0e2e0a019f4e5f7.1653555361.git.ryder.lee@mediatek.com (mailing list archive)
State New, archived
Headers show
Series mac80211: check skb_shared in ieee80211_8023_xmit() | expand

Commit Message

Ryder Lee May 26, 2022, 9:08 a.m. UTC
Add missing skb_shared check into 802.3 path as 802.11 path does
to prevent potential use-after-free from happening.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 net/mac80211/tx.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

Comments

Lorenzo Bianconi May 26, 2022, 9:35 a.m. UTC | #1
> Add missing skb_shared check into 802.3 path as 802.11 path does
> to prevent potential use-after-free from happening.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  net/mac80211/tx.c | 13 ++++++++++++-
>  1 file changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
> index 0e4efc08c762..b026e746ac5b 100644
> --- a/net/mac80211/tx.c
> +++ b/net/mac80211/tx.c
> @@ -4437,7 +4437,7 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
>  				struct net_device *dev, struct sta_info *sta,
>  				struct ieee80211_key *key, struct sk_buff *skb)
>  {
> -	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> +	struct ieee80211_tx_info *info;
>  	struct ieee80211_local *local = sdata->local;
>  	struct tid_ampdu_tx *tid_tx;
>  	u8 tid;
> @@ -4452,6 +4452,17 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
>  	    test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
>  		goto out_free;
>  
> +	if (skb_shared(skb)) {
> +		struct sk_buff *tmp_skb = skb;
> +
> +		skb = skb_clone(skb, GFP_ATOMIC);
> +		kfree_skb(tmp_skb);
> +
> +		if (!skb)
> +			return;
> +	}

I guess you can use skb_share_check() here instead.

Regards,
Lorenzo

> +
> +	info = IEEE80211_SKB_CB(skb);
>  	memset(info, 0, sizeof(*info));
>  
>  	ieee80211_aggr_check(sdata, sta, skb);
> -- 
> 2.29.2
>
diff mbox series

Patch

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 0e4efc08c762..b026e746ac5b 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4437,7 +4437,7 @@  static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
 				struct net_device *dev, struct sta_info *sta,
 				struct ieee80211_key *key, struct sk_buff *skb)
 {
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_tx_info *info;
 	struct ieee80211_local *local = sdata->local;
 	struct tid_ampdu_tx *tid_tx;
 	u8 tid;
@@ -4452,6 +4452,17 @@  static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
 	    test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
 		goto out_free;
 
+	if (skb_shared(skb)) {
+		struct sk_buff *tmp_skb = skb;
+
+		skb = skb_clone(skb, GFP_ATOMIC);
+		kfree_skb(tmp_skb);
+
+		if (!skb)
+			return;
+	}
+
+	info = IEEE80211_SKB_CB(skb);
 	memset(info, 0, sizeof(*info));
 
 	ieee80211_aggr_check(sdata, sta, skb);