mii_read_host() uses the guest-supplied register index directly to read
from Mii.regs[], which has only MII_REG_MAX (16) entries.  The adjacent
mii_write_host() already rejects idx >= MII_REG_MAX, but the read path
did not, so a guest writing MIIADDRESS.RGAD to 16..31 and then setting
MIICOMMAND.RSTAT caused a host-side out-of-bounds read.

Return 0xffff for out-of-range indices; this matches the value already
used for reads with FIAD != DEFAULT_PHY and is the conventional value
for unimplemented MII registers.

Add a qtest on the lx60 board that programs RGAD == 16 and triggers the
read command, verifying MIIRX_DATA reads 0xffff instead of crashing or
tripping sanitizer checks.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/4364
Signed-off-by: Bin Guo <[email protected]>
---
 hw/net/opencores_eth.c           |  3 ++
 tests/qtest/meson.build          |  3 ++
 tests/qtest/opencores-eth-test.c | 66 ++++++++++++++++++++++++++++++++
 3 files changed, 72 insertions(+)
 create mode 100644 tests/qtest/opencores-eth-test.c

diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c
index 5a07bcde09..a4cf72e0c4 100644
--- a/hw/net/opencores_eth.c
+++ b/hw/net/opencores_eth.c
@@ -130,6 +130,9 @@ static void mii_write_host(Mii *s, unsigned idx, uint16_t v)
 
 static uint16_t mii_read_host(Mii *s, unsigned idx)
 {
+    if (idx >= MII_REG_MAX) {
+        return 0xffff;
+    }
     trace_open_eth_mii_read(idx, s->regs[idx]);
     return s->regs[idx];
 }
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index c3593f7530..deb1c59c1f 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -217,6 +217,9 @@ qtests_sparc64 = \
   qtests_filter + \
   ['prom-env-test', 'boot-serial-test']
 
+qtests_xtensa = \
+  (config_all_devices.has_key('CONFIG_OPENCORES_ETH') ? ['opencores-eth-test'] 
: [])
+
 qtests_npcm7xx = \
   ['npcm7xx_adc-test',
    'npcm7xx_gpio-test',
diff --git a/tests/qtest/opencores-eth-test.c b/tests/qtest/opencores-eth-test.c
new file mode 100644
index 0000000000..39f04fd4c3
--- /dev/null
+++ b/tests/qtest/opencores-eth-test.c
@@ -0,0 +1,66 @@
+/*
+ * QTest regression test for OpenCores Ethernet MII register read
+ *
+ * Copyright (c) 2026 Bin Guo
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+
+/*
+ * lx60 (MMU) maps its system_io at 0xf0000000; open_eth registers live at
+ * offset 0x0d030000 inside that region.
+ */
+#define OPEN_ETH_BASE 0xfd030000
+
+/* 32-bit word register indices */
+#define OPEN_ETH_MIICOMMAND  (OPEN_ETH_BASE + 0x2c)
+#define OPEN_ETH_MIIADDRESS  (OPEN_ETH_BASE + 0x30)
+#define OPEN_ETH_MIIRX_DATA  (OPEN_ETH_BASE + 0x38)
+
+#define MIIADDRESS_FIAD      0x00000001
+#define MIIADDRESS_RGAD_SHIFT 8
+#define MIICOMMAND_RSTAT     0x00000002
+
+/*
+ * Regression test for GitLab issue #4364:
+ * MIIADDRESS.RGAD is a 5-bit field (0..31), but the local PHY register
+ * array only has 16 entries.  A read with RGAD >= 16 must not perform an
+ * out-of-bounds access.
+ */
+static void test_mii_register_out_of_range(void)
+{
+    QTestState *s;
+
+    s = qtest_init("-machine lx60");
+
+    /* Select default PHY (FIAD == 1) and first out-of-range register. */
+    qtest_writel(s, OPEN_ETH_MIIADDRESS,
+                 MIIADDRESS_FIAD | (16 << MIIADDRESS_RGAD_SHIFT));
+
+    /* Trigger MII read command. */
+    qtest_writel(s, OPEN_ETH_MIICOMMAND, MIICOMMAND_RSTAT);
+
+    /*
+     * With the bug, the read path evaluates s->regs[16] and trips ASan/UBSan.
+     * With the fix, MIIRX_DATA.PRSD should read as 0xffff (unimplemented PHY
+     * register), matching the non-default-PHY fallback in the driver.
+     */
+    g_assert_cmphex(qtest_readl(s, OPEN_ETH_MIIRX_DATA), ==, 0xffff);
+
+    qtest_quit(s);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    if (qtest_has_machine("lx60")) {
+        qtest_add_func("/opencores-eth/mii-register-out-of-range",
+                       test_mii_register_out_of_range);
+    }
+
+    return g_test_run();
+}
-- 
2.50.1 (Apple Git-155)


Reply via email to