diff --git a/enclave/core/sgx/context.inc b/enclave/core/sgx/context.inc index f340389c7f..c7c7f16091 100644 --- a/enclave/core/sgx/context.inc +++ b/enclave/core/sgx/context.inc @@ -143,9 +143,27 @@ oe_continue_execution: // Restore rdi. movq OE_CONTEXT_RDI(%rdi), %rdi - // Recovery the correct rsp. - add $(ABI_REDZONE_BYTE_SIZE + 8), %rsp - - // Jump to the target. - jmp *-(ABI_REDZONE_BYTE_SIZE + 8)(%rsp) + // LVI mitigation strategy: + // Since no register is free, we cannot load the target into a register and + // then issue an lfence. Instead, we use retq (return) instruction to carry + // out a jump. The return address is at 0(RSP). RSP is ABI_REDZONE_BYTE_SIZE + // + 8 bytes below the correct RSP which was fetched from the context. + // We issue a + // retq $ABI_REDZONE_BYTE_SIZE + // This has the following effect: + // - The return address is popped and control is transferred to + // the target address. + // - Additionally, ABI_REDZONE_BYTE_SIZE is subtracted from RSP, + // thereby restoring RSP correctly. + // - Ideally assembler's LVI mitigation would insert lfence as appropriate. + // Since it does not seem to handle retq with an immediate value, the + // LVI mitigation is manually inserted. + + // Manual LVI mitigation since the assember does not handle the retq below. + notq (%rsp) + notq (%rsp) + lfence + + // Jump to the target and restore RSP. + retq $ABI_REDZONE_BYTE_SIZE .cfi_endproc diff --git a/enclave/core/sgx/longjmp.S b/enclave/core/sgx/longjmp.S index bdd35c2217..240e033ee7 100644 --- a/enclave/core/sgx/longjmp.S +++ b/enclave/core/sgx/longjmp.S @@ -32,5 +32,10 @@ val_is_nonzero: mov 40(%rdi),%r13 mov 48(%rdi),%r14 mov 56(%rdi),%r15 - jmp *16(%rdi) + + // Load indirect jump address into register and then perform the jump. + // This pattern allows the assembler to detect and add lfence as + // appropriate. + mov 16(%rdi),%rdi + jmp *%rdi .cfi_endproc