[PATCH] lib: sbi_ecall_hsm: Reject oversized hart IDs

Shibo Zhu 3499129952 at qq.com
Mon Aug 17 11:12:02 PDT 2026


The HSM SBI interface passes hart IDs in XLEN-wide registers, while
OpenSBI's internal HSM APIs use u32 hart IDs. On RV64, values with upper
32 bits set are truncated before validation and can alias a valid hart.

Reject oversized target hart IDs at the ecall boundary for HART_START and
HART_GET_STATUS. Add SBIUnit coverage to ensure an oversized RV64 hart ID
does not alias the current hart. RV32 behavior is unchanged.

Fixes: e3f69fc1e934 ("lib: Implement Hart State Management (HSM) SBI extension")
Signed-off-by: Shibo Zhu <3499129952 at qq.com>
---
 lib/sbi/sbi_ecall_hsm.c            |  9 +++++++++
 lib/sbi/tests/objects.mk           |  2 ++
 lib/sbi/tests/sbi_ecall_hsm_test.c | 32 ++++++++++++++++++++++++++++++
 3 files changed, 43 insertions(+)
 create mode 100644 lib/sbi/tests/sbi_ecall_hsm_test.c

diff --git a/lib/sbi/sbi_ecall_hsm.c b/lib/sbi/sbi_ecall_hsm.c
index a6e83b05..b4f2b1bd 100644
--- a/lib/sbi/sbi_ecall_hsm.c
+++ b/lib/sbi/sbi_ecall_hsm.c
@@ -25,6 +25,11 @@ static int sbi_ecall_hsm_handler(unsigned long extid, unsigned long funcid,
 	ulong smode = (csr_read(CSR_MSTATUS) & MSTATUS_MPP) >>
 			MSTATUS_MPP_SHIFT;
 
+	if ((funcid == SBI_EXT_HSM_HART_START ||
+	     funcid == SBI_EXT_HSM_HART_GET_STATUS) &&
+	    (((u32)-1U) < ((u64)regs->a0)))
+		return SBI_EINVAL;
+
 	switch (funcid) {
 	case SBI_EXT_HSM_HART_START:
 		ret = sbi_hsm_hart_start(scratch, sbi_domain_thishart_ptr(),
@@ -67,3 +72,7 @@ struct sbi_ecall_extension ecall_hsm = {
 	.register_extensions	= sbi_ecall_hsm_register_extensions,
 	.handle			= sbi_ecall_hsm_handler,
 };
+
+#ifdef CONFIG_SBIUNIT
+#include "tests/sbi_ecall_hsm_test.c"
+#endif
diff --git a/lib/sbi/tests/objects.mk b/lib/sbi/tests/objects.mk
index 40c441e1..67316efb 100644
--- a/lib/sbi/tests/objects.mk
+++ b/lib/sbi/tests/objects.mk
@@ -16,6 +16,8 @@ libsbi-objs-$(CONFIG_SBIUNIT) += tests/riscv_locks_test.o
 carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += math_test_suite
 libsbi-objs-$(CONFIG_SBIUNIT) += tests/sbi_math_test.o
 
+carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += hsm_test_suite
+
 carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += ecall_test_suite
 libsbi-objs-$(CONFIG_SBIUNIT) += tests/sbi_ecall_test.o
 
diff --git a/lib/sbi/tests/sbi_ecall_hsm_test.c b/lib/sbi/tests/sbi_ecall_hsm_test.c
new file mode 100644
index 00000000..6bbcb99c
--- /dev/null
+++ b/lib/sbi/tests/sbi_ecall_hsm_test.c
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+#include <sbi/sbi_unit_test.h>
+
+static void hsm_hartid_test(struct sbiunit_test_case *test)
+{
+	struct sbi_ecall_return out = { 0 };
+	struct sbi_trap_regs regs = { 0 };
+
+	regs.a0 = current_hartid();
+	SBIUNIT_ASSERT_EQ(test,
+			  sbi_ecall_hsm_handler(SBI_EXT_HSM,
+						SBI_EXT_HSM_HART_GET_STATUS,
+						&regs, &out),
+			  SBI_OK);
+
+#if __riscv_xlen == 64
+	regs.a0 |= 1UL << 32;
+	SBIUNIT_EXPECT_EQ(test,
+			  sbi_ecall_hsm_handler(SBI_EXT_HSM,
+						SBI_EXT_HSM_HART_GET_STATUS,
+						&regs, &out),
+			  SBI_EINVAL);
+#endif
+}
+
+static struct sbiunit_test_case hsm_tests[] = {
+	SBIUNIT_TEST_CASE(hsm_hartid_test),
+	SBIUNIT_END_CASE,
+};
+
+SBIUNIT_TEST_SUITE(hsm_test_suite, hsm_tests);
-- 
2.43.0




More information about the opensbi mailing list