Switch user/kernel fsbase

This commit is contained in:
Tate, Hongliang Tian 2019-01-01 15:33:33 +08:00
parent 05e5efdb57
commit b717842113
9 changed files with 70 additions and 21 deletions

@ -2,7 +2,7 @@
<EnclaveConfiguration> <EnclaveConfiguration>
<ProdID>0</ProdID> <ProdID>0</ProdID>
<ISVSVN>0</ISVSVN> <ISVSVN>0</ISVSVN>
<StackMaxSize>0x80000</StackMaxSize> <StackMaxSize>0x100000</StackMaxSize>
<HeapMaxSize>0x1000000</HeapMaxSize> <HeapMaxSize>0x1000000</HeapMaxSize>
<TCSNum>8</TCSNum> <TCSNum>8</TCSNum>
<TCSPolicy>1</TCSPolicy> <TCSPolicy>1</TCSPolicy>

@ -13,10 +13,11 @@ extern "C" {
// See Struct Task in process.rs // See Struct Task in process.rs
struct Task { struct Task {
uint64_t syscall_stack_addr; uint64_t kernel_stack_addr;
uint64_t kernel_fsbase_addr;
uint64_t user_stack_addr; uint64_t user_stack_addr;
uint64_t user_fsbase_addr;
uint64_t user_entry_addr; uint64_t user_entry_addr;
uint64_t fs_base_addr;
jmp_buf* saved_state; jmp_buf* saved_state;
}; };
@ -37,7 +38,11 @@ void do_exit_task(void);
/* Override the field for stack guard */ /* Override the field for stack guard */
#define TD_TASK_OFFSET TD_STACKGUARD_OFFSET #define TD_TASK_OFFSET TD_STACKGUARD_OFFSET
#define TASK_SYSCALL_STACK_OFFSET (8 * 0) #define TASK_KERNEL_STACK_ADDR (8 * 0)
#define TASK_KERNEL_FSBASE_ADDR (8 * 1)
#define TASK_USER_STACK_ADDR (8 * 2)
#define TASK_USER_FSBASE_ADDR (8 * 3)
#define TASK_USER_ENTRY_ADDR (8 * 4)
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */

@ -85,7 +85,6 @@ fn init_task(user_entry: usize, stack_top: usize,
Ok(Task { Ok(Task {
user_stack_addr: user_stack, user_stack_addr: user_stack,
user_entry_addr: user_entry, user_entry_addr: user_entry,
fs_base_addr: 0,
.. Default::default() .. Default::default()
}) })
} }

