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