[openwrt/openwrt] realtek: RTL838x harden ethernet driver against fuzzying

LEDE Commits lede-commits at lists.infradead.org
Mon Aug 11 06:18:12 PDT 2025


robimarko pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/0724412c58896b765fff77d63907729d298fbb67

commit 0724412c58896b765fff77d63907729d298fbb67
Author: Markus Stockhausen <markus.stockhausen at gmx.de>
AuthorDate: Tue Aug 5 11:46:40 2025 -0400

    realtek: RTL838x harden ethernet driver against fuzzying
    
    While checking setup routines for stability and completeness,
    random RTL838x SoC I/O areas were intentionally overwritten.
    As soon as L2_CTRL_1->FAST_AGE_OUT is set to 1, the system
    stalls during bootup. Analysis shows that it loops endlessly
    in rtl838x_hw_stop()
    
    /* Flush L2 address cache */
    if (priv->family_id == RTL8380_FAMILY_ID) {
            for (int i = 0; i <= priv->cpu_port; i++) {
                    sw_w32(1 << 26 | 1 << 23 | i << 5, priv->r->l2_tbl_flush_ctrl);
                    do { } while (sw_r32(priv->r->l2_tbl_flush_ctrl) & (1 << 26));
            }
    
    This is exactly the same logic as in the vendor GPL. There
    are no hints about possible timeouts or issues. The reason is
    still unclear. Nevertheless harden the function for further fuzzy
    tests. Do this by resetting the configuration value to its SoC
    default.
    
    Additionally convert some shifts to BIT() for better readability.
    
    Signed-off-by: Markus Stockhausen <markus.stockhausen at gmx.de>
    Link: https://github.com/openwrt/openwrt/pull/19679
    Signed-off-by: Robert Marko <robimarko at gmail.com>
---
 .../realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c      | 10 ++++++----
 .../realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h      |  1 +
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c
index 66b808dba9..37dab0f2db 100644
--- a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c
+++ b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c
@@ -947,14 +947,16 @@ static void rtl838x_hw_stop(struct rtl838x_eth_priv *priv)
 
 	/* Flush L2 address cache */
 	if (priv->family_id == RTL8380_FAMILY_ID) {
+		/* Disable FAST_AGE_OUT otherwise flush will hang */
+		sw_w32_mask(BIT(23), 0, RTL838X_L2_CTRL_1);
 		for (int i = 0; i <= priv->cpu_port; i++) {
-			sw_w32(1 << 26 | 1 << 23 | i << 5, priv->r->l2_tbl_flush_ctrl);
-			do { } while (sw_r32(priv->r->l2_tbl_flush_ctrl) & (1 << 26));
+			sw_w32(BIT(26) | BIT(23) | i << 5, priv->r->l2_tbl_flush_ctrl);
+			do { } while (sw_r32(priv->r->l2_tbl_flush_ctrl) & BIT(26));
 		}
 	} else if (priv->family_id == RTL8390_FAMILY_ID) {
 		for (int i = 0; i <= priv->cpu_port; i++) {
-			sw_w32(1 << 28 | 1 << 25 | i << 5, priv->r->l2_tbl_flush_ctrl);
-			do { } while (sw_r32(priv->r->l2_tbl_flush_ctrl) & (1 << 28));
+			sw_w32(BIT(28) | BIT(25) | i << 5, priv->r->l2_tbl_flush_ctrl);
+			do { } while (sw_r32(priv->r->l2_tbl_flush_ctrl) & BIT(28));
 		}
 	}
 	/* TODO: L2 flush register is 64 bit on RTL931X and 930X */
diff --git a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h
index 24c750b403..edeea8f6e2 100644
--- a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h
+++ b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h
@@ -165,6 +165,7 @@
 #define RTL839X_L2_NOTIFICATION_CTRL		(0x7808)
 #define RTL931X_L2_NTFY_CTRL			(0xCDC8)
 #define RTL838X_L2_CTRL_0			(0x3200)
+#define RTL838X_L2_CTRL_1			(0x3204)
 #define RTL839X_L2_CTRL_0			(0x3800)
 #define RTL930X_L2_CTRL				(0x8FD8)
 #define RTL931X_L2_CTRL				(0xC800)




More information about the lede-commits mailing list