lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20120110215603.022635510@clark.kroah.org>
Date:	Tue, 10 Jan 2012 13:55:20 -0800
From:	Greg KH <gregkh@...e.de>
To:	linux-kernel@...r.kernel.org, stable@...r.kernel.org
Cc:	torvalds@...ux-foundation.org, akpm@...ux-foundation.org,
	alan@...rguk.ukuu.org.uk,
	Emmanuel Grumbach <emmanuel.grumbach@...el.com>,
	Johannes Berg <johannes.berg@...el.com>,
	Wey-Yi Guy <wey-yi.w.guy@...el.com>,
	"John W. Linville" <linville@...driver.com>
Subject: [17/49] iwlagn: fix (remove) use of PAGE_SIZE

3.2-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Johannes Berg <johannes.berg@...el.com>

commit 106671369e6d046c0b3e1e72b18ad6dd9cb298b0 upstream.

The ICT code erroneously uses PAGE_SIZE. The bug
is that PAGE_SIZE isn't necessarily 4096, so on
such platforms this code will not work correctly
as we'll try to attempt to read an index in the
table that the device never wrote, it always has
4096-byte pages.

Additionally, the manual alignment code here is
unnecessary -- Documentation/DMA-API-HOWTO.txt
states:
  The cpu return address and the DMA bus master address are both
  guaranteed to be aligned to the smallest PAGE_SIZE order which
  is greater than or equal to the requested size.  This invariant
  exists (for example) to guarantee that if you allocate a chunk
  which is smaller than or equal to 64 kilobytes, the extent of the
  buffer you receive will not cross a 64K boundary.

Just use appropriate new constants and get rid of
the alignment code.

Cc: Emmanuel Grumbach <emmanuel.grumbach@...el.com>
Signed-off-by: Johannes Berg <johannes.berg@...el.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@...el.com>
Signed-off-by: John W. Linville <linville@...driver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@...e.de>

---
 drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h |    2 
 drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c  |   77 +++++++++-------------
 2 files changed, 33 insertions(+), 46 deletions(-)

