Add argc and argv support
This commit is contained in:
		
							parent
							
								
									ae063cbf90
								
							
						
					
					
						commit
						ad704c421f
					
				| @ -7,7 +7,7 @@ enclave { | |||||||
| 
 | 
 | ||||||
|     trusted { |     trusted { | ||||||
|         /* define ECALLs here. */ |         /* define ECALLs here. */ | ||||||
|         public int libos_boot([in, string] const char* executable_path); |         public int libos_boot([in, string] const char* executable_path, [user_check] char** argv); | ||||||
|         public int libos_run(void); |         public int libos_run(void); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										82
									
								
								src/libos/src/entry.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										82
									
								
								src/libos/src/entry.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,82 @@ | |||||||
|  | use super::{*}; | ||||||
|  | use util::mem_util::from_untrusted::*; | ||||||
|  | use std::ffi::{CStr, CString, OsString}; | ||||||
|  | use std::path::{Path}; | ||||||
|  | 
 | ||||||
|  | #[no_mangle] | ||||||
|  | pub extern "C" fn libos_boot(path_buf: *const c_char, argv: *const *const c_char) -> i32 { | ||||||
|  |     let (path, args) = match parse_arguments(path_buf, argv) { | ||||||
|  |         Ok(path_and_args) => { | ||||||
|  |             path_and_args | ||||||
|  |         }, | ||||||
|  |         Err(_) => { | ||||||
|  |             return EXIT_STATUS_INTERNAL_ERROR; | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short); | ||||||
|  |     panic::catch_unwind(||{ | ||||||
|  |         backtrace::__rust_begin_short_backtrace(||{ | ||||||
|  |             match do_boot(&path, &args) { | ||||||
|  |                 Ok(()) => 0, | ||||||
|  |                 Err(err) => EXIT_STATUS_INTERNAL_ERROR, | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  |     }).unwrap_or(EXIT_STATUS_INTERNAL_ERROR) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[no_mangle] | ||||||
|  | pub extern "C" fn libos_run() -> i32 { | ||||||
|  |     let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short); | ||||||
|  |     panic::catch_unwind(||{ | ||||||
|  |         backtrace::__rust_begin_short_backtrace(||{ | ||||||
|  |             match do_run() { | ||||||
|  |                 Ok(exit_status) => exit_status, | ||||||
|  |                 Err(err) => EXIT_STATUS_INTERNAL_ERROR, | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  |     }).unwrap_or(EXIT_STATUS_INTERNAL_ERROR) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Use 127 as a special value to indicate internal error from libos, not from
 | ||||||
|  | // user programs, although it is completely ok for a user program to return 127.
 | ||||||
|  | const EXIT_STATUS_INTERNAL_ERROR : i32 = 127; | ||||||
|  | 
 | ||||||
|  | fn parse_arguments(path_buf: *const c_char, argv: *const *const c_char) | ||||||
|  |     -> Result<(String, Vec<CString>), Error> | ||||||
|  | { | ||||||
|  |     let path_string = { | ||||||
|  |         let path_cstring = clone_cstring_safely(path_buf)?; | ||||||
|  |         path_cstring.to_string_lossy().into_owned() | ||||||
|  |     }; | ||||||
|  |     let program_cstring = { | ||||||
|  |         let program_osstr= Path::new(&path_string).file_name() | ||||||
|  |             .ok_or_else(|| Error::new(Errno::EINVAL, "Invalid path"))?; | ||||||
|  |         let program_str = program_osstr.to_str() | ||||||
|  |             .ok_or_else(|| Error::new(Errno::EINVAL, "Invalid path"))?; | ||||||
|  |         CString::new(program_str) | ||||||
|  |             .or_else(|_| errno!(EINVAL, "Invalid path"))? | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     let mut args = clone_cstrings_safely(argv)?; | ||||||
|  |     args.insert(0, program_cstring); | ||||||
|  |     Ok((path_string, args)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // TODO: make sure do_boot can only be called once
 | ||||||
|  | fn do_boot(path_str: &str, argv: &Vec<CString>) -> Result<(), Error> { | ||||||
|  |     util::mpx_util::mpx_enable()?; | ||||||
|  | 
 | ||||||
|  |     let envp = std::vec::Vec::new(); | ||||||
|  |     let file_actions = Vec::new(); | ||||||
|  |     let parent = &process::IDLE_PROCESS; | ||||||
|  |     process::do_spawn(&path_str, argv, &envp, &file_actions, parent)?; | ||||||
|  | 
 | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // TODO: make sure do_run() cannot be called after do_boot()
 | ||||||
|  | fn do_run() -> Result<i32, Error> { | ||||||
|  |     let exit_status = process::run_task()?; | ||||||
|  |     Ok(exit_status) | ||||||
|  | } | ||||||
| @ -1,5 +1,5 @@ | |||||||
| use super::*; | use super::*; | ||||||
| use util::{new_ring_buf, RingBufReader, RingBufWriter}; | use util::ring_buf::{*}; | ||||||
| 
 | 
 | ||||||
| // TODO: Use Waiter and WaitQueue infrastructure to sleep when blocking
 | // TODO: Use Waiter and WaitQueue infrastructure to sleep when blocking
 | ||||||
| 
 | 
 | ||||||
| @ -13,13 +13,13 @@ pub struct Pipe { | |||||||
| 
 | 
 | ||||||
| impl Pipe { | impl Pipe { | ||||||
|     pub fn new() -> Result<Pipe, Error> { |     pub fn new() -> Result<Pipe, Error> { | ||||||
|         let (reader, writer) = new_ring_buf(PIPE_BUF_SIZE); |         let mut ring_buf = RingBuf::new(PIPE_BUF_SIZE); | ||||||
|         Ok(Pipe { |         Ok(Pipe { | ||||||
|             reader: PipeReader { |             reader: PipeReader { | ||||||
|                 inner: SgxMutex::new(reader), |                 inner: SgxMutex::new(ring_buf.reader), | ||||||
|             }, |             }, | ||||||
|             writer: PipeWriter { |             writer: PipeWriter { | ||||||
|                 inner: SgxMutex::new(writer), |                 inner: SgxMutex::new(ring_buf.writer), | ||||||
|             } |             } | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -26,6 +26,7 @@ use sgx_trts::libc; | |||||||
| 
 | 
 | ||||||
| #[macro_use] | #[macro_use] | ||||||
| mod prelude; | mod prelude; | ||||||
|  | mod entry; | ||||||
| mod errno; | mod errno; | ||||||
| mod fs; | mod fs; | ||||||
| mod process; | mod process; | ||||||
| @ -36,58 +37,7 @@ mod time; | |||||||
| 
 | 
 | ||||||
| use prelude::*; | use prelude::*; | ||||||
| 
 | 
 | ||||||
| /// Export system calls
 | // Export system calls
 | ||||||
| pub use syscall::*; | pub use syscall::*; | ||||||
| 
 | // Export ECalls
 | ||||||
| // TODO: return meaningful exit code
 | pub use entry::*; | ||||||
| #[no_mangle] |  | ||||||
| pub extern "C" fn libos_boot(path_buf: *const i8) -> i32 { |  | ||||||
|     let path_str = unsafe { |  | ||||||
|         CStr::from_ptr(path_buf).to_string_lossy().into_owned() |  | ||||||
|     }; |  | ||||||
|     let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short); |  | ||||||
|     panic::catch_unwind(||{ |  | ||||||
|         backtrace::__rust_begin_short_backtrace(||{ |  | ||||||
|             match do_boot(&path_str) { |  | ||||||
|                 Ok(()) => 0, |  | ||||||
|                 Err(err) => EXIT_STATUS_INTERNAL_ERROR, |  | ||||||
|             } |  | ||||||
|         }) |  | ||||||
|     }).unwrap_or(EXIT_STATUS_INTERNAL_ERROR) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[no_mangle] |  | ||||||
| pub extern "C" fn libos_run() -> i32 { |  | ||||||
|     let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short); |  | ||||||
|     panic::catch_unwind(||{ |  | ||||||
|         backtrace::__rust_begin_short_backtrace(||{ |  | ||||||
|             match do_run() { |  | ||||||
|                 Ok(exit_status) => exit_status, |  | ||||||
|                 Err(err) => EXIT_STATUS_INTERNAL_ERROR, |  | ||||||
|             } |  | ||||||
|         }) |  | ||||||
|     }).unwrap_or(EXIT_STATUS_INTERNAL_ERROR) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Use 127 as a special value to indicate internal error from libos, not from
 |  | ||||||
| // user programs, although it is completely ok for a user program to return 127.
 |  | ||||||
| const EXIT_STATUS_INTERNAL_ERROR : i32 = 127; |  | ||||||
| 
 |  | ||||||
| // TODO: make sure do_boot can only be called once
 |  | ||||||
| fn do_boot(path_str: &str) -> Result<(), Error> { |  | ||||||
|     util::mpx_enable()?; |  | ||||||
| 
 |  | ||||||
|     let argv = std::vec::Vec::new(); |  | ||||||
|     let envp = std::vec::Vec::new(); |  | ||||||
|     let file_actions = Vec::new(); |  | ||||||
|     let parent = &process::IDLE_PROCESS; |  | ||||||
|     process::do_spawn(&path_str, &argv, &envp, &file_actions, parent)?; |  | ||||||
| 
 |  | ||||||
|     Ok(()) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // TODO: make sure do_run() cannot be called before do_boot()
 |  | ||||||
| fn do_run() -> Result<i32, Error> { |  | ||||||
|     let exit_status = process::run_task()?; |  | ||||||
|     Ok(exit_status) |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ use fs::{off_t, FileDesc}; | |||||||
| use vm::{VMAreaFlags, VMResizeOptions}; | use vm::{VMAreaFlags, VMResizeOptions}; | ||||||
| use process::{pid_t, ChildProcessFilter, FileAction}; | use process::{pid_t, ChildProcessFilter, FileAction}; | ||||||
| use time::{timeval_t}; | use time::{timeval_t}; | ||||||
|  | use util::mem_util::from_user::{*}; | ||||||
| // 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;
 | ||||||
| @ -17,39 +18,6 @@ pub struct iovec_t { | |||||||
|     len: size_t, |     len: size_t, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn check_ptr_from_user<T>(user_ptr: *const T) -> Result<(), Error> { |  | ||||||
|     Ok(()) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn check_mut_ptr_from_user<T>(user_ptr: *mut T) -> Result<(), Error> { |  | ||||||
|     Ok(()) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn check_array_from_user<T>(user_buf: *const T, count: usize) -> Result<(), Error> { |  | ||||||
|     Ok(()) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn check_mut_array_from_user<T>(user_buf: *mut T, count: usize) -> Result<(), Error> { |  | ||||||
|     Ok(()) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn clone_cstring_from_user_safely(user_ptr: *const c_char) |  | ||||||
|     -> Result<String, Error> |  | ||||||
| { |  | ||||||
|     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) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| /* | /* | ||||||
|  * This Rust-version of fdop correspond to the C-version one in Occlum. |  * This Rust-version of fdop correspond to the C-version one in Occlum. | ||||||
| @ -73,14 +41,14 @@ pub struct FdOp { | |||||||
|     path: *const u8, |     path: *const u8, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn clone_file_actions_from_user_safely(fdop_ptr: *const FdOp) | fn clone_file_actions_safely(fdop_ptr: *const FdOp) | ||||||
|     -> Result<Vec<FileAction>, Error> |     -> Result<Vec<FileAction>, Error> | ||||||
| { | { | ||||||
|     let mut file_actions = Vec::new(); |     let mut file_actions = Vec::new(); | ||||||
| 
 | 
 | ||||||
|     let mut fdop_ptr = fdop_ptr; |     let mut fdop_ptr = fdop_ptr; | ||||||
|     while fdop_ptr != ptr::null() { |     while fdop_ptr != ptr::null() { | ||||||
|         check_ptr_from_user(fdop_ptr)?; |         check_ptr(fdop_ptr)?; | ||||||
|         let fdop = unsafe { &*fdop_ptr }; |         let fdop = unsafe { &*fdop_ptr }; | ||||||
| 
 | 
 | ||||||
|         let file_action = match fdop.cmd { |         let file_action = match fdop.cmd { | ||||||
| @ -113,11 +81,11 @@ fn do_spawn(child_pid_ptr: *mut c_uint, | |||||||
|             ) |             ) | ||||||
|     -> Result<(), Error> |     -> Result<(), Error> | ||||||
| { | { | ||||||
|     check_mut_ptr_from_user(child_pid_ptr)?; |     check_mut_ptr(child_pid_ptr)?; | ||||||
|     let path = clone_cstring_from_user_safely(path)?; |     let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); | ||||||
|     let argv = clone_cstrings_from_user_safely(argv)?; |     let argv = clone_cstrings_safely(argv)?; | ||||||
|     let envp = clone_cstrings_from_user_safely(envp)?; |     let envp = clone_cstrings_safely(envp)?; | ||||||
|     let file_actions = clone_file_actions_from_user_safely(fdop_list)?; |     let file_actions = clone_file_actions_safely(fdop_list)?; | ||||||
|     let parent = process::get_current(); |     let parent = process::get_current(); | ||||||
| 
 | 
 | ||||||
|     let child_pid = process::do_spawn(&path, &argv, &envp, &file_actions, &parent)?; |     let child_pid = process::do_spawn(&path, &argv, &envp, &file_actions, &parent)?; | ||||||
| @ -133,7 +101,7 @@ fn do_read(fd: c_int, buf: *mut c_void, size: size_t) | |||||||
|     let safe_buf = { |     let safe_buf = { | ||||||
|         let buf = buf as *mut u8; |         let buf = buf as *mut u8; | ||||||
|         let size = size as usize; |         let size = size as usize; | ||||||
|         check_mut_array_from_user(buf, size)?; |         check_mut_array(buf, size)?; | ||||||
|         unsafe { std::slice::from_raw_parts_mut(buf, size) } |         unsafe { std::slice::from_raw_parts_mut(buf, size) } | ||||||
|     }; |     }; | ||||||
|     fs::do_read(fd, safe_buf) |     fs::do_read(fd, safe_buf) | ||||||
| @ -146,7 +114,7 @@ fn do_write(fd: c_int, buf: *const c_void, size: size_t) | |||||||
|     let safe_buf = { |     let safe_buf = { | ||||||
|         let buf = buf as *mut u8; |         let buf = buf as *mut u8; | ||||||
|         let size = size as usize; |         let size = size as usize; | ||||||
|         check_array_from_user(buf, size)?; |         check_array(buf, size)?; | ||||||
|         unsafe { std::slice::from_raw_parts(buf, size) } |         unsafe { std::slice::from_raw_parts(buf, size) } | ||||||
|     }; |     }; | ||||||
|     fs::do_write(fd, safe_buf) |     fs::do_write(fd, safe_buf) | ||||||
| @ -164,7 +132,7 @@ fn do_writev(fd: c_int, iov: *const iovec_t, count: c_int) | |||||||
|         count as usize |         count as usize | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     check_array_from_user(iov, count); |     check_array(iov, count); | ||||||
|     let bufs_vec = { |     let bufs_vec = { | ||||||
|         let mut bufs_vec = Vec::with_capacity(count); |         let mut bufs_vec = Vec::with_capacity(count); | ||||||
|         for iov_i in 0..count { |         for iov_i in 0..count { | ||||||
| @ -194,7 +162,7 @@ fn do_readv(fd: c_int, iov: *mut iovec_t, count: c_int) | |||||||
|         count as usize |         count as usize | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     check_array_from_user(iov, count); |     check_array(iov, count); | ||||||
|     let mut bufs_vec = { |     let mut bufs_vec = { | ||||||
|         let mut bufs_vec = Vec::with_capacity(count); |         let mut bufs_vec = Vec::with_capacity(count); | ||||||
|         for iov_i in 0..count { |         for iov_i in 0..count { | ||||||
| @ -274,7 +242,7 @@ fn do_brk(new_brk_addr: *const c_void) -> Result<*const c_void, Error> { | |||||||
| 
 | 
 | ||||||
| fn do_wait4(pid: c_int, _exit_status: *mut c_int) -> Result<pid_t, Error> { | fn do_wait4(pid: c_int, _exit_status: *mut c_int) -> Result<pid_t, Error> { | ||||||
|     if _exit_status != 0 as *mut c_int { |     if _exit_status != 0 as *mut c_int { | ||||||
|         check_mut_ptr_from_user(_exit_status)?; |         check_mut_ptr(_exit_status)?; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     let child_process_filter = match pid { |     let child_process_filter = match pid { | ||||||
| @ -310,7 +278,7 @@ fn do_wait4(pid: c_int, _exit_status: *mut c_int) -> Result<pid_t, Error> { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn do_pipe2(fds_u: *mut c_int, flags: c_int) -> Result<(), Error> { | fn do_pipe2(fds_u: *mut c_int, flags: c_int) -> Result<(), Error> { | ||||||
|     check_mut_array_from_user(fds_u, 2)?; |     check_mut_array(fds_u, 2)?; | ||||||
|     // TODO: how to deal with open flags???
 |     // TODO: how to deal with open flags???
 | ||||||
|     let fds = fs::do_pipe2(flags as u32)?; |     let fds = fs::do_pipe2(flags as u32)?; | ||||||
|     unsafe { |     unsafe { | ||||||
| @ -321,7 +289,7 @@ fn do_pipe2(fds_u: *mut c_int, flags: c_int) -> Result<(), Error> { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn do_gettimeofday(tv_u: *mut timeval_t) -> Result<(), Error> { | fn do_gettimeofday(tv_u: *mut timeval_t) -> Result<(), Error> { | ||||||
|     check_mut_ptr_from_user(tv_u)?; |     check_mut_ptr(tv_u)?; | ||||||
|     let tv = time::do_gettimeofday(); |     let tv = time::do_gettimeofday(); | ||||||
|     unsafe { *tv_u = tv; } |     unsafe { *tv_u = tv; } | ||||||
|     Ok(()) |     Ok(()) | ||||||
|  | |||||||
							
								
								
									
										110
									
								
								src/libos/src/util/mem_util.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										110
									
								
								src/libos/src/util/mem_util.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,110 @@ | |||||||
|  | use super::*; | ||||||
|  | use std::ffi::{CStr, CString}; | ||||||
|  | use std::{ptr}; | ||||||
|  | 
 | ||||||
|  | /// Memory utilities that deals with primitive types passed from user process
 | ||||||
|  | /// running inside enclave
 | ||||||
|  | pub mod from_user { | ||||||
|  |     use super::*; | ||||||
|  | 
 | ||||||
|  |     /// Check the user pointer is within the readable memory range of the user process
 | ||||||
|  |     pub fn check_ptr<T>(user_ptr: *const T) -> Result<(), Error> { | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Check the mutable user pointer is within the writable memory of the user process
 | ||||||
|  |     pub fn check_mut_ptr<T>(user_ptr: *mut T) -> Result<(), Error> { | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Check the readonly array is within the readable memory of the user process
 | ||||||
|  |     pub fn check_array<T>(user_buf: *const T, count: usize) -> Result<(), Error> { | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Check the mutable array is within the writable memory of the user process
 | ||||||
|  |     pub fn check_mut_array<T>(user_buf: *mut T, count: usize) -> Result<(), Error> { | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Clone a C-string from the user process safely
 | ||||||
|  |     pub fn clone_cstring_safely(out_ptr: *const c_char) | ||||||
|  |         -> Result<CString, Error> | ||||||
|  |     { | ||||||
|  |         check_ptr(out_ptr)?; | ||||||
|  |         // TODO: using from_ptr directly is not safe
 | ||||||
|  |         let cstr = unsafe { CStr::from_ptr(out_ptr) }; | ||||||
|  |         let cstring = CString::from(cstr); | ||||||
|  |         Ok(cstring) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Clone a C-string array (const char*[]) from the user process safely
 | ||||||
|  |     ///
 | ||||||
|  |     /// This array must be ended with a NULL pointer.
 | ||||||
|  |     pub fn clone_cstrings_safely(user_ptr: *const *const c_char) | ||||||
|  |         -> Result<Vec<CString>, Error> | ||||||
|  |     { | ||||||
|  |         let mut cstrings = Vec::new(); | ||||||
|  |         let mut user_ptr = user_ptr; | ||||||
|  |         while user_ptr != ptr::null() { | ||||||
|  |             let cstr_ptr = unsafe { *user_ptr }; | ||||||
|  |             let cstring = clone_cstring_safely(cstr_ptr)?; | ||||||
|  |             cstrings.push(cstring); | ||||||
|  |             user_ptr = unsafe { user_ptr.offset(1) }; | ||||||
|  |         } | ||||||
|  |         Ok(cstrings) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Memory utilities that deals with primitive types passed from outside the enclave
 | ||||||
|  | pub mod from_untrusted { | ||||||
|  |     use super::*; | ||||||
|  | 
 | ||||||
|  |     /// Check the untrusted pointer is outside the enclave
 | ||||||
|  |     pub fn check_ptr<T>(out_ptr: *const T) -> Result<(), Error> { | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Check the untrusted array is outside the enclave
 | ||||||
|  |     pub fn check_array<T>(out_ptr: *const T, count: usize) -> Result<(), Error> { | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Clone a C-string from outside the enclave
 | ||||||
|  |     pub fn clone_cstring_safely(out_ptr: *const c_char) | ||||||
|  |         -> Result<CString, Error> | ||||||
|  |     { | ||||||
|  |         check_ptr(out_ptr)?; | ||||||
|  |         // TODO: using from_ptr directly is not safe
 | ||||||
|  |         let cstr = unsafe { CStr::from_ptr(out_ptr) }; | ||||||
|  |         let cstring = CString::from(cstr); | ||||||
|  |         Ok(cstring) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Clone a C-string array (const char*[]) from outside the enclave
 | ||||||
|  |     ///
 | ||||||
|  |     /// This array must be ended with a NULL pointer.
 | ||||||
|  |     pub fn clone_cstrings_safely(out_ptr: *const *const c_char) | ||||||
|  |         -> Result<Vec<CString>, Error> | ||||||
|  |     { | ||||||
|  |         let mut cstrings = Vec::new(); | ||||||
|  |         if out_ptr == ptr::null() { return Ok(cstrings); } | ||||||
|  | 
 | ||||||
|  |         let mut out_ptr = out_ptr; | ||||||
|  |         loop { | ||||||
|  |             check_ptr(out_ptr); | ||||||
|  |             let cstr_ptr = { | ||||||
|  |                 let cstr_ptr = unsafe { *out_ptr }; | ||||||
|  |                 if cstr_ptr == ptr::null() { break; } | ||||||
|  |                 check_ptr(cstr_ptr); | ||||||
|  |                 cstr_ptr | ||||||
|  |             }; | ||||||
|  |             let cstring = clone_cstring_safely(cstr_ptr)?; | ||||||
|  |             cstrings.push(cstring); | ||||||
|  | 
 | ||||||
|  |             out_ptr = unsafe { out_ptr.offset(1) }; | ||||||
|  |         } | ||||||
|  |         Ok(cstrings) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @ -1,8 +1,5 @@ | |||||||
| use super::*; | use super::*; | ||||||
| 
 | 
 | ||||||
| pub use self::mpx_util::{*}; | pub mod mpx_util; | ||||||
| pub use self::ring_buf::{RingBufReader, RingBufWriter}; | pub mod ring_buf; | ||||||
| pub use self::ring_buf::with_fixed_capacity as new_ring_buf; | pub mod mem_util; | ||||||
| 
 |  | ||||||
| mod mpx_util; |  | ||||||
| mod ring_buf; |  | ||||||
|  | |||||||
| @ -4,11 +4,19 @@ use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering}; | |||||||
| use std::cmp::{min, max}; | use std::cmp::{min, max}; | ||||||
| use std::{ptr}; | use std::{ptr}; | ||||||
| 
 | 
 | ||||||
| pub fn with_fixed_capacity(capacity: usize) -> (RingBufReader, RingBufWriter) { | #[derive(Debug)] | ||||||
|  | pub struct RingBuf { | ||||||
|  |     pub reader: RingBufReader, | ||||||
|  |     pub writer: RingBufWriter, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl RingBuf { | ||||||
|  |     pub fn new(capacity: usize) -> RingBuf { | ||||||
|         let inner = Arc::new(RingBufInner::new(capacity)); |         let inner = Arc::new(RingBufInner::new(capacity)); | ||||||
|         let reader = RingBufReader { inner: inner.clone() }; |         let reader = RingBufReader { inner: inner.clone() }; | ||||||
|         let writer = RingBufWriter { inner: inner }; |         let writer = RingBufWriter { inner: inner }; | ||||||
|     (reader, writer) |         RingBuf { reader: reader, writer: writer } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
|  | |||||||
| @ -214,9 +214,9 @@ int SGX_CDECL main(int argc, char *argv[]) | |||||||
|     uint32_t sealed_log_size = 1024; |     uint32_t sealed_log_size = 1024; | ||||||
|     uint8_t sealed_log[1024] = {0}; |     uint8_t sealed_log[1024] = {0}; | ||||||
| 
 | 
 | ||||||
|     if (argc != 2) { |     if (argc < 2) { | ||||||
|         printf("ERROR: The expected number of arguments is 1, but given %d\n\n", argc - 1); |         printf("ERROR: at least one argument must be provided\n\n"); | ||||||
|         printf("Usage: pal <path_to_executable>\n"); |         printf("Usage: pal <executable> <arg1> <arg2>...\n"); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|     const char* executable_path = argv[1]; |     const char* executable_path = argv[1]; | ||||||
| @ -229,7 +229,7 @@ int SGX_CDECL main(int argc, char *argv[]) | |||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     sgx_ret = libos_boot(global_eid, &status, executable_path); |     sgx_ret = libos_boot(global_eid, &status, executable_path, &argv[2]); | ||||||
|     if(sgx_ret != SGX_SUCCESS) { |     if(sgx_ret != SGX_SUCCESS) { | ||||||
|         print_error_message(sgx_ret); |         print_error_message(sgx_ret); | ||||||
|         return status; |         return status; | ||||||
|  | |||||||
| @ -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 := empty hello_world malloc file getpid spawn pipe time | TEST_SUITES := empty argv hello_world malloc file getpid spawn pipe time | ||||||
| BUILD_TEST_SUITES := $(TEST_SUITES:%=%) | BUILD_TEST_SUITES := $(TEST_SUITES:%=%) | ||||||
| RUN_TEST_SUITES := $(TEST_SUITES:%=test-%) | RUN_TEST_SUITES := $(TEST_SUITES:%=test-%) | ||||||
| CLEAN_TEST_SUITES := $(TEST_SUITES:%=clean-%) | CLEAN_TEST_SUITES := $(TEST_SUITES:%=clean-%) | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								test/argv/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										14
									
								
								test/argv/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | include ../test_common.mk | ||||||
|  | 
 | ||||||
|  | ARGC := 4 | ||||||
|  | ARG1 := 1 | ||||||
|  | ARG2 := arg2 | ||||||
|  | ARG3 := this is a string with spaces | ||||||
|  | 
 | ||||||
|  | EXTRA_C_FLAGS := \
 | ||||||
|  | 	-DEXPECTED_ARGC=$(ARGC) \
 | ||||||
|  | 	-DEXPECTED_ARG1="\"$(ARG1)\"" \
 | ||||||
|  | 	-DEXPECTED_ARG2="\"$(ARG2)\"" \
 | ||||||
|  | 	-DEXPECTED_ARG3="\"$(ARG3)\"" | ||||||
|  | EXTRA_LINK_FLAGS := | ||||||
|  | BIN_ARGS := "$(ARG1)" "$(ARG2)" "$(ARG3)" | ||||||
							
								
								
									
										30
									
								
								test/argv/main.c
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										30
									
								
								test/argv/main.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | |||||||
|  | #include <string.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | 
 | ||||||
|  | // Expected arguments are given by Makefile throught macro ARGC, ARG1, ARG2 and
 | ||||||
|  | // ARG3
 | ||||||
|  | const char* expected_argv[EXPECTED_ARGC] = { | ||||||
|  |     "bin.encrypted", | ||||||
|  |     EXPECTED_ARG1, | ||||||
|  |     EXPECTED_ARG2, | ||||||
|  |     EXPECTED_ARG3, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | int main(int argc, char* argv[]) { | ||||||
|  |     if (argc != EXPECTED_ARGC) { | ||||||
|  |         printf("ERROR: expect %d arguments, but %d are given\n", EXPECTED_ARGC, argc); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     for (int arg_i = 0; arg_i < argc; arg_i++) { | ||||||
|  |         const char* actual_arg = argv[arg_i]; | ||||||
|  |         const char* expected_arg = expected_argv[arg_i]; | ||||||
|  |         if (strcmp(actual_arg, expected_arg) != 0) { | ||||||
|  |             printf("ERROR: expect argument %d is %s, but given %s\n", | ||||||
|  |                     arg_i, expected_arg, actual_arg); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     printf("main()'s argc and argv are as expected\n"); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
| @ -2,3 +2,4 @@ include ../test_common.mk | |||||||
| 
 | 
 | ||||||
| EXTRA_C_FLAGS := | EXTRA_C_FLAGS := | ||||||
| EXTRA_LINK_FLAGS := | EXTRA_LINK_FLAGS := | ||||||
|  | BIN_ARGS := | ||||||
|  | |||||||
| @ -2,3 +2,4 @@ include ../test_common.mk | |||||||
| 
 | 
 | ||||||
| EXTRA_C_FLAGS := | EXTRA_C_FLAGS := | ||||||
| EXTRA_LINK_FLAGS := | EXTRA_LINK_FLAGS := | ||||||
|  | BIN_ARGS := | ||||||
|  | |||||||
| @ -2,3 +2,4 @@ include ../test_common.mk | |||||||
| 
 | 
 | ||||||
| EXTRA_C_FLAGS := | EXTRA_C_FLAGS := | ||||||
| EXTRA_LINK_FLAGS := | EXTRA_LINK_FLAGS := | ||||||
|  | BIN_ARGS := | ||||||
|  | |||||||
| @ -2,3 +2,4 @@ include ../test_common.mk | |||||||
| 
 | 
 | ||||||
| EXTRA_C_FLAGS := | EXTRA_C_FLAGS := | ||||||
| EXTRA_LINK_FLAGS := | EXTRA_LINK_FLAGS := | ||||||
|  | BIN_ARGS := | ||||||
|  | |||||||
| @ -2,3 +2,4 @@ include ../test_common.mk | |||||||
| 
 | 
 | ||||||
| EXTRA_C_FLAGS := | EXTRA_C_FLAGS := | ||||||
| EXTRA_LINK_FLAGS := | EXTRA_LINK_FLAGS := | ||||||
|  | BIN_ARGS := | ||||||
|  | |||||||
| @ -2,3 +2,4 @@ include ../test_common.mk | |||||||
| 
 | 
 | ||||||
| EXTRA_C_FLAGS := | EXTRA_C_FLAGS := | ||||||
| EXTRA_LINK_FLAGS := | EXTRA_LINK_FLAGS := | ||||||
|  | BIN_ARGS := | ||||||
|  | |||||||
| @ -2,3 +2,4 @@ include ../test_common.mk | |||||||
| 
 | 
 | ||||||
| EXTRA_C_FLAGS := | EXTRA_C_FLAGS := | ||||||
| EXTRA_LINK_FLAGS := | EXTRA_LINK_FLAGS := | ||||||
|  | BIN_ARGS := | ||||||
|  | |||||||
| @ -56,7 +56,7 @@ $(C_OBJS): %.o: %.c | |||||||
| #############################################################################
 | #############################################################################
 | ||||||
| 
 | 
 | ||||||
| test: $(BIN_ENC_NAME) | test: $(BIN_ENC_NAME) | ||||||
| 	@cd ../ && RUST_BACKTRACE=1 ./pal $(CUR_DIR)/$(BIN_ENC_NAME) | 	@cd ../ && RUST_BACKTRACE=1 ./pal $(CUR_DIR)/$(BIN_ENC_NAME) $(BIN_ARGS) | ||||||
| 
 | 
 | ||||||
| #############################################################################
 | #############################################################################
 | ||||||
| # Misc
 | # Misc
 | ||||||
|  | |||||||
| @ -2,3 +2,4 @@ include ../test_common.mk | |||||||
| 
 | 
 | ||||||
| EXTRA_C_FLAGS := | EXTRA_C_FLAGS := | ||||||
| EXTRA_LINK_FLAGS := | EXTRA_LINK_FLAGS := | ||||||
|  | BIN_ARGS := | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user