summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShell <[email protected]>2023-02-24 14:52:16 +0800
committerGitHub <[email protected]>2023-02-24 14:52:16 +0800
commit382e9bcac746b408b5b01ea2f59338428ab203dd (patch)
tree448e8692183ad031b57afda6681aaa93caa56df9
parent08c2a651360899ca59e90433dfb78579a642fd75 (diff)
[rt-smart] handling kernel from accessing unmapped user stack (#6957)
[rt-smart] handling kernel from accessing unmapped user stack
-rw-r--r--components/lwp/arch/risc-v/rv64/lwp_gcc.S10
-rw-r--r--components/lwp/lwp_user_mm.c11
-rw-r--r--libcpu/risc-v/t-head/c906/stackframe.h6
-rw-r--r--libcpu/risc-v/t-head/c906/trap.c5
-rw-r--r--libcpu/risc-v/virt64/stackframe.h7
-rw-r--r--libcpu/risc-v/virt64/trap.c5
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