aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/iwlwifi/iwl-3945.c
diff options
context:
space:
mode:
authorZhu Yi <yi.zhu@intel.com>2009-10-23 13:42:25 -0700
committerJohn W. Linville <linville@tuxdriver.com>2009-10-27 16:50:01 -0400
commit29b1b2688fd71346f78f175d9669c006686b6dc3 (patch)
tree8d7a337761cc88dae60f4d5e44eb5fd9fbe53858 /drivers/net/wireless/iwlwifi/iwl-3945.c
parent52aa081c40324ecb04a47864e4e56dafc5a72a34 (diff)
iwlwifi: fix use after free bug for paged rx
In the paged rx patch (4854fde2), I introduced a bug that could possibly touch an already freed page. It is fixed by avoiding the access in this patch. I've also added some comments so that other people touching the code won't make the same mistake. In the future, if we cannot avoid access the page after being handled to the upper layer, we can use get_page/put_page to handle it. For now, it's just not necessary. It also fixed a debug message print bug reported by Stanislaw Gruszka <sgruszka@redhat.com>. Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-3945.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 269b9889e39..f5d75288bd2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -548,6 +548,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
u16 len = le16_to_cpu(rx_hdr->len);
struct sk_buff *skb;
int ret;
+ __le16 fc = hdr->frame_control;
/* We received data from the HW, so stop the watchdog */
if (unlikely(len + IWL39_RX_FRAME_SIZE >
@@ -580,9 +581,9 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
/* mac80211 currently doesn't support paged SKB. Convert it to
* linear SKB for management frame and data frame requires
* software decryption or software defragementation. */
- if (ieee80211_is_mgmt(hdr->frame_control) ||
- ieee80211_has_protected(hdr->frame_control) ||
- ieee80211_has_morefrags(hdr->frame_control) ||
+ if (ieee80211_is_mgmt(fc) ||
+ ieee80211_has_protected(fc) ||
+ ieee80211_has_morefrags(fc) ||
le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)
ret = skb_linearize(skb);
else
@@ -594,11 +595,15 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
goto out;
}
- iwl_update_stats(priv, false, hdr->frame_control, len);
+ /*
+ * XXX: We cannot touch the page and its virtual memory (pkt) after
+ * here. It might have already been freed by the above skb change.
+ */
+ iwl_update_stats(priv, false, fc, len);
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
- ieee80211_rx(priv->hw, skb);
+ ieee80211_rx(priv->hw, skb);
out:
priv->alloc_rxb_page--;
rxb->page = NULL;