Takashi Iwai a95c58
From b106776080a1cf953a1b2fd50cb2a995db4732be Mon Sep 17 00:00:00 2001
Takashi Iwai a95c58
From: Mathias Nyman <mathias.nyman@linux.intel.com>
Takashi Iwai a95c58
Date: Tue, 27 Apr 2021 15:48:29 +0300
Takashi Iwai a95c58
Subject: [PATCH] thunderbolt: dma_port: Fix NVM read buffer bounds and offset issue
Takashi Iwai a95c58
Git-commit: b106776080a1cf953a1b2fd50cb2a995db4732be
Takashi Iwai a95c58
Patch-mainline: v5.13-rc4
Takashi Iwai a95c58
References: git-fixes
Takashi Iwai a95c58
Takashi Iwai a95c58
Up to 64 bytes of data can be read from NVM in one go. Read address
Takashi Iwai a95c58
must be dword aligned. Data is read into a local buffer.
Takashi Iwai a95c58
Takashi Iwai a95c58
If caller asks to read data starting at an unaligned address then full
Takashi Iwai a95c58
dword is anyway read from NVM into a local buffer. Data is then copied
Takashi Iwai a95c58
from the local buffer starting at the unaligned offset to the caller
Takashi Iwai a95c58
buffer.
Takashi Iwai a95c58
Takashi Iwai a95c58
In cases where asked data length + unaligned offset is over 64 bytes
Takashi Iwai a95c58
we need to make sure we don't read past the 64 bytes in the local
Takashi Iwai a95c58
buffer when copying to caller buffer, and make sure that we don't
Takashi Iwai a95c58
skip copying unaligned offset bytes from local buffer anymore after
Takashi Iwai a95c58
the first round of 64 byte NVM data read.
Takashi Iwai a95c58
Takashi Iwai a95c58
Fixes: 3e13676862f9 ("thunderbolt: Add support for DMA configuration based mailbox")
Takashi Iwai a95c58
Cc: stable@vger.kernel.org
Takashi Iwai a95c58
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Takashi Iwai a95c58
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Takashi Iwai a95c58
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai a95c58
Takashi Iwai a95c58
---
Takashi Iwai a95c58
 drivers/thunderbolt/dma_port.c | 11 ++++++-----
Takashi Iwai a95c58
 1 file changed, 6 insertions(+), 5 deletions(-)
Takashi Iwai a95c58
Takashi Iwai a95c58
diff --git a/drivers/thunderbolt/dma_port.c b/drivers/thunderbolt/dma_port.c
Takashi Iwai a95c58
index 7288aaf01ae6..5631319f7b20 100644
Takashi Iwai a95c58
--- a/drivers/thunderbolt/dma_port.c
Takashi Iwai a95c58
+++ b/drivers/thunderbolt/dma_port.c
Takashi Iwai a95c58
@@ -366,15 +366,15 @@ int dma_port_flash_read(struct tb_dma_port *dma, unsigned int address,
Takashi Iwai a95c58
 			void *buf, size_t size)
Takashi Iwai a95c58
 {
Takashi Iwai a95c58
 	unsigned int retries = DMA_PORT_RETRIES;
Takashi Iwai a95c58
-	unsigned int offset;
Takashi Iwai a95c58
-
Takashi Iwai a95c58
-	offset = address & 3;
Takashi Iwai a95c58
-	address = address & ~3;
Takashi Iwai a95c58
 
Takashi Iwai a95c58
 	do {
Takashi Iwai a95c58
-		u32 nbytes = min_t(u32, size, MAIL_DATA_DWORDS * 4);
Takashi Iwai a95c58
+		unsigned int offset;
Takashi Iwai a95c58
+		size_t nbytes;
Takashi Iwai a95c58
 		int ret;
Takashi Iwai a95c58
 
Takashi Iwai a95c58
+		offset = address & 3;
Takashi Iwai a95c58
+		nbytes = min_t(size_t, size + offset, MAIL_DATA_DWORDS * 4);
Takashi Iwai a95c58
+
Takashi Iwai a95c58
 		ret = dma_port_flash_read_block(dma, address, dma->buf,
Takashi Iwai a95c58
 						ALIGN(nbytes, 4));
Takashi Iwai a95c58
 		if (ret) {
Takashi Iwai a95c58
@@ -386,6 +386,7 @@ int dma_port_flash_read(struct tb_dma_port *dma, unsigned int address,
Takashi Iwai a95c58
 			return ret;
Takashi Iwai a95c58
 		}
Takashi Iwai a95c58
 
Takashi Iwai a95c58
+		nbytes -= offset;
Takashi Iwai a95c58
 		memcpy(buf, dma->buf + offset, nbytes);
Takashi Iwai a95c58
 
Takashi Iwai a95c58
 		size -= nbytes;
Takashi Iwai a95c58
-- 
Takashi Iwai a95c58
2.26.2
Takashi Iwai a95c58