Jelajahi Sumber

[rt-smart] handling kernel from accessing unmapped user stack (#6957)

[rt-smart] handling kernel from accessing unmapped user stack
Shell 2 tahun lalu
induk
melakukan
382e9bcac7

+ 10 - 0
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

+ 7 - 4
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;
         }

+ 5 - 1
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.
  */

+ 4 - 1
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

+ 4 - 3
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
 

+ 4 - 1
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