Re: [PATCH v1] wifi: mac80211_hwsim: fix race condition in pending packet

From: Jeongik Cha
Date: Thu Jul 14 2022 - 04:38:56 EST


On Mon, Jul 4, 2022 at 5:44 PM Jeongik Cha <jeongik@xxxxxxxxxx> wrote:
>
> A pending packet uses a cookie as an unique key, but it can be duplicated
> because it didn't use atomic operators.
>
> And also, a pending packet can be null in hwsim_tx_info_frame_received_nl
> due to race condition with mac80211_hwsim_stop.
>
> For this,
> * Use an atomic type and operator for a cookie
> * Add a lock around the loop for pending packets
>
> Signed-off-by: Jeongik Cha <jeongik@xxxxxxxxxx>
> ---
> drivers/net/wireless/mac80211_hwsim.c | 14 ++++++++------
> 1 file changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
> index c5bb97b381cf..ea006248ffcd 100644
> --- a/drivers/net/wireless/mac80211_hwsim.c
> +++ b/drivers/net/wireless/mac80211_hwsim.c
> @@ -687,7 +687,7 @@ struct mac80211_hwsim_data {
> bool ps_poll_pending;
> struct dentry *debugfs;
>
> - uintptr_t pending_cookie;
> + atomic64_t pending_cookie;
> struct sk_buff_head pending; /* packets pending */
> /*
> * Only radios in the same group can communicate together (the
> @@ -1358,7 +1358,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
> int i;
> struct hwsim_tx_rate tx_attempts[IEEE80211_TX_MAX_RATES];
> struct hwsim_tx_rate_flag tx_attempts_flags[IEEE80211_TX_MAX_RATES];
> - uintptr_t cookie;
> + u64 cookie;
>
> if (data->ps != PS_DISABLED)
> hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
> @@ -1427,8 +1427,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
> goto nla_put_failure;
>
> /* We create a cookie to identify this skb */
> - data->pending_cookie++;
> - cookie = data->pending_cookie;
> + cookie = (u64)atomic64_inc_return(&data->pending_cookie);
> info->rate_driver_data[0] = (void *)cookie;
> if (nla_put_u64_64bit(skb, HWSIM_ATTR_COOKIE, cookie, HWSIM_ATTR_PAD))
> goto nla_put_failure;
> @@ -4178,6 +4177,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
> const u8 *src;
> unsigned int hwsim_flags;
> int i;
> + unsigned long flags;
> bool found = false;
>
> if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
> @@ -4205,18 +4205,20 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
> }
>
> /* look for the skb matching the cookie passed back from user */
> + spin_lock_irqsave(&data2->pending.lock, flags);
> skb_queue_walk_safe(&data2->pending, skb, tmp) {
> u64 skb_cookie;
>
> txi = IEEE80211_SKB_CB(skb);
> - skb_cookie = (u64)(uintptr_t)txi->rate_driver_data[0];
> + skb_cookie = (u64)txi->rate_driver_data[0];
>
> if (skb_cookie == ret_skb_cookie) {
> - skb_unlink(skb, &data2->pending);
> + __skb_unlink(skb, &data2->pending);
> found = true;
> break;
> }
> }
> + spin_unlock_irqrestore(&data2->pending.lock, flags);
>
> /* not found */
> if (!found)
> --
> 2.37.0.rc0.161.g10f37bed90-goog
>

Hello Johannes!

It fixes kernel panics during a long test which uses mac80211_hwsim
driver. So I think it would be beneficial if we could merge this into
LTS branches. Could you share your opinion?

Thanks
Jeongik