Blame SOURCES/0002-e100-fix-buffer-overrun-in-e100_get_regs.patch

Kmods SIG 25e717
From 51032e6f17ce990d06123ad7307f258c50d25aa7 Mon Sep 17 00:00:00 2001
Kmods SIG 25e717
From: Jacob Keller <jacob.e.keller@intel.com>
Kmods SIG 25e717
Date: Wed, 8 Sep 2021 10:52:37 -0700
Kmods SIG 25e717
Subject: [Backport 51032e6f17ce] e100: fix buffer overrun in e100_get_regs
Kmods SIG 25e717
Kmods SIG 25e717
The e100_get_regs function is used to implement a simple register dump
Kmods SIG 25e717
for the e100 device. The data is broken into a couple of MAC control
Kmods SIG 25e717
registers, and then a series of PHY registers, followed by a memory dump
Kmods SIG 25e717
buffer.
Kmods SIG 25e717
Kmods SIG 25e717
The total length of the register dump is defined as (1 + E100_PHY_REGS)
Kmods SIG 25e717
* sizeof(u32) + sizeof(nic->mem->dump_buf).
Kmods SIG 25e717
Kmods SIG 25e717
The logic for filling in the PHY registers uses a convoluted inverted
Kmods SIG 25e717
count for loop which counts from E100_PHY_REGS (0x1C) down to 0, and
Kmods SIG 25e717
assigns the slots 1 + E100_PHY_REGS - i. The first loop iteration will
Kmods SIG 25e717
fill in [1] and the final loop iteration will fill in [1 + 0x1C]. This
Kmods SIG 25e717
is actually one more than the supposed number of PHY registers.
Kmods SIG 25e717
Kmods SIG 25e717
The memory dump buffer is then filled into the space at
Kmods SIG 25e717
[2 + E100_PHY_REGS] which will cause that memcpy to assign 4 bytes past
Kmods SIG 25e717
the total size.
Kmods SIG 25e717
Kmods SIG 25e717
The end result is that we overrun the total buffer size allocated by the
Kmods SIG 25e717
kernel, which could lead to a panic or other issues due to memory
Kmods SIG 25e717
corruption.
Kmods SIG 25e717
Kmods SIG 25e717
It is difficult to determine the actual total number of registers
Kmods SIG 25e717
here. The only 8255x datasheet I could find indicates there are 28 total
Kmods SIG 25e717
MDI registers. However, we're reading 29 here, and reading them in
Kmods SIG 25e717
reverse!
Kmods SIG 25e717
Kmods SIG 25e717
In addition, the ethtool e100 register dump interface appears to read
Kmods SIG 25e717
the first PHY register to determine if the device is in MDI or MDIx
Kmods SIG 25e717
mode. This doesn't appear to be documented anywhere within the 8255x
Kmods SIG 25e717
datasheet. I can only assume it must be in register 28 (the extra
Kmods SIG 25e717
register we're reading here).
Kmods SIG 25e717
Kmods SIG 25e717
Lets not change any of the intended meaning of what we copy here. Just
Kmods SIG 25e717
extend the space by 4 bytes to account for the extra register and
Kmods SIG 25e717
continue copying the data out in the same order.
Kmods SIG 25e717
Kmods SIG 25e717
Change the E100_PHY_REGS value to be the correct total (29) so that the
Kmods SIG 25e717
total register dump size is calculated properly. Fix the offset for
Kmods SIG 25e717
where we copy the dump buffer so that it doesn't overrun the total size.
Kmods SIG 25e717
Kmods SIG 25e717
Re-write the for loop to use counting up instead of the convoluted
Kmods SIG 25e717
down-counting. Correct the mdio_read offset to use the 0-based register
Kmods SIG 25e717
offsets, but maintain the bizarre reverse ordering so that we have the
Kmods SIG 25e717
ABI expected by applications like ethtool. This requires and additional
Kmods SIG 25e717
subtraction of 1. It seems a bit odd but it makes the flow of assignment
Kmods SIG 25e717
into the register buffer easier to follow.
Kmods SIG 25e717
Kmods SIG 25e717
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Kmods SIG 25e717
Reported-by: Felicitas Hetzelt <felicitashetzelt@gmail.com>
Kmods SIG 25e717
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Kmods SIG 25e717
Tested-by: Jacob Keller <jacob.e.keller@intel.com>
Kmods SIG 25e717
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Kmods SIG 25e717
---
Kmods SIG 25e717
 src/e100.c | 16 ++++++++++------
Kmods SIG 25e717
 1 file changed, 10 insertions(+), 6 deletions(-)
Kmods SIG 25e717
Kmods SIG 25e717
diff --git a/src/e100.c b/src/e100.c
Kmods SIG 25e717
index 588a59546d1237e7afb1e6b9bfcce37ecdf03a1c..09ae1939e6db4c7cc32e89708aa871763a543d91 100644
Kmods SIG 25e717
--- a/src/e100.c
Kmods SIG 25e717
+++ b/src/e100.c
Kmods SIG 25e717
@@ -2437,7 +2437,7 @@ static void e100_get_drvinfo(struct net_device *netdev,
Kmods SIG 25e717
 		sizeof(info->bus_info));
Kmods SIG 25e717
 }
Kmods SIG 25e717
 
Kmods SIG 25e717
-#define E100_PHY_REGS 0x1C
Kmods SIG 25e717
+#define E100_PHY_REGS 0x1D
Kmods SIG 25e717
 static int e100_get_regs_len(struct net_device *netdev)
Kmods SIG 25e717
 {
Kmods SIG 25e717
 	struct nic *nic = netdev_priv(netdev);
Kmods SIG 25e717
@@ -2459,14 +2459,18 @@ static void e100_get_regs(struct net_device *netdev,
Kmods SIG 25e717
 	buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 |
Kmods SIG 25e717
 		ioread8(&nic->csr->scb.cmd_lo) << 16 |
Kmods SIG 25e717
 		ioread16(&nic->csr->scb.status);
Kmods SIG 25e717
-	for (i = E100_PHY_REGS; i >= 0; i--)
Kmods SIG 25e717
-		buff[1 + E100_PHY_REGS - i] =
Kmods SIG 25e717
-			mdio_read(netdev, nic->mii.phy_id, i);
Kmods SIG 25e717
+	for (i = 0; i < E100_PHY_REGS; i++)
Kmods SIG 25e717
+		/* Note that we read the registers in reverse order. This
Kmods SIG 25e717
+		 * ordering is the ABI apparently used by ethtool and other
Kmods SIG 25e717
+		 * applications.
Kmods SIG 25e717
+		 */
Kmods SIG 25e717
+		buff[1 + i] = mdio_read(netdev, nic->mii.phy_id,
Kmods SIG 25e717
+					E100_PHY_REGS - 1 - i);
Kmods SIG 25e717
 	memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf));
Kmods SIG 25e717
 	e100_exec_cb(nic, NULL, e100_dump);
Kmods SIG 25e717
 	msleep(10);
Kmods SIG 25e717
-	memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf,
Kmods SIG 25e717
-		sizeof(nic->mem->dump_buf));
Kmods SIG 25e717
+	memcpy(&buff[1 + E100_PHY_REGS], nic->mem->dump_buf,
Kmods SIG 25e717
+	       sizeof(nic->mem->dump_buf));
Kmods SIG 25e717
 }
Kmods SIG 25e717
 
Kmods SIG 25e717
 static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
Kmods SIG 25e717
-- 
Kmods SIG 25e717
2.31.1
Kmods SIG 25e717