Browse Source

[Pal/Linux-SGX] Raise PAL_EVENT_ILLEGAL to LibOS when syscall instruction

This patch is preparation for LibOS to trap-and-emulate syscall
instruction.

This patch makes Pal/Linux-SGX raise PAL_EVENT_ILLEGAL to LibOS when
syscall or unknown instruction is found so that LibOS can handle it.
This patch also cleans up _DkExceptionHandler and add check if it's in
PAL or not. If it's in PAL, it panics.

Signed-off-by: Isaku Yamahata <isaku.yamahata@gmail.com>
Isaku Yamahata 5 years ago
parent
commit
e9435c68d8
1 changed files with 96 additions and 34 deletions
  1. 96 34
      Pal/src/host/Linux-SGX/db_exception.c

+ 96 - 34
Pal/src/host/Linux-SGX/db_exception.c

@@ -188,11 +188,50 @@ void restore_sgx_context (sgx_context_t * uc)
                   :: "r"(uc) : "memory");
 }
 
+/*
+ * return value:
+ *  true:  #UD is handled.
+ *         the execution can be continued without propagating #UD.
+ *  false: #UD is not handled.
+ *         the exception needs to be raised up to LibOS or user application.
+ */
+static bool handle_ud(sgx_context_t * uc)
+{
+    uint8_t * instr = (uint8_t *) uc->rip;
+    if (instr[0] == 0xcc) { /* skip int 3 */
+        uc->rip++;
+        return true;
+    } else if (instr[0] == 0x0f && instr[1] == 0xa2) {
+        /* cpuid */
+        unsigned int values[4];
+        if (!_DkCpuIdRetrieve(uc->rax & 0xffffffff,
+                              uc->rcx & 0xffffffff, values)) {
+            uc->rip += 2;
+            uc->rax = values[0];
+            uc->rbx = values[1];
+            uc->rcx = values[2];
+            uc->rdx = values[3];
+            return true;
+        }
+    } else if (instr[0] == 0x0f && instr[1] == 0x31) {
+        /* rdtsc */
+        uc->rip += 2;
+        uc->rdx = 0;
+        uc->rax = 0;
+        return true;
+    } else if (instr[0] == 0x0f && instr[1] == 0x05) {
+        /* syscall: LibOS may know how to handle this */
+        return false;
+    }
+    SGX_DBG(DBG_E, "Unknown or illegal instruction at RIP 0x%016lx\n", uc->rip);
+    return false;
+}
+
 void _DkExceptionHandler (unsigned int exit_info, sgx_context_t * uc)
 {
     union {
         sgx_arch_exitinfo_t info;
-        int intval;
+        unsigned int intval;
     } ei = { .intval = exit_info };
 
     int event_num;
@@ -200,53 +239,62 @@ void _DkExceptionHandler (unsigned int exit_info, sgx_context_t * uc)
 
     if (!ei.info.valid) {
         event_num = exit_info;
-        goto handle_event;
-    }
-
-    if (ei.info.vector == SGX_EXCEPTION_VECTOR_UD) {
-        unsigned char * instr = (unsigned char *) uc->rip;
-        if (instr[0] == 0xcc) { /* skip int 3 */
-            uc->rip++;
-            restore_sgx_context(uc);
-            return;
-        }
-        if (instr[0] == 0x0f && instr[1] == 0xa2) {
-            unsigned int values[4];
-            if (!_DkCpuIdRetrieve(uc->rax & 0xffffffff,
-                                  uc->rcx & 0xffffffff, values)) {
-                uc->rip += 2;
-                uc->rax = values[0];
-                uc->rbx = values[1];
-                uc->rcx = values[2];
-                uc->rdx = values[3];
+    } else {
+        switch (ei.info.vector) {
+        case SGX_EXCEPTION_VECTOR_BR:
+            event_num = PAL_EVENT_NUM_BOUND;
+            break;
+        case SGX_EXCEPTION_VECTOR_UD:
+            if (handle_ud(uc)) {
                 restore_sgx_context(uc);
                 return;
             }
-        }
-        if (instr[0] == 0x0f && instr[1] == 0x31) {
-            uc->rip += 2;
-            uc->rdx = 0;
-            uc->rax = 0;
-            restore_sgx_context(uc);
-            return;
-        }
-        SGX_DBG(DBG_E, "Illegal instruction executed in enclave\n");    
-        ocall_exit(1);
-    }
-
-    switch (ei.info.vector) {
+            event_num = PAL_EVENT_ILLEGAL;
+            break;
         case SGX_EXCEPTION_VECTOR_DE:
+        case SGX_EXCEPTION_VECTOR_MF:
+        case SGX_EXCEPTION_VECTOR_XM:
             event_num = PAL_EVENT_ARITHMETIC_ERROR;
             break;
         case SGX_EXCEPTION_VECTOR_AC:
             event_num = PAL_EVENT_MEMFAULT;
             break;
+        case SGX_EXCEPTION_VECTOR_DB:
+        case SGX_EXCEPTION_VECTOR_BP:
         default:
             restore_sgx_context(uc);
             return;
+        }
+    }
+
+    if (ADDR_IN_PAL(uc->rip) &&
+        /* event isn't asynchronous */
+        (event_num != PAL_EVENT_QUIT &&
+         event_num != PAL_EVENT_SUSPEND &&
+         event_num != PAL_EVENT_RESUME)) {
+        printf("*** An unexpected AEX vector occurred inside PAL. "
+               "Exiting the thread. *** \n"
+               "(vector = 0x%x, type = 0x%x valid = %d, RIP = +0x%08lx)\n"
+               "rax: 0x%08lx rcx: 0x%08lx rdx: 0x%08lx rbx: 0x%08lx\n"
+               "rsp: 0x%08lx rbp: 0x%08lx rsi: 0x%08lx rdi: 0x%08lx\n"
+               "r8 : 0x%08lx r9 : 0x%08lx r10: 0x%08lx r11: 0x%08lx\n"
+               "r12: 0x%08lx r13: 0x%08lx r14: 0x%08lx r15: 0x%08lx\n"
+               "rflags: 0x%08lx rip: 0x%08lx\n",
+               ei.info.vector, ei.info.type, ei.info.valid,
+               uc->rip - (uintptr_t) TEXT_START,
+               uc->rax, uc->rcx, uc->rdx, uc->rbx,
+               uc->rsp, uc->rbp, uc->rsi, uc->rdi,
+               uc->r8, uc->r9, uc->r10, uc->r11,
+               uc->r12, uc->r13, uc->r14, uc->r15,
+               uc->rflags, uc->rip);
+#ifdef DEBUG
+        printf("pausing for debug\n");
+        while (true)
+            __asm__ volatile("pause");
+#endif
+        _DkThreadExit();
     }
 
-handle_event:
     ctx = __alloca(sizeof(PAL_CONTEXT));
     memset(ctx, 0, sizeof(PAL_CONTEXT));
     ctx->rax = uc->rax;
@@ -271,6 +319,20 @@ handle_event:
     struct pal_frame * frame = get_frame(uc);
 
     PAL_NUM arg = 0;
+    switch (event_num) {
+    case PAL_EVENT_ILLEGAL:
+        arg = uc->rip;
+        break;
+    case PAL_EVENT_MEMFAULT:
+        /* TODO
+         * SGX1 doesn't provide fault address.
+         * SGX2 gives providing page. (lower address bits are masked)
+         */
+        break;
+    default:
+        /* nothing */
+        break;
+    }
     _DkExceptionRealHandler(event_num, arg, frame, ctx);
     restore_sgx_context(uc);
 }