Quellcode durchsuchen

[Linux PAL] Fix alternative stack alignment and leakage
[Linux PAL] Keep the thread hanging when exception handling failed

Chia-Che Tsai vor 5 Jahren
Ursprung
Commit
99e1a1abaf

+ 10 - 0
Pal/src/host/Linux/db_exception.c

@@ -187,6 +187,16 @@ static void _DkGenericSighandler (int signum, siginfo_t * info,
         printf("*** An unexpected %s occurred inside PAL. Exiting the thread. "
                "(PID = %d, TID = %d, RIP = +%p) ***\n",
                name, pid, tid, rip - (uintptr_t) TEXT_START);
+
+#ifdef DEBUG
+        // Hang for debugging
+        while (true) {
+            struct timespec sleeptime;
+            sleeptime.tv_sec = 36000;
+            sleeptime.tv_nsec = 0;
+            INLINE_SYSCALL(nanosleep, 2, &sleeptime, NULL);
+        }
+#endif
         _DkThreadExit();
         return;
     }

+ 1 - 0
Pal/src/host/Linux/db_main.c

@@ -234,6 +234,7 @@ void pal_linux_main (void * args)
         init_fail(PAL_ERROR_NOMEM, "Out of memory");
     SET_HANDLE_TYPE(first_thread, thread);
     first_thread->thread.tid = INLINE_SYSCALL(gettid, 0);
+    first_thread->thread.stack = NULL;
 
     void * alt_stack = NULL;
     _DkVirtualMemoryAlloc(&alt_stack, ALT_STACK_SIZE, 0, PAL_PROT_READ|PAL_PROT_WRITE);

+ 24 - 2
Pal/src/host/Linux/db_threading.c

@@ -62,7 +62,7 @@ int pal_thread_init (void * tcbptr)
 
     if (tcb->alt_stack) {
         // Align stack to 16 bytes
-        void * alt_stack_top = (void *) ((uint64_t) tcb & ~16);
+        void * alt_stack_top = (void *) ((uint64_t) tcb & ~15);
         assert(alt_stack_top > tcb->alt_stack);
         stack_t ss;
         ss.ss_sp    = alt_stack_top;
@@ -110,7 +110,7 @@ int _DkThreadCreate (PAL_HANDLE * handle, int (*callback) (void *),
     tcb->param     = (void *) param;
 
     /* align child_stack to 16 */
-    child_stack = (void *) ((uintptr_t) child_stack & ~16);
+    child_stack = (void *) ((uintptr_t) child_stack & ~15);
 
     ret = clone(pal_thread_init, child_stack,
                     CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SYSVSEM|
@@ -123,6 +123,7 @@ int _DkThreadCreate (PAL_HANDLE * handle, int (*callback) (void *),
         goto err;
     }
 
+    hdl->thread.stack = stack;
     *handle = hdl;
     return 0;
 err:
@@ -167,6 +168,27 @@ void _DkThreadYieldExecution (void)
 /* _DkThreadExit for internal use: Thread exiting */
 void _DkThreadExit (void)
 {
+    PAL_TCB* tcb = get_tcb();
+    PAL_HANDLE handle = tcb->handle;
+
+    if (tcb->alt_stack) {
+        stack_t ss;
+        ss.ss_sp    = NULL;
+        ss.ss_flags = SS_DISABLE;
+        ss.ss_size  = 0;
+
+        // Take precautions to unset the TCB and alternative stack first.
+        INLINE_SYSCALL(arch_prctl, 2, ARCH_SET_GS, 0);
+        INLINE_SYSCALL(sigaltstack, 2, &ss, NULL);
+        INLINE_SYSCALL(munmap, 2, tcb->alt_stack, ALT_STACK_SIZE);
+    }
+
+    if (handle && handle->thread.stack) {
+        // Free the thread stack
+        INLINE_SYSCALL(munmap, 2, handle->thread.stack, THREAD_STACK_SIZE);
+        // After this line, needs to exit the thread immediately
+    }
+
     INLINE_SYSCALL(exit, 1, 0);
 }
 

+ 1 - 0
Pal/src/host/Linux/pal_host.h

@@ -157,6 +157,7 @@ typedef struct pal_handle
 
         struct {
             PAL_IDX tid;
+            PAL_PTR stack;
         } thread;
 
         struct {