Add syscall getpid and wait4 (this latter one is fake)

This commit is contained in:
Tate, Hongliang Tian 2018-09-22 22:54:53 +08:00
parent 637e15f6c6
commit 4fbfe7bf0c
13 changed files with 210 additions and 56 deletions

@ -1,7 +1,7 @@
use std; use std;
use std::fmt; use std::fmt;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug, PartialEq)]
enum Errno { enum Errno {
OK = 0, OK = 0,
EPERM = 1, EPERM = 1,

@ -31,9 +31,6 @@ mod elf_helper;
mod mm; mod mm;
mod errno; mod errno;
use process::spawn_process;
use process::run_task;
/// Export system calls /// Export system calls
pub use syscall::*; 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); let _ = backtrace::enable_backtrace("librusgx.signed.so", PrintFormat::Short);
panic::catch_unwind(||{ panic::catch_unwind(||{
backtrace::__rust_begin_short_backtrace(||{ backtrace::__rust_begin_short_backtrace(||{
let _ = spawn_process(&path_str); let mut pid = 0;
let _ = process::do_spawn(&mut pid, &path_str);
}) })
}).ok(); }).ok();
@ -59,7 +57,7 @@ pub extern "C" fn libos_run() -> i32 {
let _ = backtrace::enable_backtrace("librusgx.signed.so", PrintFormat::Short); let _ = backtrace::enable_backtrace("librusgx.signed.so", PrintFormat::Short);
panic::catch_unwind(||{ panic::catch_unwind(||{
backtrace::__rust_begin_short_backtrace(||{ backtrace::__rust_begin_short_backtrace(||{
let _ = run_task(); let _ = process::run_task();
}) })
}).ok(); }).ok();

@ -4,6 +4,7 @@ use std::path::Path;
use std::sgxfs::SgxFile; use std::sgxfs::SgxFile;
use std::io; use std::io;
use std::io::{Read}; use std::io::{Read};
use std::mem;
use sgx_types::*; use sgx_types::*;
@ -13,20 +14,44 @@ use xmas_elf::symbol_table::Entry;
use {elf_helper, vma, syscall}; use {elf_helper, vma, syscall};
use vma::Vma; use vma::Vma;
use std::sync::atomic::AtomicU32; use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::SgxMutex; use std::sync::{SgxMutex, SgxMutexGuard};
use std::sync::Arc; use std::sync::Arc;
use std::collections::{HashMap, VecDeque}; use std::collections::{HashMap, VecDeque};
use std::thread;
//static next_pid : AtomicU32 = AtomicU32::new(42); use std::cell::Cell;
lazy_static! { lazy_static! {
static ref process_table: SgxMutex<HashMap<u32, Arc<SgxMutex<Process>>>> = { static ref PROCESS_TABLE: SgxMutex<HashMap<u32, ProcessRef>> = {
SgxMutex::new(HashMap::new()) SgxMutex::new(HashMap::new())
}; };
} }
pub fn spawn_process<P: AsRef<Path>>(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<ProcessRef> {
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<P: AsRef<Path>>(new_pid: &mut u32, elf_path: &P) -> Result<(), &'static str> {
let elf_buf = open_elf(elf_path).unwrap(); let elf_buf = open_elf(elf_path).unwrap();
let elf_file = ElfFile::new(&elf_buf).unwrap(); let elf_file = ElfFile::new(&elf_buf).unwrap();
header::sanity_check(&elf_file).unwrap(); header::sanity_check(&elf_file).unwrap();
@ -36,13 +61,12 @@ pub fn spawn_process<P: AsRef<Path>>(elf_path: &P) -> Result<(), &'static str> {
elf_helper::print_pltrel_section(&elf_file)?; elf_helper::print_pltrel_section(&elf_file)?;
*/ */
let new_process = Process::new(&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); //println!("new_process: {:#x?}", &new_process);
let new_task = Task::from(&new_process);
process_table.lock().unwrap() enqueue_new_process(new_process.clone());
.insert(0, Arc::new(SgxMutex::new(new_process))); put_into_pid_table(*new_pid, new_process);
new_task_queue.lock().unwrap()
.push_back(new_task);
let mut ret = 0; let mut ret = 0;
let ocall_status = unsafe { ocall_run_new_task(&mut ret) }; let ocall_status = unsafe { ocall_run_new_task(&mut ret) };
@ -53,14 +77,72 @@ pub fn spawn_process<P: AsRef<Path>>(elf_path: &P) -> Result<(), &'static str> {
Ok(()) Ok(())
} }
thread_local! {
static _CURRENT_PROCESS_PTR: Cell<*const SgxMutex<Process>> =
Cell::new(0 as *const SgxMutex<Process>);
}
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<Process> {
let mut process_ptr : *const SgxMutex<Process> = 0 as *const SgxMutex<Process>;
_CURRENT_PROCESS_PTR.with(|cp| {
process_ptr = cp.get();
});
unsafe {
mem::transmute::<*const SgxMutex<Process>, &'static SgxMutex<Process>>(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> { pub fn run_task() -> Result<(), &'static str> {
if let Some(new_task) = pop_new_task() { let new_process : ProcessRef = dequeue_new_process().ok_or("No new process to run")?;
println!("Run task: {:#x?}", &new_task); set_current(&new_process);
println!("do_run_task() begin: {}", do_run_task as *const () as usize);
unsafe { do_run_task(&new_task as *const Task); } let new_task;
println!("do_run_task() end"); {
} 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(()) Ok(())
} }
@ -77,12 +159,17 @@ fn open_elf<P: AsRef<Path>>(path: &P) -> io::Result<Vec<u8>> {
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
#[repr(C)] #[repr(C)]
pub struct Process { pub struct Process {
pub task: Task,
pub status: Status,
pub pid: u32,
pub exit_code: i32,
pub code_vma: Vma, pub code_vma: Vma,
pub data_vma: Vma, pub data_vma: Vma,
pub stack_vma: Vma, pub stack_vma: Vma,
pub program_base_addr: usize, pub program_base_addr: usize,
pub program_entry_addr: usize, pub program_entry_addr: usize,
} }
pub type ProcessRef = Arc<SgxMutex<Process>>;
impl Process { impl Process {
pub fn new(elf_file: &ElfFile) -> Result<Process, &'static str> { pub fn new(elf_file: &ElfFile) -> Result<Process, &'static str> {
@ -90,6 +177,16 @@ impl Process {
new_process.create_process_image(elf_file)?; new_process.create_process_image(elf_file)?;
new_process.link_syscalls(elf_file)?; new_process.link_syscalls(elf_file)?;
new_process.mprotect()?; 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) 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)] #[derive(Clone, Debug, Default)]
#[repr(C)] #[repr(C)]
pub struct Task { pub struct Task {
pub pid: u32,
pub exit_code: u32,
pub syscall_stack_addr: usize, pub syscall_stack_addr: usize,
pub user_stack_addr: usize, pub user_stack_addr: usize,
pub user_entry_addr: usize, pub user_entry_addr: usize,
@ -165,31 +267,40 @@ pub struct Task {
pub saved_state: usize, // struct jmpbuf* 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! { lazy_static! {
static ref new_task_queue: Arc<SgxMutex<VecDeque<Task>>> = { static ref new_process_queue: SgxMutex<VecDeque<ProcessRef>> = {
Arc::new(SgxMutex::new(VecDeque::new())) SgxMutex::new(VecDeque::new())
}; };
} }
fn pop_new_task() -> Option<Task> {
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<ProcessRef> {
new_process_queue.lock().unwrap().pop_front()
}
fn enqueue_new_process(new_process: ProcessRef) {
new_process_queue.lock().unwrap().push_back(new_process)
} }
extern { extern {
fn ocall_run_new_task(ret: *mut i32) -> sgx_status_t; fn ocall_run_new_task(ret: *mut i32) -> sgx_status_t;
fn do_run_task(task: *const Task) -> i32; 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; fn rusgx_syscall(num: i32, arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64) -> i64;
} }

@ -13,6 +13,8 @@ extern int rusgx_spawn(int* child_pid, const char* path,
const char** argv, const char** argv,
const char** envp); const char** envp);
extern int rusgx_wait4(int child_pid, int* status, int options/*, struct rusage* rusage*/); 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 #ifdef __cplusplus
} }

@ -25,7 +25,7 @@ pub unsafe extern "C" fn sys_read(fd: c_int, buf: * mut c_void, size: size_t) ->
*/ */
#[no_mangle] #[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 { let str_from_c = unsafe {
CStr::from_ptr(buf as * const i8).to_string_lossy().into_owned() 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] #[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 argv: *const *const c_char, envp: *const *const c_char) -> c_int
{ {
let mut ret = 0; let mut ret = 0;
let mut child_pid = 0;
let path_str = unsafe { let path_str = unsafe {
CStr::from_ptr(path as * const i8).to_string_lossy().into_owned() 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; ret = -1;
} }
unsafe {
*_child_pid = child_pid as c_int;
}
ret ret
} }
#[no_mangle] #[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 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 0
} }

@ -9,8 +9,9 @@ long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long
switch (num) { switch (num) {
case SYS_exit: { case SYS_exit: {
DECL_SYSCALL_ARG(int, exit_code, arg0); DECL_SYSCALL_ARG(int, status, arg0);
do_exit_task(exit_code); rusgx_exit(status);
do_exit_task();
break; break;
} }
case SYS_write: { 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*/); ret = rusgx_wait4(child_pid, status, options/*, rusage*/);
break; break;
} }
case SYS_getpid: {
ret = rusgx_getpid();
break;
}
default: default:
ret = -1; ret = -1;
break; break;

@ -35,10 +35,10 @@ int do_run_task(struct Task* task) {
// From rusgx_exit // From rusgx_exit
RESET_CURRENT_TASK(); 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; jmp_buf* jb = __get_current_task()->saved_state;
longjmp(*jb, 1); longjmp(*jb, 1);
} }

