Init program stack to pass argc, argv, etc.
This commit is contained in:
parent
f0e7bae0d7
commit
cf77c3a9a8
8
TODO.md
8
TODO.md
@ -1,7 +1,3 @@
|
|||||||
# TODOs
|
# TODOs
|
||||||
- [ ] Add README.md
|
- [ ] Remove src/libc
|
||||||
- [ ] Add file table
|
- [ ] Check all dangerous arithmetic overflows and underflows
|
||||||
- [ ] Add more syscalls
|
|
||||||
- [ ] Pass argc and argv
|
|
||||||
|
|
||||||
- [ ] Add libc
|
|
||||||
|
2
src/libos/Cargo.lock
generated
2
src/libos/Cargo.lock
generated
@ -1,5 +1,5 @@
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "Rusgx"
|
name = "Occlum"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "Rusgx"
|
name = "Occlum"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
345
src/libos/src/init_stack.rs
Normal file
345
src/libos/src/init_stack.rs
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
use prelude::*;
|
||||||
|
use {std, std::mem, std::ptr};
|
||||||
|
use std::ffi::{CStr, CString};
|
||||||
|
use std::os::raw::c_char;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The initial stack of a process looks like below:
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* +---------------------+ <------+ Top of stack
|
||||||
|
* | | (high address)
|
||||||
|
* | Null-terminated |
|
||||||
|
* | strings referenced |
|
||||||
|
* | by variables below |
|
||||||
|
* | |
|
||||||
|
* +---------------------+
|
||||||
|
* | AT_NULL |
|
||||||
|
* +---------------------+
|
||||||
|
* | AT_NULL |
|
||||||
|
* +---------------------+
|
||||||
|
* | ... |
|
||||||
|
* +---------------------+
|
||||||
|
* | aux_val[0] |
|
||||||
|
* +---------------------+
|
||||||
|
* | aux_key[0] | <------+ Auxiliary table
|
||||||
|
* +---------------------+
|
||||||
|
* | NULL |
|
||||||
|
* +---------------------+
|
||||||
|
* | ... |
|
||||||
|
* +---------------------+
|
||||||
|
* | char* envp[0] | <------+ Environment variabls
|
||||||
|
* +---------------------+
|
||||||
|
* | NULL |
|
||||||
|
* +---------------------+
|
||||||
|
* | char* argv[argc-1] |
|
||||||
|
* +---------------------+
|
||||||
|
* | ... |
|
||||||
|
* +---------------------+
|
||||||
|
* | char* argv[0] |
|
||||||
|
* +---------------------+
|
||||||
|
* | long argc | <------+ Program arguments
|
||||||
|
* +---------------------+
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* + +
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub fn do_init_process_stack<'a, 'b>(stack: &'a StackBuf,
|
||||||
|
argv: &'b [CString], envp: &'b [CString], auxtbl: &'b AuxTable)
|
||||||
|
-> Result<(), Error>
|
||||||
|
{
|
||||||
|
let envp_cloned = clone_cstrings_on_stack(stack, envp)?;
|
||||||
|
let argv_cloned = clone_cstrings_on_stack(stack, argv)?;
|
||||||
|
dump_auxtbl_on_stack(stack, auxtbl)?;
|
||||||
|
dump_cstrptrs_on_stack(stack, &envp_cloned);
|
||||||
|
dump_cstrptrs_on_stack(stack, &argv_cloned);
|
||||||
|
stack.put(argv.len() as u64);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// StackBuf is a buffer that is filled in from high addresses to low
|
||||||
|
/// (just as a stack). The range of available memory of a StackBuf is from
|
||||||
|
/// [self.bottom, self.top).
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StackBuf {
|
||||||
|
stack_top: *const u8,
|
||||||
|
stack_bottom: *const u8,
|
||||||
|
stack_pos: Cell<*const u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for StackBuf {
|
||||||
|
fn default() -> StackBuf {
|
||||||
|
StackBuf {
|
||||||
|
stack_top: 0 as *const u8,
|
||||||
|
stack_bottom: 0 as *const u8,
|
||||||
|
stack_pos: Cell::new(0 as *const u8),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StackBuf {
|
||||||
|
pub fn new(stack_top: *const u8, stack_bottom: *const u8) -> Result<StackBuf, Error>{
|
||||||
|
if stack_top as usize <= stack_bottom as usize{
|
||||||
|
return Err(Error::new(Errno::EINVAL, "Invalid stack range"));
|
||||||
|
};
|
||||||
|
Ok(StackBuf {
|
||||||
|
stack_top: stack_top,
|
||||||
|
stack_bottom: stack_bottom,
|
||||||
|
stack_pos: Cell::new(stack_top),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn put<T>(&self, val: T) -> Result<*const T, Error>
|
||||||
|
where T : Copy
|
||||||
|
{
|
||||||
|
let val_size = mem::size_of::<T>();
|
||||||
|
let val_align = mem::align_of::<T>();
|
||||||
|
let val_ptr = self.alloc(val_size, val_align)? as *mut T;
|
||||||
|
unsafe { ptr::write(val_ptr, val); }
|
||||||
|
Ok(val_ptr as *const T)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn put_slice<T>(&self, vals: &[T]) -> Result<*const T, Error>
|
||||||
|
where T: Copy
|
||||||
|
{
|
||||||
|
let val_size = mem::size_of::<T>();
|
||||||
|
let val_align = mem::align_of::<T>();
|
||||||
|
let total_size = val_size * vals.len();
|
||||||
|
let base_ptr = self.alloc(total_size, val_align)? as *mut T;
|
||||||
|
|
||||||
|
let mut val_ptr = base_ptr;
|
||||||
|
for v in vals {
|
||||||
|
unsafe { ptr::write(val_ptr, *v); }
|
||||||
|
val_ptr = unsafe { val_ptr.offset(1) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(base_ptr as *const T)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn put_cstr(&self, cstr: &CStr) -> Result<*const u8, Error> {
|
||||||
|
let bytes = cstr.to_bytes_with_nul();
|
||||||
|
self.put_slice(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_pos(&self) -> *const u8 {
|
||||||
|
self.stack_pos.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn alloc(&self, size: usize, align_power2: usize) -> Result<*mut u8, Error> {
|
||||||
|
if size == 0 || !align_power2.is_power_of_two() {
|
||||||
|
return Err(Error::new(Errno::EINVAL, "Invalid size or align"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let old_pos = {
|
||||||
|
let old_pos = self.stack_pos.get() as usize;
|
||||||
|
let remain_size = old_pos - self.stack_bottom as usize;
|
||||||
|
if size > remain_size {
|
||||||
|
return Err(Error::new(Errno::ENOMEM, "No enough space in buffer"));
|
||||||
|
}
|
||||||
|
old_pos
|
||||||
|
};
|
||||||
|
|
||||||
|
let new_pos = {
|
||||||
|
let mask = (-(align_power2 as isize)) as usize;
|
||||||
|
let new_pos = (old_pos - size) & mask;
|
||||||
|
if new_pos < self.stack_bottom as usize {
|
||||||
|
return Err(Error::new(Errno::ENOMEM, "No enough space in buffer"));
|
||||||
|
}
|
||||||
|
new_pos as *const u8
|
||||||
|
};
|
||||||
|
self.stack_pos.set(new_pos);
|
||||||
|
|
||||||
|
Ok(new_pos as *mut u8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn clone_cstrings_on_stack<'a, 'b>(stack: &'a StackBuf,
|
||||||
|
cstrings: &'b [CString])
|
||||||
|
-> Result<Vec<&'a CStr>, Error>
|
||||||
|
{
|
||||||
|
let mut cstrs_cloned = Vec::new();
|
||||||
|
for cs in cstrings.iter().rev() {
|
||||||
|
let cstrp_cloned = stack.put_cstr(cs)?;
|
||||||
|
let cstr_cloned = unsafe {
|
||||||
|
CStr::from_ptr::<'a>(cstrp_cloned as *const c_char)
|
||||||
|
};
|
||||||
|
cstrs_cloned.push(cstr_cloned);
|
||||||
|
}
|
||||||
|
cstrs_cloned.reverse();
|
||||||
|
Ok(cstrs_cloned)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dump_auxtbl_on_stack<'a, 'b>(stack: &'a StackBuf, auxtbl: &'b AuxTable)
|
||||||
|
-> Result<(), Error>
|
||||||
|
{
|
||||||
|
// For every key-value pari, dump the value first, then the key
|
||||||
|
stack.put(AuxKey::AT_NULL as u64);
|
||||||
|
stack.put(AuxKey::AT_NULL as u64);
|
||||||
|
for (aux_key, aux_val) in auxtbl {
|
||||||
|
stack.put(aux_val);
|
||||||
|
stack.put(aux_key as u64);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dump_cstrptrs_on_stack<'a, 'b>(stack: &'a StackBuf, strptrs: &'b [&'a CStr])
|
||||||
|
-> Result<(), Error>
|
||||||
|
{
|
||||||
|
stack.put(0 as u64); // End with a NULL pointer
|
||||||
|
for sp in strptrs.iter().rev() {
|
||||||
|
stack.put(sp.as_ptr() as u64);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Symbolic values for the entries in the auxiliary table
|
||||||
|
put on the initial stack */
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub enum AuxKey {
|
||||||
|
AT_NULL = 0, /* end of vector */
|
||||||
|
AT_IGNORE = 1, /* entry should be ignored */
|
||||||
|
AT_EXECFD = 2, /* file descriptor of program */
|
||||||
|
AT_PHDR = 3, /* program headers for program */
|
||||||
|
AT_PHENT = 4, /* size of program header entry */
|
||||||
|
AT_PHNUM = 5, /* number of program headers */
|
||||||
|
AT_PAGESZ = 6, /* system page size */
|
||||||
|
AT_BASE = 7, /* base address of interpreter */
|
||||||
|
AT_FLAGS = 8, /* flags */
|
||||||
|
AT_ENTRY = 9, /* entry point of program */
|
||||||
|
AT_NOTELF = 10, /* program is not ELF */
|
||||||
|
AT_UID = 11, /* real uid */
|
||||||
|
AT_EUID = 12, /* effective uid */
|
||||||
|
AT_GID = 13, /* real gid */
|
||||||
|
AT_EGID = 14, /* effective gid */
|
||||||
|
AT_PLATFORM = 15, /* string identifying CPU for optimizations */
|
||||||
|
AT_HWCAP = 16, /* arch dependent hints at CPU capabilities */
|
||||||
|
AT_CLKTCK = 17, /* frequency at which times() increments */
|
||||||
|
|
||||||
|
/* 18...22 not used */
|
||||||
|
|
||||||
|
AT_SECURE = 23, /* secure mode boolean */
|
||||||
|
AT_BASE_PLATFORM = 24, /* string identifying real platform, may
|
||||||
|
* differ from AT_PLATFORM. */
|
||||||
|
AT_RANDOM = 25, /* address of 16 random bytes */
|
||||||
|
AT_HWCAP2 = 26, /* extension of AT_HWCAP */
|
||||||
|
|
||||||
|
/* 28...30 not used */
|
||||||
|
|
||||||
|
AT_EXECFN = 31, /* filename of program */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static AUX_KEYS: &'static [AuxKey] = &[
|
||||||
|
AuxKey::AT_NULL,
|
||||||
|
AuxKey::AT_IGNORE,
|
||||||
|
AuxKey::AT_EXECFD,
|
||||||
|
AuxKey::AT_PHDR,
|
||||||
|
AuxKey::AT_PHENT,
|
||||||
|
AuxKey::AT_PHNUM,
|
||||||
|
AuxKey::AT_PAGESZ,
|
||||||
|
AuxKey::AT_BASE,
|
||||||
|
AuxKey::AT_FLAGS,
|
||||||
|
AuxKey::AT_ENTRY,
|
||||||
|
AuxKey::AT_NOTELF,
|
||||||
|
AuxKey::AT_UID,
|
||||||
|
AuxKey::AT_EUID,
|
||||||
|
AuxKey::AT_GID,
|
||||||
|
AuxKey::AT_EGID,
|
||||||
|
AuxKey::AT_PLATFORM,
|
||||||
|
AuxKey::AT_HWCAP,
|
||||||
|
AuxKey::AT_CLKTCK,
|
||||||
|
AuxKey::AT_SECURE,
|
||||||
|
AuxKey::AT_BASE_PLATFORM,
|
||||||
|
AuxKey::AT_RANDOM,
|
||||||
|
AuxKey::AT_HWCAP2,
|
||||||
|
AuxKey::AT_EXECFN,
|
||||||
|
];
|
||||||
|
|
||||||
|
impl AuxKey {
|
||||||
|
pub const MAX: usize = 32;
|
||||||
|
|
||||||
|
pub fn next(&self) -> Option<AuxKey> {
|
||||||
|
let self_idx = AUX_KEYS.iter().position(|x| *x == *self).unwrap();
|
||||||
|
let next_idx = self_idx + 1;
|
||||||
|
if next_idx < AUX_KEYS.len() {
|
||||||
|
Some(AUX_KEYS[next_idx])
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Copy, Debug)]
|
||||||
|
pub struct AuxTable {
|
||||||
|
values: [Option<u64>; AuxKey::MAX],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AuxTable {
|
||||||
|
pub fn new() -> AuxTable {
|
||||||
|
AuxTable {
|
||||||
|
values: [None; AuxKey::MAX]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_val(&mut self, key: AuxKey, val: u64) -> Result<(), Error>{
|
||||||
|
if key == AuxKey::AT_NULL || key == AuxKey::AT_IGNORE {
|
||||||
|
return Err(Error::new(Errno::EINVAL, "Illegal key"));
|
||||||
|
}
|
||||||
|
self.values[key as usize] = Some(val);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_val(&self, key: AuxKey) -> Option<u64> {
|
||||||
|
self.values[key as usize]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn del_val(&mut self, key: AuxKey) {
|
||||||
|
self.values[key as usize] = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter<'a>(&'a self) -> AuxTableIter<'a> {
|
||||||
|
AuxTableIter {
|
||||||
|
tbl: self,
|
||||||
|
key: Some(AuxKey::AT_NULL),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a AuxTable {
|
||||||
|
type Item = (AuxKey, u64);
|
||||||
|
type IntoIter = AuxTableIter<'a>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AuxTableIter<'a> {
|
||||||
|
tbl: &'a AuxTable,
|
||||||
|
key: Option<AuxKey>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for AuxTableIter<'a> {
|
||||||
|
type Item = (AuxKey, u64);
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<(AuxKey, u64)> {
|
||||||
|
loop {
|
||||||
|
if self.key == None { return None; }
|
||||||
|
let key = self.key.unwrap();
|
||||||
|
|
||||||
|
let item = self.tbl.get_val(key).map(|val| (key, val) );
|
||||||
|
self.key = key.next();
|
||||||
|
|
||||||
|
if item != None {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -34,6 +34,7 @@ mod mm;
|
|||||||
mod process;
|
mod process;
|
||||||
mod syscall;
|
mod syscall;
|
||||||
mod vma;
|
mod vma;
|
||||||
|
mod init_stack;
|
||||||
|
|
||||||
/// Export system calls
|
/// Export system calls
|
||||||
pub use syscall::*;
|
pub use syscall::*;
|
||||||
@ -48,7 +49,9 @@ pub extern "C" fn libos_boot(path_buf: *const i8) -> i32 {
|
|||||||
let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short);
|
let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short);
|
||||||
panic::catch_unwind(||{
|
panic::catch_unwind(||{
|
||||||
backtrace::__rust_begin_short_backtrace(||{
|
backtrace::__rust_begin_short_backtrace(||{
|
||||||
process::do_spawn(&path_str);
|
let argv = std::vec::Vec::new();
|
||||||
|
let envp = std::vec::Vec::new();
|
||||||
|
process::do_spawn(&path_str, &argv, &envp);
|
||||||
})
|
})
|
||||||
}).ok();
|
}).ok();
|
||||||
|
|
||||||
|
@ -7,10 +7,12 @@ pub use sgx_trts::libc;
|
|||||||
pub use std::marker::{Sync, Send};
|
pub use std::marker::{Sync, Send};
|
||||||
pub use std::sync::{Arc, SgxMutex, SgxMutexGuard, SgxRwLock,
|
pub use std::sync::{Arc, SgxMutex, SgxMutexGuard, SgxRwLock,
|
||||||
SgxRwLockReadGuard, SgxRwLockWriteGuard};
|
SgxRwLockReadGuard, SgxRwLockWriteGuard};
|
||||||
|
pub use std::cell::{Cell};
|
||||||
pub use std::result::Result;
|
pub use std::result::Result;
|
||||||
pub use std::borrow::BorrowMut;
|
pub use std::borrow::BorrowMut;
|
||||||
pub use std::boxed::Box;
|
pub use std::boxed::Box;
|
||||||
pub use std::vec::Vec;
|
pub use std::vec::Vec;
|
||||||
|
pub use std::string::{String};
|
||||||
pub use std::collections::{HashMap, VecDeque};
|
pub use std::collections::{HashMap, VecDeque};
|
||||||
pub use std::fmt::{Debug, Display};
|
pub use std::fmt::{Debug, Display};
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ use std::sync::atomic::{AtomicU32, Ordering};
|
|||||||
use std::sgxfs::SgxFile;
|
use std::sgxfs::SgxFile;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
use std::ffi::{CStr, CString};
|
||||||
|
|
||||||
use xmas_elf::{ElfFile, header, program, sections};
|
use xmas_elf::{ElfFile, header, program, sections};
|
||||||
use xmas_elf::symbol_table::Entry;
|
use xmas_elf::symbol_table::Entry;
|
||||||
@ -14,6 +15,7 @@ use xmas_elf::symbol_table::Entry;
|
|||||||
use vma::Vma;
|
use vma::Vma;
|
||||||
use file::{File, StdinFile, StdoutFile/*, StderrFile*/};
|
use file::{File, StdinFile, StdoutFile/*, StderrFile*/};
|
||||||
use file_table::{FileTable};
|
use file_table::{FileTable};
|
||||||
|
use init_stack::{StackBuf, AuxKey, AuxTable, do_init_process_stack};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref PROCESS_TABLE: SgxMutex<HashMap<u32, ProcessRef>> = {
|
static ref PROCESS_TABLE: SgxMutex<HashMap<u32, ProcessRef>> = {
|
||||||
@ -45,8 +47,10 @@ fn free_pid(pid: u32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn do_spawn<P: AsRef<Path>>(elf_path: &P) -> Result<u32, Error> {
|
pub fn do_spawn<P: AsRef<Path>>(elf_path: &P, argv: &[CString], envp: &[CString])
|
||||||
let elf_buf = open_elf(elf_path)
|
-> Result<u32, Error>
|
||||||
|
{
|
||||||
|
let elf_buf = open_elf(&elf_path)
|
||||||
.map_err(|e| (e.errno, "Failed to open the ELF file"))?;
|
.map_err(|e| (e.errno, "Failed to open the ELF file"))?;
|
||||||
|
|
||||||
let elf_file = {
|
let elf_file = {
|
||||||
@ -64,7 +68,7 @@ pub fn do_spawn<P: AsRef<Path>>(elf_path: &P) -> Result<u32, Error> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let new_process = {
|
let new_process = {
|
||||||
let mut new_process = Process::new(&elf_file)
|
let mut new_process = Process::new(&elf_file, argv, envp)
|
||||||
.map_err(|e| (Errno::EUNDEF, "Failed to create the process"))?;
|
.map_err(|e| (Errno::EUNDEF, "Failed to create the process"))?;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -206,7 +210,7 @@ fn open_elf<P: AsRef<Path>>(path: &P) -> Result<Vec<u8>, Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Process {
|
pub struct Process {
|
||||||
pub task: Task,
|
pub task: Task,
|
||||||
@ -223,14 +227,16 @@ pub struct Process {
|
|||||||
pub type ProcessRef = Arc<SgxMutex<Process>>;
|
pub type ProcessRef = Arc<SgxMutex<Process>>;
|
||||||
|
|
||||||
impl Process {
|
impl Process {
|
||||||
pub fn new(elf_file: &ElfFile) -> Result<Process, Error> {
|
pub fn new(elf_file: &ElfFile, argv: &[CString], envp: &[CString])
|
||||||
|
-> Result<Process, Error>
|
||||||
|
{
|
||||||
let mut new_process : Process = Default::default();
|
let mut new_process : Process = Default::default();
|
||||||
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 {
|
new_process.task = Task {
|
||||||
user_stack_addr: new_process.stack_vma.mem_end - 16,
|
user_stack_addr: new_process.init_stack(argv, envp)? as usize,
|
||||||
user_entry_addr: new_process.program_entry_addr,
|
user_entry_addr: new_process.program_entry_addr,
|
||||||
fs_base_addr: 0,
|
fs_base_addr: 0,
|
||||||
.. Default::default()
|
.. Default::default()
|
||||||
@ -241,6 +247,25 @@ impl Process {
|
|||||||
Ok(new_process)
|
Ok(new_process)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn init_stack(&mut self, argv: &[CString], envp: &[CString])
|
||||||
|
-> Result<*const u8, Error>
|
||||||
|
{
|
||||||
|
let stack = StackBuf::new(self.stack_vma.mem_end as *const u8,
|
||||||
|
self.stack_vma.mem_begin as *const u8)?;
|
||||||
|
|
||||||
|
let mut auxtbl = AuxTable::new();
|
||||||
|
auxtbl.set_val(AuxKey::AT_PAGESZ, 4096)?;
|
||||||
|
auxtbl.set_val(AuxKey::AT_UID, 0)?;
|
||||||
|
auxtbl.set_val(AuxKey::AT_GID, 0)?;
|
||||||
|
auxtbl.set_val(AuxKey::AT_EUID, 0)?;
|
||||||
|
auxtbl.set_val(AuxKey::AT_EGID, 0)?;
|
||||||
|
auxtbl.set_val(AuxKey::AT_SECURE, 0)?;
|
||||||
|
|
||||||
|
do_init_process_stack(&stack, &argv, &envp, &auxtbl)?;
|
||||||
|
|
||||||
|
Ok(stack.get_pos())
|
||||||
|
}
|
||||||
|
|
||||||
fn create_process_image(self: &mut Process, elf_file: &ElfFile)
|
fn create_process_image(self: &mut Process, elf_file: &ElfFile)
|
||||||
-> Result<(), Error>
|
-> Result<(), Error>
|
||||||
{
|
{
|
||||||
|
@ -1,15 +1,36 @@
|
|||||||
use prelude::*;
|
use prelude::*;
|
||||||
use {std, file, file_table, fs, process};
|
use {std, file, file_table, fs, process};
|
||||||
use std::ffi::CStr; // a borrowed C string
|
use std::ffi::{CStr, CString};
|
||||||
// Use the internal syscall wrappers from sgx_tstd
|
// Use the internal syscall wrappers from sgx_tstd
|
||||||
//use std::libc_fs as fs;
|
//use std::libc_fs as fs;
|
||||||
//use std::libc_io as io;
|
//use std::libc_io as io;
|
||||||
|
|
||||||
// TODO: check all pointer passed from user belongs to user space
|
fn check_ptr_from_user<T>(user_ptr: *const T) -> Result<*const T, Error> {
|
||||||
|
Ok(user_ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_mut_ptr_from_user<T>(user_ptr: *mut T) -> Result<*mut T, Error> {
|
||||||
|
Ok(user_ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clone_string_from_user_safely(user_ptr: *const c_char)
|
||||||
|
-> Result<String, Error>
|
||||||
|
{
|
||||||
|
let user_ptr = check_ptr_from_user(user_ptr)?;
|
||||||
|
let string = unsafe {
|
||||||
|
CStr::from_ptr(user_ptr).to_string_lossy().into_owned()
|
||||||
|
};
|
||||||
|
Ok(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clone_cstrings_from_user_safely(user_ptr: *const *const c_char)
|
||||||
|
-> Result<Vec<CString>, Error>
|
||||||
|
{
|
||||||
|
let cstrings = Vec::new();
|
||||||
|
Ok(cstrings)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
*/
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn occlum_open(path_buf: * const c_char, flags: c_int, mode: c_int) -> c_int {
|
pub extern "C" fn occlum_open(path_buf: * const c_char, flags: c_int, mode: c_int) -> c_int {
|
||||||
let path = unsafe {
|
let path = unsafe {
|
||||||
@ -91,22 +112,31 @@ pub extern "C" fn occlum_unknown(num: u32)
|
|||||||
println!("[WARNING] Unknown syscall (num = {})", num);
|
println!("[WARNING] Unknown syscall (num = {})", num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn do_spawn(child_pid_ptr: *mut c_uint,
|
||||||
|
path: *const c_char,
|
||||||
|
argv: *const *const c_char,
|
||||||
|
envp: *const *const c_char)
|
||||||
|
-> Result<(), Error>
|
||||||
|
{
|
||||||
|
let child_pid_ptr = check_mut_ptr_from_user(child_pid_ptr)?;
|
||||||
|
let path = clone_string_from_user_safely(path)?;
|
||||||
|
let argv = clone_cstrings_from_user_safely(argv)?;
|
||||||
|
let envp = clone_cstrings_from_user_safely(envp)?;
|
||||||
|
|
||||||
|
let child_pid = process::do_spawn(&path, &argv, &envp)?;
|
||||||
|
|
||||||
|
unsafe { *child_pid_ptr = child_pid };
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn occlum_spawn(child_pid: *mut c_int, path: *const c_char,
|
pub extern "C" fn occlum_spawn(
|
||||||
|
child_pid: *mut c_uint, 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;
|
match do_spawn(child_pid, path, argv, envp) {
|
||||||
let path_str = unsafe {
|
Ok(()) => 0,
|
||||||
CStr::from_ptr(path as * const i8).to_string_lossy().into_owned()
|
Err(e) => { e.errno.as_retval() }
|
||||||
};
|
|
||||||
match process::do_spawn(&path_str) {
|
|
||||||
Ok(new_pid) => unsafe {
|
|
||||||
*child_pid = new_pid as c_int;
|
|
||||||
0
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
e.errno.as_retval()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user