occlum/src/libos/src/process/task.c
Tate, Hongliang Tian c096e7d0b9 Inform Intel SGX SDK about Occlum-defined stacks
There are two types of stacks: the kernel ones and the user ones. The kernel
stacks are used by Occlum and managed by Intel SGX SDK itself, while the user
stacks are used by the threads created and managed by Occlum. These user stacks
are transparent to Intel SGX SDK so far.

The problem is that Intel SGX SDK needs to be aware of the user stacks.
SGX exception handlers will check whether the rsp value---when the exception
happened---is within the stack of the current SGX thread. If the check fails,
the registered exception handler will not be triggered. But when exceptions are
triggered by the threads running upon Occlum, the rsp value points to the user
stacks, which Intel SGX SDK are completely unware of. So the check always
fails.

Therefore, we extend Intel SGX SDK with two new APIs:

  int sgx_enable_user_stack(size_t stack_base, size_t stack_limit);
  void sgx_disable_user_stack(void);

And this commit uses the two APIs to inform Intel SGX SDK about the
Occlum-managed stacks. And the rsp checks in SGX exception handlers will
check whether rsp is within the user stacks.
2019-07-18 07:16:17 +00:00

53 lines
1.4 KiB
C

#include "task.h"
extern void __run_task(struct Task* task);
extern uint64_t __get_stack_guard(void);
extern void __set_stack_guard(uint64_t new_val);
// From SGX SDK
int sgx_enable_user_stack(size_t stack_base, size_t stack_limit);
void sgx_disable_user_stack(void);
static uint64_t get_syscall_stack(struct Task* this_task) {
#define LARGE_ENOUGH_GAP (8192)
char libos_stack_var = 0;
uint64_t libos_stack = ((uint64_t) &libos_stack_var) - LARGE_ENOUGH_GAP;
libos_stack &= ~0x0FUL; // stack must be 16-byte aligned
return libos_stack;
}
#define SET_CURRENT_TASK(task) \
long stack_guard = __get_stack_guard(); \
__set_current_task(task);
#define RESET_CURRENT_TASK() \
__set_stack_guard(stack_guard);
int do_run_task(struct Task* task) {
jmp_buf libos_state = {0};
task->saved_state = &libos_state;
task->kernel_rsp = get_syscall_stack(task);
if (sgx_enable_user_stack(task->user_stack_base, task->user_stack_limit)) {
return -1;
}
SET_CURRENT_TASK(task);
int second = setjmp(libos_state);
if (!second) {
__run_task(task);
}
// Jump from do_exit_task
RESET_CURRENT_TASK();
sgx_disable_user_stack();
return 0;
}
void do_exit_task(void) {
struct Task* task = __get_current_task();
jmp_buf* jb = task->saved_state;
longjmp(*jb, 1);
}