Forwarded: [PATCH] e100: prevent shift out-of-bounds in e100_eeprom_load

syzbot <[email protected]>
Newsgroups org.kernel.vger.linux-kernel
Message-ID <[email protected]>
For archival purposes, forwarding an incoming command email to
[email protected], [email protected].

***

Subject: [PATCH] e100: prevent shift out-of-bounds in e100_eeprom_load
Author: [email protected]

From: Yalagada Pavan Kumar <[email protected]>

When reading the EEPROM address length, e100_eeprom_read() can return
an invalid length (0 or >= 16). Passing an invalid addr_len to bit-shift
operations causes a shift out-of-bounds, triggering a kernel panic or
UBSAN warning.

Validate addr_len after reading it from EEPROM and return -EINVAL if
the value is out of bounds. Additionally, use 1U to prevent
signed integer overflow when calculating eeprom_wc.

Reported-by: [email protected]
Link: https://syzkaller.appspot.com/bug?extid=e0abb1d45ac291ebebeb
Signed-off-by: Yalagada Pavan Kumar <[email protected]>
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
---
Tested using syzbot c reproducer.
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
---
 drivers/net/ethernet/intel/e100.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index 29960762e64a..1de5cd41ea0c 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -744,7 +744,12 @@ static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
 		 * complete address.  Use this to adjust addr_len. */
 		ctrl = ioread8(&nic->csr->eeprom_ctrl_lo);
 		if (!(ctrl & eedo) && i > 16) {
-			*addr_len -= (i - 16);
+			u16 len = i - 16;
+
+			if (len > *addr_len)
+				*addr_len = 0;
+			else
+				*addr_len -= len;
 			i = 17;
 		}
 
@@ -765,7 +770,15 @@ static int e100_eeprom_load(struct nic *nic)
 
 	/* Try reading with an 8-bit addr len to discover actual addr len */
 	e100_eeprom_read(nic, &addr_len, 0);
-	nic->eeprom_wc = 1 << addr_len;
+
+	if (!addr_len || addr_len >= 16) {
+		netif_err(nic, probe, nic->netdev,
+			"Invalid EEPROM address length %u\n",
+			addr_len);
+		return -EINVAL;
+	}
+
+	nic->eeprom_wc = 1U << addr_len;
 
 	for (addr = 0; addr < nic->eeprom_wc; addr++) {
 		nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr);
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.