summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Stockhausen2025-05-02 17:44:29 +0000
committerStijn Tintel2025-05-12 13:09:19 +0000
commit47de87eb23c48315be208dad9995382208fad25f (patch)
tree8df0e8afefe042015bda2f228cc16b55ed16ac81
parent96ce4855bc8449b6afc31996c6b250199bbda7ae (diff)
downloadopenwrt-47de87eb23c48315be208dad9995382208fad25f.tar.gz
realtek: harden MDIO driver
At least since 2022 there is a major bug in the MDIO driver that produces out-of-bound reads and erratic behaviour during initialization. - mdiobus_scan_bus_c22() scans the bus for 64 devices (PHY_MAX_ADDR) - private bus structure only supports 57 entry arrays (MAX_PORTS) All the bus/reader writer functions accept calls with addr>=57 and will silently read beyond their limits. This can lead to ghost SERDES like https://github.com/openwrt/openwrt/issues/18665#issuecomment-2846053813 Add proper boundary checks and end the functions with -ENODEV that is the only accepted error code from the bus scan function. Fixes: 0536c582e673aa292 ("realtek: Fix RTL931X Ethernet driver") etc ... Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de> Link: https://github.com/openwrt/openwrt/pull/18402 Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
-rw-r--r--target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.c
index 269d8bed56..fe4e867065 100644
--- a/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.c
+++ b/target/linux/realtek/files-6.6/drivers/net/ethernet/rtl838x_eth.c
@@ -1819,6 +1819,9 @@ static int rtmdio_read_c45(struct mii_bus *bus, int addr, int devnum, int regnum
if (bus_priv->extaddr >= 0)
addr = bus_priv->extaddr;
+
+ if (addr >= RTMDIO_MAX_PORT)
+ return -ENODEV;
err = (*bus_priv->read_mmd_phy)(addr, devnum, regnum, &val);
pr_debug("rd_MMD(adr=%d, dev=%d, reg=%d) = %d, err = %d\n",
@@ -1834,6 +1837,9 @@ static int rtmdio_83xx_read(struct mii_bus *bus, int addr, int regnum)
if (bus_priv->extaddr >= 0)
addr = bus_priv->extaddr;
+
+ if (addr >= RTMDIO_MAX_PORT)
+ return -ENODEV;
if (addr >= 24 && addr <= 27 && eth_priv->id == 0x8380)
return rtl838x_read_sds_phy(addr, regnum);
@@ -1860,6 +1866,9 @@ static int rtmdio_93xx_read(struct mii_bus *bus, int addr, int regnum)
if (bus_priv->extaddr >= 0)
addr = bus_priv->extaddr;
+ if (addr >= RTMDIO_MAX_PORT)
+ return -ENODEV;
+
if (regnum == RTMDIO_PAGE_SELECT && bus_priv->page[addr] != bus_priv->rawpage)
return bus_priv->page[addr];
@@ -1887,6 +1896,9 @@ static int rtmdio_write_c45(struct mii_bus *bus, int addr, int devnum, int regnu
if (bus_priv->extaddr >= 0)
addr = bus_priv->extaddr;
+ if (addr >= RTMDIO_MAX_PORT)
+ return -ENODEV;
+
err = (*bus_priv->write_mmd_phy)(addr, devnum, regnum, val);
pr_debug("wr_MMD(adr=%d, dev=%d, reg=%d, val=%d) err = %d\n",
addr, devnum, regnum, val, err);
@@ -1906,6 +1918,10 @@ static int rtmdio_83xx_write(struct mii_bus *bus, int addr, int regnum, u16 val)
if (bus_priv->extaddr >= 0)
addr = bus_priv->extaddr;
+
+ if (addr >= RTMDIO_MAX_PORT)
+ return -ENODEV;
+
page = bus_priv->page[addr];
if (addr >= 24 && addr <= 27 && eth_priv->id == 0x8380) {
@@ -1946,6 +1962,10 @@ static int rtmdio_93xx_write(struct mii_bus *bus, int addr, int regnum, u16 val)
if (bus_priv->extaddr >= 0)
addr = bus_priv->extaddr;
+
+ if (addr >= RTMDIO_MAX_PORT)
+ return -ENODEV;
+
page = bus_priv->page[addr];
if (regnum == RTMDIO_PAGE_SELECT)