[PATCH] lib: sbi_ecall_hsm: Reject oversized hart IDs

Shibo Zhu <[email protected]>
Newsgroups org.infradead.lists.opensbi
Message-ID <[email protected]>
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 <[email protected]>
---
 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


-- 
opensbi mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/opensbi
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.