2022-05-26 15:06:27

by Ryder Lee

[permalink] [raw]
Subject: [PATCH] mac80211: check skb_shared in ieee80211_8023_xmit()

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 <[email protected]>
---
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;
+ }
+
+ info = IEEE80211_SKB_CB(skb);
memset(info, 0, sizeof(*info));

ieee80211_aggr_check(sdata, sta, skb);
--
2.29.2



2022-05-28 19:51:04

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH] mac80211: check skb_shared in ieee80211_8023_xmit()

> 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 <[email protected]>
> ---
> 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
>


Attachments:
(No filename) (1.39 kB)
signature.asc (235.00 B)
Download all attachments