diff options
author | Zhu Yi <yi.zhu@intel.com> | 2009-10-23 13:42:25 -0700 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-10-27 16:50:01 -0400 |
commit | 29b1b2688fd71346f78f175d9669c006686b6dc3 (patch) | |
tree | 8d7a337761cc88dae60f4d5e44eb5fd9fbe53858 /drivers/net/wireless/iwlwifi/iwl-3945.c | |
parent | 52aa081c40324ecb04a47864e4e56dafc5a72a34 (diff) | |
download | blackbird-op-linux-29b1b2688fd71346f78f175d9669c006686b6dc3.tar.gz blackbird-op-linux-29b1b2688fd71346f78f175d9669c006686b6dc3.zip |
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.c | 15 |
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 269b9889e39e..f5d75288bd27 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; |