From 382e9bcac746b408b5b01ea2f59338428ab203dd Mon Sep 17 00:00:00 2001 From: Shell Date: Fri, 24 Feb 2023 14:52:16 +0800 Subject: [PATCH] [rt-smart] handling kernel from accessing unmapped user stack (#6957) [rt-smart] handling kernel from accessing unmapped user stack --- components/lwp/arch/risc-v/rv64/lwp_gcc.S | 10 ++++++++++ components/lwp/lwp_user_mm.c | 11 +++++++---- libcpu/risc-v/t-head/c906/stackframe.h | 6 +++++- libcpu/risc-v/t-head/c906/trap.c | 5 ++++- libcpu/risc-v/virt64/stackframe.h | 7 ++++--- libcpu/risc-v/virt64/trap.c | 5 ++++- 6 files changed, 34 insertions(+), 10 deletions(-) diff --git a/components/lwp/arch/risc-v/rv64/lwp_gcc.S b/components/lwp/arch/risc-v/rv64/lwp_gcc.S index c54726bc45..3977553dbf 100644 --- a/components/lwp/arch/risc-v/rv64/lwp_gcc.S +++ b/components/lwp/arch/risc-v/rv64/lwp_gcc.S @@ -121,6 +121,16 @@ arch_signal_quit: * routine in user stack */ user_do_signal: + /* prefetch ustack to avoid corrupted status in RESTORE/STORE pair below */ + LOAD t0, FRAME_OFF_SP(sp) + addi t1, t0, -CTX_REG_NR * REGBYTES + LOAD t2, (t0) + li t3, -0x1000 +1: + add t0, t0, t3 + LOAD t2, (t0) + bgt t0, t1, 1b + /** restore and backup kernel sp carefully to avoid leaking */ addi t0, sp, CTX_REG_NR * REGBYTES csrw sscratch, t0 diff --git a/components/lwp/lwp_user_mm.c b/components/lwp/lwp_user_mm.c index 3844a3b189..edda62632d 100644 --- a/components/lwp/lwp_user_mm.c +++ b/components/lwp/lwp_user_mm.c @@ -560,9 +560,12 @@ int lwp_user_accessable(void *addr, size_t size) len = size; } tmp_addr = lwp_v2p(lwp, addr_start); - if (!tmp_addr) + if (tmp_addr == ARCH_MAP_FAILED) { - return 0; + if ((rt_ubase_t)addr_start >= USER_STACK_VSTART && (rt_ubase_t)addr_start < USER_STACK_VEND) + tmp_addr = *(void **)addr_start; + else + return 0; } addr_start = (void *)((char *)addr_start + len); size -= len; @@ -596,7 +599,7 @@ size_t lwp_data_get(struct rt_lwp *lwp, void *dst, void *src, size_t size) len = size; } tmp_src = lwp_v2p(lwp, addr_start); - if (!tmp_src) + if (tmp_src == ARCH_MAP_FAILED) { break; } @@ -636,7 +639,7 @@ size_t lwp_data_put(struct rt_lwp *lwp, void *dst, void *src, size_t size) len = size; } tmp_dst = lwp_v2p(lwp, addr_start); - if (!tmp_dst) + if (tmp_dst == ARCH_MAP_FAILED) { break; } diff --git a/libcpu/risc-v/t-head/c906/stackframe.h b/libcpu/risc-v/t-head/c906/stackframe.h index 1e191900b4..d6fd0c3c5e 100644 --- a/libcpu/risc-v/t-head/c906/stackframe.h +++ b/libcpu/risc-v/t-head/c906/stackframe.h @@ -13,6 +13,10 @@ #ifndef __STACKFRAME_H__ #define __STACKFRAME_H__ +#define BYTES(idx) ((idx) * REGBYTES) +#define FRAME_OFF_SSTATUS BYTES(2) +#define FRAME_OFF_SP BYTES(32) + #include "cpuport.h" #include "encoding.h" @@ -54,7 +58,7 @@ /** * The register `tp` always save/restore when context switch, * we call `lwp_user_setting_save` when syscall enter, - * call `lwp_user_setting_restore` when syscall exit + * call `lwp_user_setting_restore` when syscall exit * and modify context stack after `lwp_user_setting_restore` called * so that the `tp` can be the correct thread area value. */ diff --git a/libcpu/risc-v/t-head/c906/trap.c b/libcpu/risc-v/t-head/c906/trap.c index aaf5be893f..2600ee0c37 100644 --- a/libcpu/risc-v/t-head/c906/trap.c +++ b/libcpu/risc-v/t-head/c906/trap.c @@ -277,6 +277,9 @@ static void handle_nested_trap_panic( rt_hw_cpu_shutdown(); } +#define IN_USER_SPACE (stval >= USER_VADDR_START && stval < USER_VADDR_TOP) +#define PAGE_FAULT (id == EP_LOAD_PAGE_FAULT || id == EP_STORE_PAGE_FAULT) + /* Trap entry */ void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw_stack_frame *sp) { @@ -314,7 +317,7 @@ void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw else { #ifdef RT_USING_SMART - if (!(sp->sstatus & 0x100)) + if (!(sp->sstatus & 0x100) || (PAGE_FAULT && IN_USER_SPACE)) { handle_user(scause, stval, sepc, sp); // if handle_user() return here, jump to u mode then diff --git a/libcpu/risc-v/virt64/stackframe.h b/libcpu/risc-v/virt64/stackframe.h index 5b546f01f9..550fa8947e 100644 --- a/libcpu/risc-v/virt64/stackframe.h +++ b/libcpu/risc-v/virt64/stackframe.h @@ -18,8 +18,9 @@ #include "encoding.h" #include "ext_context.h" -#define BYTES(idx) ((idx) * REGBYTES) -#define FRAME_OFF_SSTATUS BYTES(2) +#define BYTES(idx) ((idx) * REGBYTES) +#define FRAME_OFF_SSTATUS BYTES(2) +#define FRAME_OFF_SP BYTES(32) #ifdef __ASSEMBLY__ @@ -140,7 +141,7 @@ /** * @brief Restore All General Registers, for interrupt handling - * + * */ .macro RESTORE_ALL diff --git a/libcpu/risc-v/virt64/trap.c b/libcpu/risc-v/virt64/trap.c index 7b3bafae88..b9f30ed715 100644 --- a/libcpu/risc-v/virt64/trap.c +++ b/libcpu/risc-v/virt64/trap.c @@ -274,6 +274,9 @@ static void handle_nested_trap_panic( rt_hw_cpu_shutdown(); } +#define IN_USER_SPACE (stval >= USER_VADDR_START && stval < USER_VADDR_TOP) +#define PAGE_FAULT (id == EP_LOAD_PAGE_FAULT || id == EP_STORE_PAGE_FAULT) + /* Trap entry */ void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw_stack_frame *sp) { @@ -326,7 +329,7 @@ void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw } #endif /* ENABLE_VECTOR */ #ifdef RT_USING_SMART - if (!(sp->sstatus & 0x100)) + if (!(sp->sstatus & 0x100) || (PAGE_FAULT && IN_USER_SPACE)) { handle_user(scause, stval, sepc, sp); // if handle_user() return here, jump to u mode then