diff mbox series

iwlwifi: mvm: Fix potential NULL dereference for sta

Message ID 20220121111418.9144-1-tiwai@suse.de (mailing list archive)
State Superseded
Delegated to: Luca Coelho
Headers show
Series iwlwifi: mvm: Fix potential NULL dereference for sta | expand

Commit Message

Takashi Iwai Jan. 21, 2022, 11:14 a.m. UTC
The recent fix for NULL sta in iwl_mvm_get_tx_rate() may still hit a
potential NULL dereference, as iwl_mvm_sta_from_mac80211() is called
unconditionally (although this doesn't seem happening, practically
seen, thanks to the compiler optimization).

This patch addresses it by dropping the temporary variable.

Fixes: d599f714b73e ("iwlwifi: mvm: don't crash on invalid rate w/o STA")
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

Comments

Johannes Berg Jan. 21, 2022, 11:22 a.m. UTC | #1
On Fri, 2022-01-21 at 12:14 +0100, Takashi Iwai wrote:
> The recent fix for NULL sta in iwl_mvm_get_tx_rate() may still hit a
> potential NULL dereference, as iwl_mvm_sta_from_mac80211() is called
> unconditionally (although this doesn't seem happening, practically
> seen, thanks to the compiler optimization).
> 

No objection to the patch, but I think the description isn't quite
right?

static inline struct iwl_mvm_sta *
iwl_mvm_sta_from_mac80211(struct ieee80211_sta *sta)
{
        return (void *)sta->drv_priv;
}

looks like a dereference, but I _think_

struct ieee80211_sta {
	[...]

        /* must be last */
        u8 drv_priv[] __aligned(sizeof(void *));
};


means it's just an address calculation, i.e. the same as if we had

	return (void *)((u8 *)sta + offsetof(typeof(*sta), drv_priv));

no?

I guess technically it's still UB doing calculations on a NULL pointer,
but practically that's going to work.

Anyway, no objections :)

johannes
Takashi Iwai Jan. 21, 2022, 11:30 a.m. UTC | #2
On Fri, 21 Jan 2022 12:22:05 +0100,
Johannes Berg wrote:
> 
> On Fri, 2022-01-21 at 12:14 +0100, Takashi Iwai wrote:
> > The recent fix for NULL sta in iwl_mvm_get_tx_rate() may still hit a
> > potential NULL dereference, as iwl_mvm_sta_from_mac80211() is called
> > unconditionally (although this doesn't seem happening, practically
> > seen, thanks to the compiler optimization).
> > 
> 
> No objection to the patch, but I think the description isn't quite
> right?
> 
> static inline struct iwl_mvm_sta *
> iwl_mvm_sta_from_mac80211(struct ieee80211_sta *sta)
> {
>         return (void *)sta->drv_priv;
> }
> 
> looks like a dereference, but I _think_
> 
> struct ieee80211_sta {
> 	[...]
> 
>         /* must be last */
>         u8 drv_priv[] __aligned(sizeof(void *));
> };
> 
> 
> means it's just an address calculation, i.e. the same as if we had
> 
> 	return (void *)((u8 *)sta + offsetof(typeof(*sta), drv_priv));
> 
> no?

Yeah, indeed, that won't access the member.

> I guess technically it's still UB doing calculations on a NULL pointer,
> but practically that's going to work.
> 
> Anyway, no objections :)

OK, I'll submit v2 with rephrasing for avoid confusion.


Takashi
diff mbox series

Patch

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 6fa2c12f7955..4d1ddca73fb0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -318,15 +318,14 @@  static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
 
 	/* info->control is only relevant for non HW rate control */
 	if (!ieee80211_hw_check(mvm->hw, HAS_RATE_CONTROL)) {
-		struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-
 		/* HT rate doesn't make sense for a non data frame */
 		WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS &&
 			  !ieee80211_is_data(fc),
 			  "Got a HT rate (flags:0x%x/mcs:%d/fc:0x%x/state:%d) for a non data frame\n",
 			  info->control.rates[0].flags,
 			  info->control.rates[0].idx,
-			  le16_to_cpu(fc), sta ? mvmsta->sta_state : -1);
+			  le16_to_cpu(fc),
+			  sta ? iwl_mvm_sta_from_mac80211(sta)->sta_state : -1);
 
 		rate_idx = info->control.rates[0].idx;
 	}