@ -1,12 +1,12 @@
#include "task.h" #include "task.h"
extern void __run_task(uint64_t entry_point, uint64_t stack_top); extern void __run_task(struct Task* task);
extern uint64_t __get_stack_guard(void); extern uint64_t __get_stack_guard(void);
extern void __set_stack_guard(uint64_t new_val); extern void __set_stack_guard(uint64_t new_val);
static uint64_t get_syscall_stack(struct Task* this_task) { static uint64_t get_syscall_stack(struct Task* this_task) {
#define LARGE_ENOUGH_GAP 4096 #define LARGE_ENOUGH_GAP (8192)
char libos_stack_var = 0; char libos_stack_var = 0;
uint64_t libos_stack = ((uint64_t) &libos_stack_var) - LARGE_ENOUGH_GAP; uint64_t libos_stack = ((uint64_t) &libos_stack_var) - LARGE_ENOUGH_GAP;
libos_stack &= ~0x0FUL; // stack must be 16-byte aligned libos_stack &= ~0x0FUL; // stack must be 16-byte aligned
@ -20,17 +20,16 @@ static uint64_t get_syscall_stack(struct Task* this_task) {
#define RESET_CURRENT_TASK() \ #define RESET_CURRENT_TASK() \
__set_stack_guard(stack_guard); __set_stack_guard(stack_guard);
int do_run_task(struct Task* task) { int do_run_task(struct Task* task) {
jmp_buf libos_state = {0}; jmp_buf libos_state = {0};
task->saved_state = &libos_state; task->saved_state = &libos_state;
task->syscall_stack_addr = get_syscall_stack(task); task->kernel_stack_addr = get_syscall_stack(task);
SET_CURRENT_TASK(task); SET_CURRENT_TASK(task);
int second = setjmp(libos_state); int second = setjmp(libos_state);
if (!second) { if (!second) {
__run_task(task->user_entry_addr, task->user_stack_addr); __run_task(task);
} }
// From occlum_exit // From occlum_exit
@ -39,6 +38,7 @@ int do_run_task(struct Task* task) {
} }
void do_exit_task(void) { void do_exit_task(void) {
jmp_buf* jb = __get_current_task()->saved_state; struct Task* task = __get_current_task();
jmp_buf* jb = task->saved_state;
longjmp(*jb, 1); longjmp(*jb, 1);
} }

@ -5,10 +5,11 @@ use std::{mem};
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
#[repr(C)] #[repr(C)]
pub struct Task { pub struct Task {
pub syscall_stack_addr: usize, pub kernel_stack_addr: usize,
pub kernel_fsbase_addr: usize,
pub user_stack_addr: usize, pub user_stack_addr: usize,
pub user_fsbase_addr: usize,
pub user_entry_addr: usize, pub user_entry_addr: usize,
pub fs_base_addr: usize,
pub saved_state: usize, // struct jmpbuf* pub saved_state: usize, // struct jmpbuf*
} }

@ -30,5 +30,14 @@ __set_stack_guard:
.global __run_task .global __run_task
.type __run_task, @function .type __run_task, @function
__run_task: __run_task:
mov %rsi, %rsp // Save kernel fsbase
jmp *%rdi rdfsbase %r10
movq %r10, TASK_KERNEL_FSBASE_ADDR(%rdi)
// Use user fsbase
movq TASK_USER_FSBASE_ADDR(%rdi), %r10
wrfsbase %r10
// Use user stack
movq TASK_USER_STACK_ADDR(%rdi), %rsp
// Run user code
movq TASK_USER_ENTRY_ADDR(%rdi), %r11
jmp *%r11

@ -6,7 +6,6 @@
long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5) { long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5) {
long ret = 0; long ret = 0;
switch (num) { switch (num) {
case SYS_exit: { case SYS_exit: {
DECL_SYSCALL_ARG(int, status, arg0); DECL_SYSCALL_ARG(int, status, arg0);

@ -5,13 +5,50 @@
.global __occlum_syscall .global __occlum_syscall
.type __occlum_syscall, @function .type __occlum_syscall, @function
__occlum_syscall: __occlum_syscall:
push %rbp // num - %rdi
// arg0 - %rsi
// arg1 - %rdx
// arg2 - %rcx
// arg3 - %r8
// arg4 - %r9
// arg5 - *0x8(%rsp)
// Given by the user, the user-space stack pointer %rsp cannot be trusted.
// So we need to check whether %rsp is within the read-write region of the
// current data domain
bndcl %rsp, %bnd0
bndcu %rsp, %bnd0
// Save the user stack
pushq %rbp
movq %rsp, %rbp movq %rsp, %rbp
movq %gs:(TD_TASK_OFFSET), %rax // Get current task
movq TASK_SYSCALL_STACK_OFFSET(%rax), %rsp movq %gs:(TD_TASK_OFFSET), %r12
// Switch to the kernel stack
movq TASK_KERNEL_STACK_ADDR(%r12), %rsp
// Use kernel fsbase
movq TASK_KERNEL_FSBASE_ADDR(%r12), %r11
wrfsbase %r11
// TODO: Pass arg5
// pushq 0x10(%rbp)
call dispatch_syscall call dispatch_syscall
// addq 0x08, %rsp
// Use user fsbase
movq TASK_KERNEL_FSBASE_ADDR(%r12), %r11
wrfsbase %r11
// Restore the user stack
movq %rbp, %rsp movq %rbp, %rsp
popq %rbp popq %rbp
ret
// Check return target is a valid instruction (i.e., a cfi_label)
popq %r10
movq (%r10), %r11
bndcl %r11, %bnd2
bndcu %r11, %bnd2
jmpq *%r10

@ -8,7 +8,6 @@ lazy_static! {
unsafe { vm_get_prealloced_data_space(&mut addr, &mut size) }; unsafe { vm_get_prealloced_data_space(&mut addr, &mut size) };
(addr, size) (addr, size)
}; };
println!("addr = {:X?}, size = {}", addr, size);
let vm_space = unsafe { let vm_space = unsafe {
match VMSpace::new(addr, size, VMGuardAreaType::None) { match VMSpace::new(addr, size, VMGuardAreaType::None) {
Ok(vm_space) => vm_space, Ok(vm_space) => vm_space,