[PATCH wireless-next 4/7] wifi: mac80211: unshare the skb before building the header
Johannes Berg <[email protected]> Mon, 3 Aug 2026 16:08:40 +0200
| Newsgroups | org.kernel.vger.linux-wireless |
|---|---|
| Message-ID | <[email protected]> |
From: Johannes Berg <[email protected]> ieee80211_build_hdr() unshares the skb halfway through, after it has already looked at it but before it writes anything. That's not a problem, but complicates the callers and requires passing the flags to the function, etc. Move the unsharing to the only caller that matters, the new one from the previous patch has a fresh SKB and doesn't need it and the TDLS callers via ieee80211_tdls_build_mgmt_packet_data() are also fresh SKBs. Signed-off-by: Johannes Berg <[email protected]> --- net/mac80211/tx.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 28c60ae442c0..1d139c2506bb 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2637,9 +2637,8 @@ static void ieee80211_remove_ack_skb(struct ieee80211_local *local, u16 info_id) * the appropriate IEEE 802.11 header based on which interface the packet is * being transmitted on. * - * Note that this function also takes care of the TX status request and - * potential unsharing of the SKB - this needs to be interleaved with the - * header building. + * Note that this function also takes care of the TX status request. The skb + * must not be shared. * * The function requires the read-side RCU lock held * @@ -2949,15 +2948,6 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, info_id = ieee80211_store_ack_skb(local, skb, &info_flags, cookie); - /* - * If the skb is shared we need to obtain our own copy. - */ - skb = skb_share_check(skb, GFP_ATOMIC); - if (unlikely(!skb)) { - ret = -ENOMEM; - goto free; - } - hdr.frame_control = fc; hdr.duration_id = 0; hdr.seq_ctrl = 0; @@ -4424,6 +4414,12 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, if (skb->protocol == sdata->control_port_protocol) ctrl_flags |= IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP; + skb = skb_share_check(skb, GFP_ATOMIC); + if (unlikely(!skb)) { + kfree_skb_list(next); + goto out; + } + skb = ieee80211_build_hdr(sdata, skb, info_flags, sta, ctrl_flags, 0); if (IS_ERR(skb)) { -- 2.55.0