diff --git a/Pal/src/host/Linux-SGX/enclave_entry.S b/Pal/src/host/Linux-SGX/enclave_entry.S index 6cb922b2..acde721f 100644 --- a/Pal/src/host/Linux-SGX/enclave_entry.S +++ b/Pal/src/host/Linux-SGX/enclave_entry.S @@ -135,8 +135,40 @@ enclave_entry: retq #endif + ## There is a race between host signal delivery and restoring %rsp + ## in this entry code. We must be careful to setup %rsp. + ## + ## Race scenario + ## 1. We are inside the enclave but %rsp isn't restored yet to something + ## inside the enclave. That's for example the case when returning from + ## an ocall. + ## 2. The enclave gets interrupted. The not restored %rsp is pushed into + ## SGX_GPR_RSP by the processor. + ## 3. The host enters the enclave again and indicated that there's a new + ## signal. + ## 4. The code after .Lhandle_exception pushes stuff on the untrusted + ## stack (because SGX_GPR_RSP points there) and then diverts %rip to + ## execute the event handler after ERESUME (which will use the untrusted + ## stack). + ## + ## The solution is to have a "fallback" value stored in SGX_STACK. + ## If SGX_STACK == 0, then %rsp was correctly restored during + ## Lreturn_from_ocall and the interrupt happened after that, so the CPU + ## pushed the restored %rsp into SGX_GPR_RSP, thus we can safely use + ## SGX_GPR_RSP. + ## However, if SGX_STACK != 0, this indicates that the interrupt came + ## before xchgq %rsp, %gs:SGX_STACK and %rsp was not yet restored, + ## so the CPU pushed some untrusted %rsp into SGX_GPR_RSP. Thus, we + ## cannot trust value in SGX_GPR_RSP and should fall-back to using + ## SGX_STACK (which was updated with the last known good in-enclave + ## %rsp during Leexit). .Lhandle_exception: movq SGX_GPR_RSP(%rbx), %rsi + movq %gs:SGX_STACK, %rax + cmpq $0, %rax + je 1f + movq %rax, %rsi +1: subq $0x90, %rsi # we have exitinfo in RDI, swap with the one on GPR @@ -232,12 +264,9 @@ sgx_ocall: fxsave (%rsp) pushq %rbp - movq %rsp, %gs:SGX_STACK jmp .Leexit -.Lexception_handler: - .Leexit: xorq %rdx, %rdx xorq %r8, %r8 @@ -250,6 +279,7 @@ sgx_ocall: xorq %r15, %r15 xorq %rbp, %rbp + movq %rsp, %gs:SGX_STACK movq %gs:SGX_USTACK, %rsp andq $STACK_ALIGN, %rsp @@ -273,7 +303,8 @@ sgx_ocall: .Lno_fsbase: # restore the stack - movq %gs:SGX_STACK, %rsp + movq $0, %rsp + xchgq %rsp, %gs:SGX_STACK popq %rbp fxrstor (%rsp)