diff options
author | Johannes Berg <johannes.berg@intel.com> | 2011-11-10 09:55:05 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-11-11 12:32:52 -0500 |
commit | aed0fd4acd9b1a4fa042ea65f5de697996f6ac7f (patch) | |
tree | 120fd648461bbfd8e771e5952d169cecd75a1f71 /drivers | |
parent | b2ccccdca46273c7b321ecf5041c362cd950da20 (diff) |
iwlagn: fix NULL ptr deref when reprogramming sta w/o LQ
Reinette reports a crash in iwl_reprogram_ap_sta(). The
debugging shows:
b1 16 mov $0x16,%cl
*f3 a5 rep movsl %ds <-- trapping instruction:(%rsi),%es:(%rdi)
which is a memcpy of 22 (0x16) words (movsl). this points
to "priv->stations[sta_id].lq" being NULL since that is
the memcpy() of that size here.
The only way I see for this to happen is if we try to
do some RXON reprogramming while connecting to an AP,
after tx_sync() but before full setup, but that seems
like something that might very well happen.
Fix this by checking if the LQ is present and only then
reprogramming it.
Reported-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 93067686218..1b112dfbce7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c | |||
@@ -647,7 +647,7 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
647 | int ret; | 647 | int ret; |
648 | struct iwl_addsta_cmd sta_cmd; | 648 | struct iwl_addsta_cmd sta_cmd; |
649 | struct iwl_link_quality_cmd lq; | 649 | struct iwl_link_quality_cmd lq; |
650 | bool active; | 650 | bool active, have_lq = false; |
651 | 651 | ||
652 | spin_lock_irqsave(&priv->shrd->sta_lock, flags); | 652 | spin_lock_irqsave(&priv->shrd->sta_lock, flags); |
653 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { | 653 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { |
@@ -657,7 +657,10 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
657 | 657 | ||
658 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); | 658 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); |
659 | sta_cmd.mode = 0; | 659 | sta_cmd.mode = 0; |
660 | memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq)); | 660 | if (priv->stations[sta_id].lq) { |
661 | memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq)); | ||
662 | have_lq = true; | ||
663 | } | ||
661 | 664 | ||
662 | active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE; | 665 | active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE; |
663 | priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; | 666 | priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; |
@@ -679,7 +682,8 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
679 | if (ret) | 682 | if (ret) |
680 | IWL_ERR(priv, "failed to re-add STA %pM (%d)\n", | 683 | IWL_ERR(priv, "failed to re-add STA %pM (%d)\n", |
681 | priv->stations[sta_id].sta.sta.addr, ret); | 684 | priv->stations[sta_id].sta.sta.addr, ret); |
682 | iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); | 685 | if (have_lq) |
686 | iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); | ||
683 | } | 687 | } |
684 | 688 | ||
685 | int iwl_get_free_ucode_key_offset(struct iwl_priv *priv) | 689 | int iwl_get_free_ucode_key_offset(struct iwl_priv *priv) |