@ -13,8 +13,6 @@ extern "C" {
// See Struct Task in process.rs // See Struct Task in process.rs
struct Task { struct Task {
uint32_t pid;
int32_t exit_code;
uint64_t syscall_stack_addr; uint64_t syscall_stack_addr;
uint64_t user_stack_addr; uint64_t user_stack_addr;
uint64_t user_entry_addr; uint64_t user_entry_addr;
@ -26,7 +24,7 @@ void __set_current_task(struct Task* task);
struct Task* __get_current_task(void); struct Task* __get_current_task(void);
int do_run_task(struct Task* task); int do_run_task(struct Task* task);
void do_exit_task(int exitcode); void do_exit_task(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
@ -39,7 +37,7 @@ void do_exit_task(int exitcode);
/* 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 * 1) #define TASK_SYSCALL_STACK_OFFSET (8 * 0)
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */

@ -1,7 +1,7 @@
CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
PROJECT_DIR := $(realpath $(CUR_DIR)/../) 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:%=%) BUILD_TEST_SUITES := $(TEST_SUITES:%=%)
RUN_TEST_SUITES := $(TEST_SUITES:%=run-%) RUN_TEST_SUITES := $(TEST_SUITES:%=run-%)
CLEAN_TEST_SUITES := $(TEST_SUITES:%=clean-%) CLEAN_TEST_SUITES := $(TEST_SUITES:%=clean-%)

4
test/getpid/Makefile Normal file

@ -0,0 +1,4 @@
include ../test_common.mk
EXTRA_C_FLAGS := -fno-builtin
EXTRA_LINK_FLAGS := -nostdlib

8
test/getpid/main.c Normal file

@ -0,0 +1,8 @@
#include "rusgx_stub.h"
void _start(void) {
int pid = __rusgx_getpid();
(void)pid;
__rusgx_exit(0);
}

@ -21,12 +21,15 @@
*/ */
#define SYS_write 1 #define SYS_write 1
#define SYS_getpid 39
#define SYS_exit 60 #define SYS_exit 60
#define SYS_wait4 61 #define SYS_wait4 61
#define SYS_spawn 360 #define SYS_spawn 360
long rusgx_syscall(int num, long arg0, long arg1, long arg2, long arg3, long arg4); 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) \ #define RUSGX_SYSCALL1(num, arg0) \
rusgx_syscall((num), (long)(arg0), (long)0, (long)0, (long)0, (long)0) rusgx_syscall((num), (long)(arg0), (long)0, (long)0, (long)0, (long)0)
#define RUSGX_SYSCALL2(num, arg0, arg1) \ #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); 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) { static inline void __rusgx_exit(int status) {
RUSGX_SYSCALL1(SYS_exit, status); RUSGX_SYSCALL1(SYS_exit, status);
} }

@ -13,11 +13,11 @@ void _start(void) {
ret = __rusgx_spawn(&pid, "hello_world_raw/bin.encrypted", NULL, NULL); ret = __rusgx_spawn(&pid, "hello_world_raw/bin.encrypted", NULL, NULL);
if (ret < 0) { __rusgx_exit(0); } if (ret < 0) { __rusgx_exit(0); }
/*
int status; int status;
ret = __rusgx_wait4(pid, &status, 0); ret = __rusgx_wait4(pid, &status, 0);
if (ret < 0) { __rusgx_exit(0); } if (ret < 0) { __rusgx_exit(0); }
*/
print_ok(); print_ok();
__rusgx_exit(0); __rusgx_exit(0);