[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