From 4fbfe7bf0cf293730f8681b263a41947fbc3c21e Mon Sep 17 00:00:00 2001 From: "Tate, Hongliang Tian" Date: Sat, 22 Sep 2018 22:54:53 +0800 Subject: [PATCH] Add syscall getpid and wait4 (this latter one is fake) --- src/libos/src/errno.rs | 2 +- src/libos/src/lib.rs | 8 +- src/libos/src/process.rs | 181 ++++++++++++++++++++++++++------ src/libos/src/syscall.h | 2 + src/libos/src/syscall.rs | 29 ++++- src/libos/src/syscall_entry.c | 9 +- src/libos/src/task.c | 4 +- src/libos/src/task.h | 6 +- test/Makefile | 2 +- test/getpid/Makefile | 4 + test/getpid/main.c | 8 ++ test/include/rusgx_stub.h | 7 ++ test/spawn_and_wait4_raw/main.c | 4 +- 13 files changed, 210 insertions(+), 56 deletions(-) create mode 100644 test/getpid/Makefile create mode 100644 test/getpid/main.c diff --git a/src/libos/src/errno.rs b/src/libos/src/errno.rs index 592ec979..aeb0b5f8 100644 --- a/src/libos/src/errno.rs +++ b/src/libos/src/errno.rs @@ -1,7 +1,7 @@ use std; use std::fmt; -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq)] enum Errno { OK = 0, EPERM = 1, diff --git a/src/libos/src/lib.rs b/src/libos/src/lib.rs index c6a4549a..6e580fff 100644 --- a/src/libos/src/lib.rs +++ b/src/libos/src/lib.rs @@ -31,9 +31,6 @@ mod elf_helper; mod mm; mod errno; -use process::spawn_process; -use process::run_task; - /// Export system calls pub use syscall::*; @@ -47,7 +44,8 @@ pub extern "C" fn libos_boot(path_buf: *const i8) -> i32 { let _ = backtrace::enable_backtrace("librusgx.signed.so", PrintFormat::Short); panic::catch_unwind(||{ backtrace::__rust_begin_short_backtrace(||{ - let _ = spawn_process(&path_str); + let mut pid = 0; + let _ = process::do_spawn(&mut pid, &path_str); }) }).ok(); @@ -59,7 +57,7 @@ pub extern "C" fn libos_run() -> i32 { let _ = backtrace::enable_backtrace("librusgx.signed.so", PrintFormat::Short); panic::catch_unwind(||{ backtrace::__rust_begin_short_backtrace(||{ - let _ = run_task(); + let _ = process::run_task(); }) }).ok(); diff --git a/src/libos/src/process.rs b/src/libos/src/process.rs index 80435f74..1936709c 100644 --- a/src/libos/src/process.rs +++ b/src/libos/src/process.rs @@ -4,6 +4,7 @@ use std::path::Path; use std::sgxfs::SgxFile; use std::io; use std::io::{Read}; +use std::mem; use sgx_types::*; @@ -13,20 +14,44 @@ use xmas_elf::symbol_table::Entry; use {elf_helper, vma, syscall}; use vma::Vma; -use std::sync::atomic::AtomicU32; -use std::sync::SgxMutex; +use std::sync::atomic::{AtomicU32, Ordering}; +use std::sync::{SgxMutex, SgxMutexGuard}; use std::sync::Arc; use std::collections::{HashMap, VecDeque}; - -//static next_pid : AtomicU32 = AtomicU32::new(42); +use std::thread; +use std::cell::Cell; lazy_static! { - static ref process_table: SgxMutex>>> = { + static ref PROCESS_TABLE: SgxMutex> = { SgxMutex::new(HashMap::new()) }; } -pub fn spawn_process>(elf_path: &P) -> Result<(), &'static str> { +fn put_into_pid_table(pid: u32, process: ProcessRef) { + PROCESS_TABLE.lock().unwrap().insert(pid, process); +} + +fn del_from_pid_table(pid: u32) { + PROCESS_TABLE.lock().unwrap().remove(&pid); +} + +fn look_up_pid_table(pid: u32) -> Option { + PROCESS_TABLE.lock().unwrap().get(&pid).map(|pr| pr.clone()) +} + + +static NEXT_PID : AtomicU32 = AtomicU32::new(1); + +fn alloc_pid() -> u32 { + NEXT_PID.fetch_add(1, Ordering::SeqCst) +} + +fn free_pid(pid: u32) { + // TODO: +} + + +pub fn do_spawn>(new_pid: &mut u32, elf_path: &P) -> Result<(), &'static str> { let elf_buf = open_elf(elf_path).unwrap(); let elf_file = ElfFile::new(&elf_buf).unwrap(); header::sanity_check(&elf_file).unwrap(); @@ -36,13 +61,12 @@ pub fn spawn_process>(elf_path: &P) -> Result<(), &'static str> { elf_helper::print_pltrel_section(&elf_file)?; */ let new_process = Process::new(&elf_file)?; + *new_pid = new_process.pid; + let new_process = Arc::new(SgxMutex::new(new_process)); //println!("new_process: {:#x?}", &new_process); - let new_task = Task::from(&new_process); - process_table.lock().unwrap() - .insert(0, Arc::new(SgxMutex::new(new_process))); - new_task_queue.lock().unwrap() - .push_back(new_task); + enqueue_new_process(new_process.clone()); + put_into_pid_table(*new_pid, new_process); let mut ret = 0; let ocall_status = unsafe { ocall_run_new_task(&mut ret) }; @@ -53,14 +77,72 @@ pub fn spawn_process>(elf_path: &P) -> Result<(), &'static str> { Ok(()) } +thread_local! { + static _CURRENT_PROCESS_PTR: Cell<*const SgxMutex> = + Cell::new(0 as *const SgxMutex); +} + +pub fn set_current(process: &ProcessRef) { + let process_ref_clone = process.clone(); + let process_ptr = Arc::into_raw(process_ref_clone); + + _CURRENT_PROCESS_PTR.with(|cp| { + cp.set(process_ptr); + }); +} + +pub fn get_current() -> &'static SgxMutex { + let mut process_ptr : *const SgxMutex = 0 as *const SgxMutex; + _CURRENT_PROCESS_PTR.with(|cp| { + process_ptr = cp.get(); + }); + unsafe { + mem::transmute::<*const SgxMutex, &'static SgxMutex>(process_ptr) + } +} + +pub fn do_getpid() -> u32 { + let current_ref = get_current(); + let current_process = current_ref.lock().unwrap(); + current_process.pid +} + +pub fn do_exit(exit_code: i32) { + { + let current_ref = get_current(); + let mut current_process = current_ref.lock().unwrap(); + current_process.exit_code = exit_code; + current_process.status = Status::ZOMBIE; + } +} + +pub fn do_wait4(child_pid: u32, exit_code: &mut i32) -> Result<(), &'static str> { + let child_process = look_up_pid_table(child_pid).ok_or("Not found")?; + loop { + let guard = child_process.lock().unwrap(); + if guard.status == Status::ZOMBIE { + *exit_code = guard.exit_code; + break; + } + drop(guard); + } + Ok(()) +} pub fn run_task() -> Result<(), &'static str> { - if let Some(new_task) = pop_new_task() { - println!("Run task: {:#x?}", &new_task); - println!("do_run_task() begin: {}", do_run_task as *const () as usize); - unsafe { do_run_task(&new_task as *const Task); } - println!("do_run_task() end"); - } + let new_process : ProcessRef = dequeue_new_process().ok_or("No new process to run")?; + set_current(&new_process); + + let new_task; + { + let guard = new_process.lock().unwrap(); + let process : &Process = &guard; + println!("Run process: {:#x?}", process); + new_task = &process.task as *const Task + }; + + unsafe { do_run_task(new_task as *const Task); } + Ok(()) } @@ -77,12 +159,17 @@ fn open_elf>(path: &P) -> io::Result> { #[derive(Clone, Debug, Default)] #[repr(C)] pub struct Process { + pub task: Task, + pub status: Status, + pub pid: u32, + pub exit_code: i32, pub code_vma: Vma, pub data_vma: Vma, pub stack_vma: Vma, pub program_base_addr: usize, pub program_entry_addr: usize, } +pub type ProcessRef = Arc>; impl Process { pub fn new(elf_file: &ElfFile) -> Result { @@ -90,6 +177,16 @@ impl Process { new_process.create_process_image(elf_file)?; new_process.link_syscalls(elf_file)?; new_process.mprotect()?; + + new_process.task = Task { + user_stack_addr: new_process.stack_vma.mem_end - 16, + user_entry_addr: new_process.program_entry_addr, + fs_base_addr: 0, + .. Default::default() + }; + + new_process.pid = alloc_pid(); + Ok(new_process) } @@ -152,12 +249,17 @@ impl Process { } } +impl Drop for Process { + fn drop(&mut self) { + del_from_pid_table(self.pid); + free_pid(self.pid); + } +} +/// Note: this definition must be in sync with task.h #[derive(Clone, Debug, Default)] #[repr(C)] pub struct Task { - pub pid: u32, - pub exit_code: u32, pub syscall_stack_addr: usize, pub user_stack_addr: usize, pub user_entry_addr: usize, @@ -165,31 +267,40 @@ pub struct Task { pub saved_state: usize, // struct jmpbuf* } -impl<'a> From<&'a Process> for Task { - fn from(process: &'a Process) -> Task { - Task { - pid: 1234, - user_stack_addr: process.stack_vma.mem_end - 16, - user_entry_addr: process.program_entry_addr, - fs_base_addr: 0, - .. Default::default() - } - } -} - lazy_static! { - static ref new_task_queue: Arc>> = { - Arc::new(SgxMutex::new(VecDeque::new())) + static ref new_process_queue: SgxMutex> = { + SgxMutex::new(VecDeque::new()) }; } -fn pop_new_task() -> Option { - new_task_queue.lock().unwrap().pop_front() + +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum Status { + RUNNING, + INTERRUPTIBLE, + ZOMBIE, + STOPPED, +} + +impl Default for Status { + fn default() -> Status { + Status::RUNNING + } +} + + +fn dequeue_new_process() -> Option { + new_process_queue.lock().unwrap().pop_front() +} + +fn enqueue_new_process(new_process: ProcessRef) { + new_process_queue.lock().unwrap().push_back(new_process) } extern { fn ocall_run_new_task(ret: *mut i32) -> sgx_status_t; fn do_run_task(task: *const Task) -> i32; + fn do_exit_task(); fn rusgx_syscall(num: i32, arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64) -> i64; } diff --git a/src/libos/src/syscall.h b/src/libos/src/syscall.h index 42a94b95..afb4fdb7 100644 --- a/src/libos/src/syscall.h +++ b/src/libos/src/syscall.h @@ -13,6 +13,8 @@ extern int rusgx_spawn(int* child_pid, const char* path, const char** argv, const char** envp); extern int rusgx_wait4(int child_pid, int* status, int options/*, struct rusage* rusage*/); +extern unsigned int rusgx_getpid(void); +extern void rusgx_exit(int status); #ifdef __cplusplus } diff --git a/src/libos/src/syscall.rs b/src/libos/src/syscall.rs index deb0d15a..92e85f23 100644 --- a/src/libos/src/syscall.rs +++ b/src/libos/src/syscall.rs @@ -25,7 +25,7 @@ pub unsafe extern "C" fn sys_read(fd: c_int, buf: * mut c_void, size: size_t) -> */ #[no_mangle] -pub extern fn rusgx_write(fd: c_int, buf: * const c_void, size: size_t) -> ssize_t { +pub extern "C" fn rusgx_write(fd: c_int, buf: * const c_void, size: size_t) -> ssize_t { let str_from_c = unsafe { CStr::from_ptr(buf as * const i8).to_string_lossy().into_owned() }; @@ -34,22 +34,43 @@ pub extern fn rusgx_write(fd: c_int, buf: * const c_void, size: size_t) -> ssize } #[no_mangle] -pub extern "C" fn rusgx_spawn(child_pid: *mut c_int, path: *const c_char, +pub extern "C" fn rusgx_getpid() -> c_uint +{ + process::do_getpid() +} + +#[no_mangle] +pub extern "C" fn rusgx_exit(status: i32) +{ + process::do_exit(status); +} + +#[no_mangle] +pub extern "C" fn rusgx_spawn(_child_pid: *mut c_int, path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int { let mut ret = 0; + let mut child_pid = 0; let path_str = unsafe { CStr::from_ptr(path as * const i8).to_string_lossy().into_owned() }; - if process::spawn_process(&path_str) != Ok(()) { + if process::do_spawn(&mut child_pid, &path_str) != Ok(()) { ret = -1; } + unsafe { + *_child_pid = child_pid as c_int; + } ret } #[no_mangle] -pub extern "C" fn rusgx_wait4(child_pid: c_int, status: *mut c_int, +pub extern "C" fn rusgx_wait4(child_pid: c_int, _exit_code: *mut c_int, options: c_int/*, rusage: *mut Rusage*/) -> c_int { + let mut exit_code = 0; + process::do_wait4(child_pid as u32, &mut exit_code); + unsafe { + *_exit_code = exit_code; + } 0 } diff --git a/src/libos/src/syscall_entry.c b/src/libos/src/syscall_entry.c index cd24b3b6..7842e38d 100644 --- a/src/libos/src/syscall_entry.c +++ b/src/libos/src/syscall_entry.c @@ -9,8 +9,9 @@ long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long switch (num) { case SYS_exit: { - DECL_SYSCALL_ARG(int, exit_code, arg0); - do_exit_task(exit_code); + DECL_SYSCALL_ARG(int, status, arg0); + rusgx_exit(status); + do_exit_task(); break; } case SYS_write: { @@ -36,6 +37,10 @@ long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long ret = rusgx_wait4(child_pid, status, options/*, rusage*/); break; } + case SYS_getpid: { + ret = rusgx_getpid(); + break; + } default: ret = -1; break; diff --git a/src/libos/src/task.c b/src/libos/src/task.c index f94e5ae2..ccf751cc 100644 --- a/src/libos/src/task.c +++ b/src/libos/src/task.c @@ -35,10 +35,10 @@ int do_run_task(struct Task* task) { // From rusgx_exit RESET_CURRENT_TASK(); - return task->exit_code; + return 0; } -void do_exit_task(int exitcode) { +void do_exit_task(void) { jmp_buf* jb = __get_current_task()->saved_state; longjmp(*jb, 1); } diff --git a/src/libos/src/task.h b/src/libos/src/task.h index cc99a594..c7693b26 100644 --- a/src/libos/src/task.h +++ b/src/libos/src/task.h @@ -13,8 +13,6 @@ extern "C" { // See Struct Task in process.rs struct Task { - uint32_t pid; - int32_t exit_code; uint64_t syscall_stack_addr; uint64_t user_stack_addr; uint64_t user_entry_addr; @@ -26,7 +24,7 @@ void __set_current_task(struct Task* task); struct Task* __get_current_task(void); int do_run_task(struct Task* task); -void do_exit_task(int exitcode); +void do_exit_task(void); #ifdef __cplusplus } @@ -39,7 +37,7 @@ void do_exit_task(int exitcode); /* Override the field for stack guard */ #define TD_TASK_OFFSET TD_STACKGUARD_OFFSET -#define TASK_SYSCALL_STACK_OFFSET (8 * 1) +#define TASK_SYSCALL_STACK_OFFSET (8 * 0) #endif /* __ASSEMBLY__ */ diff --git a/test/Makefile b/test/Makefile index 61dae3a2..2d1649ac 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,7 +1,7 @@ CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) PROJECT_DIR := $(realpath $(CUR_DIR)/../) -TEST_SUITES := hello_world_raw spawn_and_wait4_raw +TEST_SUITES := hello_world_raw spawn_and_wait4_raw getpid BUILD_TEST_SUITES := $(TEST_SUITES:%=%) RUN_TEST_SUITES := $(TEST_SUITES:%=run-%) CLEAN_TEST_SUITES := $(TEST_SUITES:%=clean-%) diff --git a/test/getpid/Makefile b/test/getpid/Makefile new file mode 100644 index 00000000..593ab76d --- /dev/null +++ b/test/getpid/Makefile @@ -0,0 +1,4 @@ +include ../test_common.mk + +EXTRA_C_FLAGS := -fno-builtin +EXTRA_LINK_FLAGS := -nostdlib diff --git a/test/getpid/main.c b/test/getpid/main.c new file mode 100644 index 00000000..270be522 --- /dev/null +++ b/test/getpid/main.c @@ -0,0 +1,8 @@ +#include "rusgx_stub.h" + +void _start(void) { + int pid = __rusgx_getpid(); + (void)pid; + + __rusgx_exit(0); +} diff --git a/test/include/rusgx_stub.h b/test/include/rusgx_stub.h index 20ccc84e..4237e170 100644 --- a/test/include/rusgx_stub.h +++ b/test/include/rusgx_stub.h @@ -21,12 +21,15 @@ */ #define SYS_write 1 +#define SYS_getpid 39 #define SYS_exit 60 #define SYS_wait4 61 #define SYS_spawn 360 long rusgx_syscall(int num, long arg0, long arg1, long arg2, long arg3, long arg4); +#define RUSGX_SYSCALL0(num) \ + rusgx_syscall((num), (long)0, (long)0, (long)0, (long)0, (long)0) #define RUSGX_SYSCALL1(num, arg0) \ rusgx_syscall((num), (long)(arg0), (long)0, (long)0, (long)0, (long)0) #define RUSGX_SYSCALL2(num, arg0, arg1) \ @@ -42,6 +45,10 @@ static inline ssize_t __rusgx_write(int fd, const void* buf, unsigned long size) return (ssize_t) RUSGX_SYSCALL3(SYS_write, fd, buf, size); } +static inline unsigned int __rusgx_getpid(void) { + return (unsigned int) RUSGX_SYSCALL0(SYS_getpid); +} + static inline void __rusgx_exit(int status) { RUSGX_SYSCALL1(SYS_exit, status); } diff --git a/test/spawn_and_wait4_raw/main.c b/test/spawn_and_wait4_raw/main.c index 35f9361f..e9417c8b 100644 --- a/test/spawn_and_wait4_raw/main.c +++ b/test/spawn_and_wait4_raw/main.c @@ -13,11 +13,11 @@ void _start(void) { ret = __rusgx_spawn(&pid, "hello_world_raw/bin.encrypted", NULL, NULL); if (ret < 0) { __rusgx_exit(0); } -/* + int status; ret = __rusgx_wait4(pid, &status, 0); if (ret < 0) { __rusgx_exit(0); } -*/ + print_ok(); __rusgx_exit(0);