From 3898597f53f09da308b0d7b72b642bf179b1019f Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 10 Nov 2024 13:51:02 +0800 Subject: [PATCH 1/3] arch: riscv: add macro to access hardware registers Add macros to read / write hardware registers. Signed-off-by: Yong Cong Sin Signed-off-by: Yong Cong Sin --- include/zephyr/arch/riscv/reg.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 include/zephyr/arch/riscv/reg.h diff --git a/include/zephyr/arch/riscv/reg.h b/include/zephyr/arch/riscv/reg.h new file mode 100644 index 0000000000000..6d3b2d88b1755 --- /dev/null +++ b/include/zephyr/arch/riscv/reg.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024 Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ZEPHYR_ARCH_RISCV_REG_H_ +#define ZEPHYR_INCLUDE_ZEPHYR_ARCH_RISCV_REG_H_ + +#define reg_read(reg) \ + ({ \ + register unsigned long __rv; \ + __asm__ volatile("mv %0, " STRINGIFY(reg) : "=r"(__rv)); \ + __rv; \ + }) + +#define reg_write(reg, val) ({ __asm__("mv " STRINGIFY(reg) ", %0" : : "r"(val)); }) + +#endif /* ZEPHYR_INCLUDE_ZEPHYR_ARCH_RISCV_REG_H_ */ From 6193a9376910b94bab67d77ffcb03b329adf614f Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sat, 9 Nov 2024 02:15:21 +0800 Subject: [PATCH 2/3] arch: riscv: reset global pointer on exception Reset the gp on exception entry from u-mode to protect the kernel against a possible rogue user thread. Signed-off-by: Yong Cong Sin Signed-off-by: Yong Cong Sin --- arch/riscv/core/isr.S | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/riscv/core/isr.S b/arch/riscv/core/isr.S index 65c40e63456e1..5ac71fe17b473 100644 --- a/arch/riscv/core/isr.S +++ b/arch/riscv/core/isr.S @@ -163,6 +163,14 @@ SECTION_FUNC(exception.entry, _isr_wrapper) lr t0, ___cpu_t_current_OFFSET(s0) lr tp, _thread_offset_to_tls(t0) + /* Make sure global pointer is sane */ +#ifdef CONFIG_RISCV_GP + .option push + .option norelax + la gp, __global_pointer$ + .option pop +#endif /* CONFIG_RISCV_GP */ + /* Clear our per-thread usermode flag */ lui t0, %tprel_hi(is_user_mode) add t0, t0, tp, %tprel_add(is_user_mode) From 3a82ebbcc788063f02bb41f04f88fc78bacd7b5e Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 10 Nov 2024 14:03:35 +0800 Subject: [PATCH 3/3] tests: arch: riscv: make sure that `gp` reg can't be corrupted Add a test to make sure that the `gp` global pointer register used for relative addressing when `CONFIG_RISCV_GP` is enabled can't be corrupted by a rogue user thread. Signed-off-by: Yong Cong Sin Signed-off-by: Yong Cong Sin --- .../riscv/userspace/riscv_gp/CMakeLists.txt | 8 ++++ tests/arch/riscv/userspace/riscv_gp/prj.conf | 3 ++ .../arch/riscv/userspace/riscv_gp/src/main.c | 47 +++++++++++++++++++ .../riscv/userspace/riscv_gp/testcase.yaml | 8 ++++ 4 files changed, 66 insertions(+) create mode 100644 tests/arch/riscv/userspace/riscv_gp/CMakeLists.txt create mode 100644 tests/arch/riscv/userspace/riscv_gp/prj.conf create mode 100644 tests/arch/riscv/userspace/riscv_gp/src/main.c create mode 100644 tests/arch/riscv/userspace/riscv_gp/testcase.yaml diff --git a/tests/arch/riscv/userspace/riscv_gp/CMakeLists.txt b/tests/arch/riscv/userspace/riscv_gp/CMakeLists.txt new file mode 100644 index 0000000000000..04987303450f5 --- /dev/null +++ b/tests/arch/riscv/userspace/riscv_gp/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(riscv_gp) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/arch/riscv/userspace/riscv_gp/prj.conf b/tests/arch/riscv/userspace/riscv_gp/prj.conf new file mode 100644 index 0000000000000..1f8e1275be3e2 --- /dev/null +++ b/tests/arch/riscv/userspace/riscv_gp/prj.conf @@ -0,0 +1,3 @@ +CONFIG_ZTEST=y +CONFIG_RISCV_GP=y +CONFIG_TEST_USERSPACE=y diff --git a/tests/arch/riscv/userspace/riscv_gp/src/main.c b/tests/arch/riscv/userspace/riscv_gp/src/main.c new file mode 100644 index 0000000000000..76a9ecffc22f7 --- /dev/null +++ b/tests/arch/riscv/userspace/riscv_gp/src/main.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include + +#define ROGUE_USER_STACK_SZ 2048 + +static struct k_thread rogue_user_thread; +static K_THREAD_STACK_DEFINE(rogue_user_stack, ROGUE_USER_STACK_SZ); + +static void rogue_user_fn(void *p1, void *p2, void *p3) +{ + zassert_true(k_is_user_context()); + + reg_write(gp, 0xbad); + zassert_equal(reg_read(gp), 0xbad); +} + +ZTEST_USER(riscv_gp, test_gp_value) +{ + uintptr_t gp_val = reg_read(gp); + k_tid_t th; + + zassert_not_equal(gp_val, 0); + + th = k_thread_create(&rogue_user_thread, rogue_user_stack, ROGUE_USER_STACK_SZ, + rogue_user_fn, NULL, NULL, NULL, -1, K_USER, K_NO_WAIT); + zassert_ok(k_thread_join(th, K_FOREVER)); + + zassert_equal(reg_read(gp), gp_val, "`gp` corrupted by user thread"); +} + +static void *userspace_setup(void) +{ + k_thread_access_grant(k_current_get(), &rogue_user_thread, &rogue_user_stack); + + return NULL; +} + +ZTEST_SUITE(riscv_gp, NULL, userspace_setup, NULL, NULL, NULL); diff --git a/tests/arch/riscv/userspace/riscv_gp/testcase.yaml b/tests/arch/riscv/userspace/riscv_gp/testcase.yaml new file mode 100644 index 0000000000000..5b1345abc5475 --- /dev/null +++ b/tests/arch/riscv/userspace/riscv_gp/testcase.yaml @@ -0,0 +1,8 @@ +common: + ignore_faults: true + ignore_qemu_crash: true + tags: kernel riscv + platform_allow: + - qemu_riscv64 +tests: + arch.riscv64.riscv_gp: {}