From 7dd2459d8f7a967bcd1466591aec72bb3ddc07cc Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 27 Jul 2009 10:10:20 +0800 Subject: [PATCH 1/7] ipw2x00: Write outside array bounds > channel_index loops up to IPW_SCAN_CHANNELS, but is used after being > incremented. This might be able to access 1 past the end of the array Reported-by: Roel Kluin Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 44c29b3f6728..6dcac73b4d29 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -6226,7 +6226,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv, }; u8 channel; - while (channel_index < IPW_SCAN_CHANNELS) { + while (channel_index < IPW_SCAN_CHANNELS - 1) { channel = priv->speed_scan[priv->speed_scan_pos]; if (channel == 0) { From d25f9f1357139bbdc79bc960ea84909a7c22ec2b Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 3 Aug 2009 21:58:26 +0200 Subject: [PATCH 2/7] mwl8k: fix NULL pointer dereference on receive out-of-memory When we go into out-of-memory and fail to allocate skbuffs to refill the receive ring with, rxq_process can end up running into a receive ring entry that is marked as host-owned but doesn't have an associated skbuff. If this happens, we must break out of the rx processing loop instead of trying to process the descriptor. Signed-off-by: Lennert Buytenhek Acked-by: Nicolas Pitre Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index a263d5c84c08..71f3eb67981e 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1012,6 +1012,8 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) rmb(); skb = rxq->rx_skb[rxq->rx_head]; + if (skb == NULL) + break; rxq->rx_skb[rxq->rx_head] = NULL; rxq->rx_head = (rxq->rx_head + 1) % MWL8K_RX_DESCS; From 4ff6432ea620ba467e50ec04b8271ea0eb94e62e Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 3 Aug 2009 21:58:39 +0200 Subject: [PATCH 3/7] mwl8k: add various missing GET_HW_SPEC endian conversions Signed-off-by: Lennert Buytenhek Acked-by: Nicolas Pitre Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 71f3eb67981e..9643aa4751c9 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1656,18 +1656,18 @@ static int mwl8k_cmd_get_hw_spec(struct ieee80211_hw *hw) memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr)); cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rx_desc_dma); - cmd->num_tx_queues = MWL8K_TX_QUEUES; + cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); for (i = 0; i < MWL8K_TX_QUEUES; i++) cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].tx_desc_dma); - cmd->num_tx_desc_per_queue = MWL8K_TX_DESCS; - cmd->total_rx_desc = MWL8K_RX_DESCS; + cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); + cmd->total_rx_desc = cpu_to_le32(MWL8K_RX_DESCS); rc = mwl8k_post_cmd(hw, &cmd->header); if (!rc) { SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr); priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); - priv->fw_rev = cmd->fw_rev; + priv->fw_rev = le32_to_cpu(cmd->fw_rev); priv->hw_rev = cmd->hw_rev; priv->region_code = le16_to_cpu(cmd->region_code); } From 37055bd455b31b8220c35a1ede9c6aceb791cc88 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 3 Aug 2009 21:58:47 +0200 Subject: [PATCH 4/7] mwl8k: call pci_unmap_single() before accessing command structure again Signed-off-by: Lennert Buytenhek Acked-by: Nicolas Pitre Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 9643aa4751c9..25423c05aff1 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1593,6 +1593,9 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) timeout = wait_for_completion_timeout(&cmd_wait, msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS)); + pci_unmap_single(priv->pdev, dma_addr, dma_size, + PCI_DMA_BIDIRECTIONAL); + result = &cmd->result; if (!timeout) { spin_lock_irq(&priv->fw_lock); @@ -1612,8 +1615,6 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) *result); } - pci_unmap_single(priv->pdev, dma_addr, dma_size, - PCI_DMA_BIDIRECTIONAL); return rc; } From a94cc97e14c5750ec2b50b2e4ecdfb0f369ed0f4 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 3 Aug 2009 21:58:57 +0200 Subject: [PATCH 5/7] mwl8k: prevent crash in ->configure_filter() if no interface was added Signed-off-by: Lennert Buytenhek Acked-by: Nicolas Pitre Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 25423c05aff1..6e491171f73e 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -261,7 +261,7 @@ struct mwl8k_vif { */ }; -#define MWL8K_VIF(_vif) (struct mwl8k_vif *)(&((_vif)->drv_priv)) +#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) static const struct ieee80211_channel mwl8k_channels[] = { { .center_freq = 2412, .hw_value = 1, }, @@ -3219,15 +3219,19 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt) struct dev_addr_list *mclist = worker->mclist; struct mwl8k_priv *priv = hw->priv; - struct mwl8k_vif *mv_vif; int rc = 0; if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { if (*total_flags & FIF_BCN_PRBRESP_PROMISC) rc = mwl8k_cmd_set_pre_scan(hw); else { - mv_vif = MWL8K_VIF(priv->vif); - rc = mwl8k_cmd_set_post_scan(hw, mv_vif->bssid); + u8 *bssid; + + bssid = "\x00\x00\x00\x00\x00\x00"; + if (priv->vif != NULL) + bssid = MWL8K_VIF(priv->vif)->bssid; + + rc = mwl8k_cmd_set_post_scan(hw, bssid); } } From 60aa569f9212a13382c29cc734f275dec0f55e0b Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 3 Aug 2009 21:59:09 +0200 Subject: [PATCH 6/7] mwl8k: prevent module unload hang We need to unregister our ieee80211_hw before resetting the chip, as the former causes firmware commands to be issued which will time out once the chip has been reset. Signed-off-by: Lennert Buytenhek Acked-by: Nicolas Pitre Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 6e491171f73e..83967afe0821 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3733,6 +3733,8 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) ieee80211_stop_queues(hw); + ieee80211_unregister_hw(hw); + /* Remove tx reclaim tasklet */ tasklet_kill(&priv->tx_reclaim_task); @@ -3746,8 +3748,6 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) for (i = 0; i < MWL8K_TX_QUEUES; i++) mwl8k_txq_reclaim(hw, i, 1); - ieee80211_unregister_hw(hw); - for (i = 0; i < MWL8K_TX_QUEUES; i++) mwl8k_txq_deinit(hw, i); From dd1f57ecaf9688efa69d982652ecfa3e64f1fa55 Mon Sep 17 00:00:00 2001 From: Bob Dunlop Date: Thu, 6 Aug 2009 12:01:03 -0400 Subject: [PATCH 7/7] libertas: correct packing of rxpd structure Older Gcc compilers (3.4.5 tested) need additional hints in order to get the packing of the rxpd structure (which contains a 16 bit union) correct on the ARM processor. struct txpd does not need these hints since it contains a 32 bit union that packs naturally. Signed-off-by: R.J.Dunlop Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/hostcmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index 0a2e29140add..c8a1998d4744 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -56,8 +56,8 @@ struct rxpd { u8 bss_type; /* BSS number */ u8 bss_num; - } bss; - } u; + } __attribute__ ((packed)) bss; + } __attribute__ ((packed)) u; /* SNR */ u8 snr;