From bcadc93ae8338b08a7d47b9d11157cce20b23b6a Mon Sep 17 00:00:00 2001 From: Alvin Chang Date: Tue, 18 Jul 2023 15:07:59 +0800 Subject: [PATCH] core: riscv: Support Privileged Access Never by status.SUM bit The SUM (Supervisor User Memory access) bit modifies the privilege with which S-mode loads and stores the user virtual memory. When SUM bit is 0, S-mode accesses to pages whose U bit of corresponding PTE is set will fault. When SUM bit is 1, these accesses are permitted. When CFG_PAN is disabled in RISC-V architecture, the status.SUM bit is initialized as 1 by default. Therefore all accesses to user pages will succeed. When CFG_PAN is enabled, the status.SUM bit is initialized as 0, and only set to 1 when kernel needs to access user pages. Signed-off-by: Alvin Chang Tested-by: Marouene Boubakri --- .../riscv/include/kernel/user_access_arch.h | 16 ++++++++++- core/arch/riscv/kernel/arch_scall.c | 27 ++++++++++++++----- core/arch/riscv/kernel/thread_arch.c | 7 ++++- mk/config.mk | 3 ++- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/core/arch/riscv/include/kernel/user_access_arch.h b/core/arch/riscv/include/kernel/user_access_arch.h index 6d9c952f5f6..2b9d563fd83 100644 --- a/core/arch/riscv/include/kernel/user_access_arch.h +++ b/core/arch/riscv/include/kernel/user_access_arch.h @@ -1,15 +1,29 @@ /* SPDX-License-Identifier: BSD-2-Clause */ /* + * Copyright (c) 2023 Andes Technology Corporation * Copyright (c) 2023, Amazon.com Inc. or its affiliates. All rights Reserved. */ #ifndef __KERNEL_USER_ACCESS_ARCH_H #define __KERNEL_USER_ACCESS_ARCH_H +#include + +#ifdef CFG_PAN /* Enter a section where user mode access is temporarily enabled. */ -static inline void enter_user_access(void) {} +static inline void enter_user_access(void) +{ + set_csr(CSR_XSTATUS, CSR_XSTATUS_SUM); +} /* Exit from the section where user mode access was temporarily enabled. */ +static inline void exit_user_access(void) +{ + clear_csr(CSR_XSTATUS, CSR_XSTATUS_SUM); +} +#else +static inline void enter_user_access(void) {} static inline void exit_user_access(void) {} +#endif /* CFG_PAN */ #endif /* __KERNEL_USER_ACCESS_ARCH_H */ diff --git a/core/arch/riscv/kernel/arch_scall.c b/core/arch/riscv/kernel/arch_scall.c index 33a35309203..546ea68c1cb 100644 --- a/core/arch/riscv/kernel/arch_scall.c +++ b/core/arch/riscv/kernel/arch_scall.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -23,15 +24,29 @@ static void save_panic_regs_rv_ta(struct thread_specific_data *tsd, unsigned long *pushed) { - tsd->abort_regs = (struct thread_abort_regs){ - .sp = (unsigned long)pushed, + TEE_Result res = TEE_SUCCESS; + unsigned long s0 = 0; + unsigned long epc = 0; #if defined(RV32) - .s0 = pushed[2], - .epc = pushed[3], + unsigned long *stack_s0 = &pushed[2]; + unsigned long *stack_epc = &pushed[3]; #elif defined(RV64) - .s0 = pushed[0], - .epc = pushed[1], + unsigned long *stack_s0 = &pushed[0]; + unsigned long *stack_epc = &pushed[1]; #endif + + res = GET_USER_SCALAR(s0, stack_s0); + if (res) + s0 = 0; + + res = GET_USER_SCALAR(epc, stack_epc); + if (res) + epc = 0; + + tsd->abort_regs = (struct thread_abort_regs){ + .sp = (unsigned long)pushed, + .s0 = s0, + .epc = epc, }; } diff --git a/core/arch/riscv/kernel/thread_arch.c b/core/arch/riscv/kernel/thread_arch.c index 0f78b2da325..af20c8ff1b3 100644 --- a/core/arch/riscv/kernel/thread_arch.c +++ b/core/arch/riscv/kernel/thread_arch.c @@ -565,8 +565,13 @@ void thread_init_per_cpu(void) * and kernel traps. */ write_csr(CSR_XSCRATCH, 0); - /* Allow access to user pages */ +#ifndef CFG_PAN + /* + * Allow access to user pages. When CFG_PAN is enabled, the SUM bit will + * be set and clear at runtime when necessary. + */ set_csr(CSR_XSTATUS, CSR_XSTATUS_SUM); +#endif } static void set_ctx_regs(struct thread_ctx_regs *regs, unsigned long a0, diff --git a/mk/config.mk b/mk/config.mk index ea35bddd2a5..04eb9a0e8b3 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -929,9 +929,10 @@ endif # Privileged Access Never (PAN, part of the ARMv8.1 Extensions) can be # used to restrict accesses to unprivileged memory from privileged mode. +# For RISC-V architecture, CSR {m|s}status.SUM bit is used to implement PAN. CFG_PAN ?= n -$(eval $(call cfg-depends-all,CFG_PAN,CFG_ARM64_core)) +$(eval $(call cfg-depends-one,CFG_PAN,CFG_ARM64_core CFG_RV64_core CFG_RV32_core)) # CFG_CORE_ASYNC_NOTIF is defined by the platform to enable support # for sending asynchronous notifications to normal world. Note that an