From: Bin Guo <guobin@linux.alibaba.com>
To: qemu-devel@nongnu.org
Cc: Max Filippov <jcmvbkbc@gmail.com>,
Jason Wang <jasowangio@gmail.com>,
Fabiano Rosas <farosas@suse.de>,
Laurent Vivier <lvivier@redhat.com>,
Paolo Bonzini <pbonzini@redhat.com>
Subject: [PATCH] hw/net/opencores_eth: clamp MII register read to local PHY array
Date: Tue, 15 Sep 2026 15:17:43 +0800 [thread overview]
Message-ID: <20260915071743.22125-1-guobin@linux.alibaba.com> (raw)
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 <guobin@linux.alibaba.com>
---
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 other threads:[~2026-09-15 7:18 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260915071743.22125-1-guobin@linux.alibaba.com \
--to=guobin@linux.alibaba.com \
--cc=farosas@suse.de \
--cc=jasowangio@gmail.com \
--cc=jcmvbkbc@gmail.com \
--cc=lvivier@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.