--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
@@ -219,9 +219,7 @@ struct iwl_trans_pcie {
 
 	/* INT ICT Table */
 	__le32 *ict_tbl;
-	void *ict_tbl_vir;
 	dma_addr_t ict_tbl_dma;
-	dma_addr_t aligned_ict_tbl_dma;
 	int ict_index;
 	u32 inta;
 	bool use_ict;
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
@@ -1136,7 +1136,11 @@ void iwl_irq_tasklet(struct iwl_trans *t
  * ICT functions
  *
  ******************************************************************************/
-#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
+
+/* a device (PCI-E) page is 4096 bytes long */
+#define ICT_SHIFT	12
+#define ICT_SIZE	(1 << ICT_SHIFT)
+#define ICT_COUNT	(ICT_SIZE / sizeof(u32))
 
 /* Free dram table */
 void iwl_free_isr_ict(struct iwl_trans *trans)
@@ -1144,21 +1148,19 @@ void iwl_free_isr_ict(struct iwl_trans *
 	struct iwl_trans_pcie *trans_pcie =
 		IWL_TRANS_GET_PCIE_TRANS(trans);
 
-	if (trans_pcie->ict_tbl_vir) {
-		dma_free_coherent(bus(trans)->dev,
-				  (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
-				  trans_pcie->ict_tbl_vir,
+	if (trans_pcie->ict_tbl) {
+		dma_free_coherent(bus(trans)->dev, ICT_SIZE,
+				  trans_pcie->ict_tbl,
 				  trans_pcie->ict_tbl_dma);
-		trans_pcie->ict_tbl_vir = NULL;
-		memset(&trans_pcie->ict_tbl_dma, 0,
-			sizeof(trans_pcie->ict_tbl_dma));
-		memset(&trans_pcie->aligned_ict_tbl_dma, 0,
-			sizeof(trans_pcie->aligned_ict_tbl_dma));
+		trans_pcie->ict_tbl = NULL;
+		trans_pcie->ict_tbl_dma = 0;
 	}
 }
 
 
-/* allocate dram shared table it is a PAGE_SIZE aligned
+/*
+ * allocate dram shared table, it is an aligned memory
+ * block of ICT_SIZE.
  * also reset all data related to ICT table interrupt.
  */
 int iwl_alloc_isr_ict(struct iwl_trans *trans)
@@ -1166,36 +1168,26 @@ int iwl_alloc_isr_ict(struct iwl_trans *
 	struct iwl_trans_pcie *trans_pcie =
 		IWL_TRANS_GET_PCIE_TRANS(trans);
 
-	/* allocate shrared data table */
-	trans_pcie->ict_tbl_vir =
-		dma_alloc_coherent(bus(trans)->dev,
-				   (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
-				   &trans_pcie->ict_tbl_dma, GFP_KERNEL);
-	if (!trans_pcie->ict_tbl_vir)
+	trans_pcie->ict_tbl =
+		dma_alloc_coherent(bus(trans)->dev, ICT_SIZE,
+				   &trans_pcie->ict_tbl_dma,
+				   GFP_KERNEL);
+	if (!trans_pcie->ict_tbl)
 		return -ENOMEM;
 
-	/* align table to PAGE_SIZE boundary */
-	trans_pcie->aligned_ict_tbl_dma =
-		ALIGN(trans_pcie->ict_tbl_dma, PAGE_SIZE);
-
-	IWL_DEBUG_ISR(trans, "ict dma addr %Lx dma aligned %Lx diff %d\n",
-			   (unsigned long long)trans_pcie->ict_tbl_dma,
-			   (unsigned long long)trans_pcie->aligned_ict_tbl_dma,
-			   (int)(trans_pcie->aligned_ict_tbl_dma -
-			   trans_pcie->ict_tbl_dma));
-
-	trans_pcie->ict_tbl =  trans_pcie->ict_tbl_vir +
-			  (trans_pcie->aligned_ict_tbl_dma -
-			  trans_pcie->ict_tbl_dma);
-
-	IWL_DEBUG_ISR(trans, "ict vir addr %p vir aligned %p diff %d\n",
-			     trans_pcie->ict_tbl, trans_pcie->ict_tbl_vir,
-			(int)(trans_pcie->aligned_ict_tbl_dma -
-			    trans_pcie->ict_tbl_dma));
+	/* just an API sanity check ... it is guaranteed to be aligned */
+	if (WARN_ON(trans_pcie->ict_tbl_dma & (ICT_SIZE - 1))) {
+		iwl_free_isr_ict(trans);
+		return -EINVAL;
+	}
+
+	IWL_DEBUG_ISR(trans, "ict dma addr %Lx\n",
+		      (unsigned long long)trans_pcie->ict_tbl_dma);
+
+	IWL_DEBUG_ISR(trans, "ict vir addr %p\n", trans_pcie->ict_tbl);
 
 	/* reset table and index to all 0 */
-	memset(trans_pcie->ict_tbl_vir, 0,
-		(sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
+	memset(trans_pcie->ict_tbl, 0, ICT_SIZE);
 	trans_pcie->ict_index = 0;
 
 	/* add periodic RX interrupt */
@@ -1213,23 +1205,20 @@ int iwl_reset_ict(struct iwl_trans *tran
 	struct iwl_trans_pcie *trans_pcie =
 		IWL_TRANS_GET_PCIE_TRANS(trans);
 
-	if (!trans_pcie->ict_tbl_vir)
+	if (!trans_pcie->ict_tbl)
 		return 0;
 
 	spin_lock_irqsave(&trans->shrd->lock, flags);
 	iwl_disable_interrupts(trans);
 
-	memset(&trans_pcie->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
+	memset(trans_pcie->ict_tbl, 0, ICT_SIZE);
 
-	val = trans_pcie->aligned_ict_tbl_dma >> PAGE_SHIFT;
+	val = trans_pcie->ict_tbl_dma >> ICT_SHIFT;
 
 	val |= CSR_DRAM_INT_TBL_ENABLE;
 	val |= CSR_DRAM_INIT_TBL_WRAP_CHECK;
 
-	IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%X "
-			"aligned dma address %Lx\n",
-			val,
-			(unsigned long long)trans_pcie->aligned_ict_tbl_dma);
+	IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%x\n", val);
 
 	iwl_write32(bus(trans), CSR_DRAM_INT_TBL_REG, val);
 	trans_pcie->use_ict = true;


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