aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl3945-base.c
diff options
context:
space:
mode:
authorZhu Yi <yi.zhu@intel.com>2009-10-23 16:42:25 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-27 16:50:01 -0400
commit29b1b2688fd71346f78f175d9669c006686b6dc3 (patch)
tree8d7a337761cc88dae60f4d5e44eb5fd9fbe53858 /drivers/net/wireless/iwlwifi/iwl3945-base.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/iwl3945-base.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 5977a57a234c..8b08bdc10bc9 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1124,6 +1124,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
1124 struct iwl_rx_mem_buffer *rxb; 1124 struct iwl_rx_mem_buffer *rxb;
1125 struct page *page; 1125 struct page *page;
1126 unsigned long flags; 1126 unsigned long flags;
1127 gfp_t gfp_mask = priority;
1127 1128
1128 while (1) { 1129 while (1) {
1129 spin_lock_irqsave(&rxq->lock, flags); 1130 spin_lock_irqsave(&rxq->lock, flags);
@@ -1135,13 +1136,13 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
1135 spin_unlock_irqrestore(&rxq->lock, flags); 1136 spin_unlock_irqrestore(&rxq->lock, flags);
1136 1137
1137 if (rxq->free_count > RX_LOW_WATERMARK) 1138 if (rxq->free_count > RX_LOW_WATERMARK)
1138 priority |= __GFP_NOWARN; 1139 gfp_mask |= __GFP_NOWARN;
1139 1140
1140 if (priv->hw_params.rx_page_order > 0) 1141 if (priv->hw_params.rx_page_order > 0)
1141 priority |= __GFP_COMP; 1142 gfp_mask |= __GFP_COMP;
1142 1143
1143 /* Alloc a new receive buffer */ 1144 /* Alloc a new receive buffer */
1144 page = alloc_pages(priority, priv->hw_params.rx_page_order); 1145 page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
1145 if (!page) { 1146 if (!page) {
1146 if (net_ratelimit()) 1147 if (net_ratelimit())
1147 IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); 1148 IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
@@ -1410,8 +1411,8 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
1410 if (priv->rx_handlers[pkt->hdr.cmd]) { 1411 if (priv->rx_handlers[pkt->hdr.cmd]) {
1411 IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i, 1412 IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i,
1412 get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); 1413 get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
1413 priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
1414 priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; 1414 priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
1415 priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
1415 } else { 1416 } else {
1416 /* No handling needed */ 1417 /* No handling needed */
1417 IWL_DEBUG_RX(priv, 1418 IWL_DEBUG_RX(priv,
@@ -1420,11 +1421,18 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
1420 pkt->hdr.cmd); 1421 pkt->hdr.cmd);
1421 } 1422 }
1422 1423
1424 /*
1425 * XXX: After here, we should always check rxb->page
1426 * against NULL before touching it or its virtual
1427 * memory (pkt). Because some rx_handler might have
1428 * already taken or freed the pages.
1429 */
1430
1423 if (reclaim) { 1431 if (reclaim) {
1424 /* Invoke any callbacks, transfer the buffer to caller, 1432 /* Invoke any callbacks, transfer the buffer to caller,
1425 * and fire off the (possibly) blocking iwl_send_cmd() 1433 * and fire off the (possibly) blocking iwl_send_cmd()
1426 * as we reclaim the driver command queue */ 1434 * as we reclaim the driver command queue */
1427 if (rxb && rxb->page) 1435 if (rxb->page)
1428 iwl_tx_cmd_complete(priv, rxb); 1436 iwl_tx_cmd_complete(priv, rxb);
1429 else 1437 else
1430 IWL_WARN(priv, "Claim null rxb?\n"); 1438 IWL_WARN(priv, "Claim null rxb?\n");