From 1a365de08f83453b3da5a90b706841fdc9a30c22 Mon Sep 17 00:00:00 2001 From: "Tate, Hongliang Tian" Date: Sat, 5 Oct 2019 14:21:15 +0000 Subject: [PATCH] Introduce the new error handling mechanism * Fast error diagnosing (e.g., backtrace and code location) * First-class POSIX errno (e.g., every error has an errno) * Zero-overhead abstraction (e.g., no heap allocation for simple errors) * Ergonomic grammar (e.g., providing convenient macros) --- src/libos/Cargo.lock | 2 +- src/libos/Cargo.toml | 2 +- src/libos/Makefile | 18 +- src/libos/src/config.rs | 110 ++++----- src/libos/src/entry.rs | 27 ++- src/libos/src/errno.rs | 257 ---------------------- src/libos/src/error/backtrace.rs | 65 ++++++ src/libos/src/error/errno.rs | 207 +++++++++++++++++ src/libos/src/error/error.rs | 107 +++++++++ src/libos/src/error/mod.rs | 53 +++++ src/libos/src/error/to_errno.rs | 100 +++++++++ src/libos/src/exception/cpuid.rs | 4 +- src/libos/src/fs/access.rs | 14 +- src/libos/src/fs/dev_null.rs | 36 +-- src/libos/src/fs/dev_random.rs | 38 ++-- src/libos/src/fs/dev_zero.rs | 36 +-- src/libos/src/fs/file.rs | 189 +++++++--------- src/libos/src/fs/file_table.rs | 22 +- src/libos/src/fs/inode_file.rs | 90 +++----- src/libos/src/fs/io_multiplexing.rs | 56 +++-- src/libos/src/fs/mod.rs | 112 +++++----- src/libos/src/fs/pipe.rs | 62 +++--- src/libos/src/fs/root_inode.rs | 53 ++--- src/libos/src/fs/sgx_impl.rs | 4 +- src/libos/src/fs/socket_file.rs | 36 +-- src/libos/src/fs/unix_socket.rs | 86 ++++---- src/libos/src/lib.rs | 11 +- src/libos/src/misc/rlimit.rs | 12 +- src/libos/src/misc/uname.rs | 2 +- src/libos/src/prelude.rs | 58 +---- src/libos/src/process/arch_prctl.rs | 8 +- src/libos/src/process/exit.rs | 4 +- src/libos/src/process/futex.rs | 18 +- src/libos/src/process/process.rs | 2 +- src/libos/src/process/process_table.rs | 4 +- src/libos/src/process/sched.rs | 18 +- src/libos/src/process/spawn/elf_helper.rs | 48 ++-- src/libos/src/process/spawn/init_stack.rs | 29 ++- src/libos/src/process/spawn/init_vm.rs | 9 +- src/libos/src/process/spawn/mod.rs | 39 ++-- src/libos/src/process/spawn/segment.rs | 25 +-- src/libos/src/process/task.rs | 8 +- src/libos/src/process/thread.rs | 8 +- src/libos/src/syscall/mod.rs | 241 ++++++++++---------- src/libos/src/time/mod.rs | 6 +- src/libos/src/util/log.rs | 12 +- src/libos/src/util/mem_util.rs | 24 +- src/libos/src/util/mpx_util.rs | 8 +- src/libos/src/util/ring_buf.rs | 6 +- src/libos/src/vm/mod.rs | 8 +- src/libos/src/vm/process_vm.rs | 26 +-- src/libos/src/vm/user_space_vm.rs | 4 +- src/libos/src/vm/vm_manager.rs | 50 ++--- 53 files changed, 1332 insertions(+), 1142 deletions(-) delete mode 100644 src/libos/src/errno.rs create mode 100644 src/libos/src/error/backtrace.rs create mode 100644 src/libos/src/error/errno.rs create mode 100644 src/libos/src/error/error.rs create mode 100644 src/libos/src/error/mod.rs create mode 100644 src/libos/src/error/to_errno.rs diff --git a/src/libos/Cargo.lock b/src/libos/Cargo.lock index b3059f83..5c15e019 100644 --- a/src/libos/Cargo.lock +++ b/src/libos/Cargo.lock @@ -2,7 +2,7 @@ # It is not intended for manual editing. [[package]] name = "Occlum" -version = "0.0.1" +version = "0.5.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "derive_builder 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/libos/Cargo.toml b/src/libos/Cargo.toml index 1d171cda..be33ba2c 100644 --- a/src/libos/Cargo.toml +++ b/src/libos/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "Occlum" -version = "0.0.1" +version = "0.5.0" [lib] name = "occlum_rs" diff --git a/src/libos/Makefile b/src/libos/Makefile index 9c1a49e7..b36861a1 100644 --- a/src/libos/Makefile +++ b/src/libos/Makefile @@ -1,6 +1,22 @@ include ../sgxenv.mk -RELEASE ?= 0 +# Build LibOS in debug or release mode +LIBOS_RELEASE ?= 0 + +# The log level for LibOS +# +# There are five levels: +# 1 - error +# 2 - warn +# 3 - info +# 4 - debug +# 5 - trace +# +# By setting the log level to a specific value (say warn), all log messages +# whose levels are no greater than the value (error and warn <= warn) will +# be printed. +LIBOS_LOG ?= error + ONLY_REBUILD_BUILTIN ?= 0 # The final and intermediate libraries diff --git a/src/libos/src/config.rs b/src/libos/src/config.rs index 2ce98b0e..260ae96a 100644 --- a/src/libos/src/config.rs +++ b/src/libos/src/config.rs @@ -1,64 +1,47 @@ use super::*; use serde::{Deserialize, Serialize}; use std::ffi::CString; +use std::io::Read; use std::path::{Path, PathBuf}; use std::sgxfs::SgxFile; -const LIBOS_CONFIG_PATH: &str = "./.occlum/build/Occlum.json.protected"; - lazy_static! { pub static ref LIBOS_CONFIG: Config = { - let mut config_file = { - let config_file = match SgxFile::open_integrity_only(LIBOS_CONFIG_PATH) { - Err(_) => panic!( - "Failed to find or open Occlum's config file: {}", - LIBOS_CONFIG_PATH - ), - Ok(file) => file, - }; + fn load_config(config_path: &str) -> Result { + let mut config_file = { + let config_file = + SgxFile::open_integrity_only(config_path).map_err(|e| errno!(e))?; - let actual_mac = match config_file.get_mac() { - Err(_) => panic!( - "Failed to get the MAC of Occlum's config file: {}", - LIBOS_CONFIG_PATH - ), - Ok(mac) => mac, + let actual_mac = config_file.get_mac().map_err(|e| errno!(e))?; + let expected_mac = conf_get_hardcoded_file_mac(); + if actual_mac != expected_mac { + return_errno!(EINVAL, "unexpected file MAC"); + } + + config_file }; - let expected_mac = conf_get_hardcoded_file_mac(); - if actual_mac != expected_mac { - panic!( - "The MAC of Occlum's config file is not as expected: {}", - LIBOS_CONFIG_PATH - ); + let config_json = { + let mut config_json = String::new(); + config_file + .read_to_string(&mut config_json) + .map_err(|e| errno!(e))?; + config_json + }; + let config_input: InputConfig = + serde_json::from_str(&config_json).map_err(|e| errno!(e))?; + let config = Config::from_input(&config_input) + .cause_err(|e| errno!(EINVAL, "invalid config JSON"))?; + Ok(config) + } + + let config_path = "./.occlum/build/Occlum.json.protected"; + match load_config(config_path) { + Err(e) => { + error!("failed to load config: {}", e.backtrace()); + panic!(); } - - config_file - }; - let config_json = { - let mut config_json = String::new(); - config_file.read_to_string(&mut config_json).map_err(|_| { - panic!( - "Failed to read from Occlum's config file: {}", - LIBOS_CONFIG_PATH - ); - }); - config_json - }; - let config_input: InputConfig = match serde_json::from_str(&config_json) { - Err(_) => panic!( - "Failed to parse JSON from Occlum's config file: {}", - LIBOS_CONFIG_PATH - ), - Ok(config_input) => config_input, - }; - let config = match Config::from_input(&config_input) { - Err(_) => panic!( - "Found invalid config in Occlum's config file: {}", - LIBOS_CONFIG_PATH - ), Ok(config) => config, - }; - config + } }; } @@ -77,18 +60,17 @@ fn conf_get_hardcoded_file_mac() -> sgx_aes_gcm_128bit_tag_t { mac } -fn parse_mac(mac_str: &str) -> Result { +fn parse_mac(mac_str: &str) -> Result { let bytes_str_vec = { let bytes_str_vec: Vec<&str> = mac_str.split("-").collect(); if bytes_str_vec.len() != 16 { - return errno!(EINVAL, "The length or format of MAC string is invalid"); + return_errno!(EINVAL, "The length or format of MAC string is invalid"); } bytes_str_vec }; let mut mac: sgx_aes_gcm_128bit_tag_t = Default::default(); for (byte_i, byte_str) in bytes_str_vec.iter().enumerate() { - mac[byte_i] = u8::from_str_radix(byte_str, 16) - .map_err(|_| Error::new(Errno::EINVAL, "The format of MAC string is invalid"))?; + mac[byte_i] = u8::from_str_radix(byte_str, 16).map_err(|e| errno!(e))?; } Ok(mac) } @@ -136,7 +118,7 @@ pub struct ConfigMountOptions { } impl Config { - fn from_input(input: &InputConfig) -> Result { + fn from_input(input: &InputConfig) -> Result { let vm = ConfigVM::from_input(&input.vm)?; let process = ConfigProcess::from_input(&input.process)?; let env = { @@ -163,14 +145,14 @@ impl Config { } impl ConfigVM { - fn from_input(input: &InputConfigVM) -> Result { + fn from_input(input: &InputConfigVM) -> Result { let user_space_size = parse_memory_size(&input.user_space_size)?; Ok(ConfigVM { user_space_size }) } } impl ConfigProcess { - fn from_input(input: &InputConfigProcess) -> Result { + fn from_input(input: &InputConfigProcess) -> Result { let default_stack_size = parse_memory_size(&input.default_stack_size)?; let default_heap_size = parse_memory_size(&input.default_heap_size)?; let default_mmap_size = parse_memory_size(&input.default_mmap_size)?; @@ -183,7 +165,7 @@ impl ConfigProcess { } impl ConfigMount { - fn from_input(input: &InputConfigMount) -> Result { + fn from_input(input: &InputConfigMount) -> Result { const ALL_FS_TYPES: [&str; 3] = ["sefs", "hostfs", "ramfs"]; let type_ = match input.type_.as_str() { @@ -191,13 +173,13 @@ impl ConfigMount { "hostfs" => ConfigMountFsType::TYPE_HOSTFS, "ramfs" => ConfigMountFsType::TYPE_RAMFS, _ => { - return errno!(EINVAL, "Unsupported file system type"); + return_errno!(EINVAL, "Unsupported file system type"); } }; let target = { let target = PathBuf::from(&input.target); if !target.starts_with("/") { - return errno!(EINVAL, "Target must be an absolute path"); + return_errno!(EINVAL, "Target must be an absolute path"); } target }; @@ -213,12 +195,12 @@ impl ConfigMount { } impl ConfigMountOptions { - fn from_input(input: &InputConfigMountOptions) -> Result { + fn from_input(input: &InputConfigMountOptions) -> Result { let (integrity_only, mac) = if !input.integrity_only { (false, None) } else { if input.mac.is_none() { - return errno!(EINVAL, "MAC is expected"); + return_errno!(EINVAL, "MAC is expected"); } (true, Some(parse_mac(&input.mac.as_ref().unwrap())?)) }; @@ -229,7 +211,7 @@ impl ConfigMountOptions { } } -fn parse_memory_size(mem_str: &str) -> Result { +fn parse_memory_size(mem_str: &str) -> Result { const UNIT2FACTOR: [(&str, usize); 5] = [ ("KB", 1024), ("MB", 1024 * 1024), @@ -242,13 +224,13 @@ fn parse_memory_size(mem_str: &str) -> Result { let (unit, factor) = UNIT2FACTOR .iter() .position(|(unit, _)| mem_str.ends_with(unit)) - .ok_or_else(|| Error::new(Errno::EINVAL, "No unit")) + .ok_or_else(|| errno!(EINVAL, "No unit")) .map(|unit_i| &UNIT2FACTOR[unit_i])?; let number = match mem_str[0..mem_str.len() - unit.len()] .trim() .parse::() { - Err(_) => return errno!(EINVAL, "No number"), + Err(_) => return_errno!(EINVAL, "No number"), Ok(number) => number, }; Ok(number * factor) diff --git a/src/libos/src/entry.rs b/src/libos/src/entry.rs index ba2280c5..b46c1b49 100644 --- a/src/libos/src/entry.rs +++ b/src/libos/src/entry.rs @@ -9,10 +9,13 @@ const ENCLAVE_PATH: &'static str = ".occlum/build/lib/libocclum.signed.so"; #[no_mangle] pub extern "C" fn libos_boot(path_buf: *const c_char, argv: *const *const c_char) -> i32 { + // Init the log infrastructure first so that log messages will be printed afterwards util::log::init(); + let (path, args) = match parse_arguments(path_buf, argv) { Ok(path_and_args) => path_and_args, - Err(_) => { + Err(e) => { + error!("invalid arguments for LibOS: {}", e.backtrace()); return EXIT_STATUS_INTERNAL_ERROR; } }; @@ -24,7 +27,10 @@ pub extern "C" fn libos_boot(path_buf: *const c_char, argv: *const *const c_char panic::catch_unwind(|| { backtrace::__rust_begin_short_backtrace(|| match do_boot(&path, &args) { Ok(()) => 0, - Err(err) => EXIT_STATUS_INTERNAL_ERROR, + Err(e) => { + error!("failed to boot up LibOS: {}", e.backtrace()); + EXIT_STATUS_INTERNAL_ERROR + } }) }) .unwrap_or(EXIT_STATUS_INTERNAL_ERROR) @@ -36,7 +42,10 @@ pub extern "C" fn libos_run(host_tid: i32) -> i32 { panic::catch_unwind(|| { backtrace::__rust_begin_short_backtrace(|| match do_run(host_tid as pid_t) { Ok(exit_status) => exit_status, - Err(err) => EXIT_STATUS_INTERNAL_ERROR, + Err(e) => { + error!("failed to execute a process: {}", e.backtrace()); + EXIT_STATUS_INTERNAL_ERROR + } }) }) .unwrap_or(EXIT_STATUS_INTERNAL_ERROR) @@ -53,7 +62,7 @@ const EXIT_STATUS_INTERNAL_ERROR: i32 = 127; fn parse_arguments( path_buf: *const c_char, argv: *const *const c_char, -) -> Result<(String, Vec), Error> { +) -> Result<(String, Vec)> { let path_string = { let path_cstring = clone_cstring_safely(path_buf)?; path_cstring.to_string_lossy().into_owned() @@ -61,11 +70,11 @@ fn parse_arguments( let program_cstring = { let program_osstr = Path::new(&path_string) .file_name() - .ok_or_else(|| Error::new(Errno::EINVAL, "Invalid path"))?; + .ok_or_else(|| 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"))? + .ok_or_else(|| errno!(EINVAL, "invalid path"))?; + CString::new(program_str).map_err(|e| errno!(e))? }; let mut args = clone_cstrings_safely(argv)?; @@ -74,7 +83,7 @@ fn parse_arguments( } // TODO: make sure do_boot can only be called once -fn do_boot(path_str: &str, argv: &Vec) -> Result<(), Error> { +fn do_boot(path_str: &str, argv: &Vec) -> Result<()> { // info!("boot: path: {:?}, argv: {:?}", path_str, argv); util::mpx_util::mpx_enable()?; @@ -87,7 +96,7 @@ fn do_boot(path_str: &str, argv: &Vec) -> Result<(), Error> { } // TODO: make sure do_run() cannot be called after do_boot() -fn do_run(host_tid: pid_t) -> Result { +fn do_run(host_tid: pid_t) -> Result { let exit_status = process::run_task(host_tid)?; // sync file system diff --git a/src/libos/src/errno.rs b/src/libos/src/errno.rs deleted file mode 100644 index cdf8717d..00000000 --- a/src/libos/src/errno.rs +++ /dev/null @@ -1,257 +0,0 @@ -use prelude::*; -use std::{convert, error, ffi, fmt}; - -// TODO: remove errno.h - -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Error { - pub errno: Errno, - pub desc: &'static str, -} - -impl Error { - pub fn new(errno: Errno, desc: &'static str) -> Error { - let ret = Error { errno, desc }; - ret - } -} - -impl convert::From<(Errno, &'static str)> for Error { - fn from(info: (Errno, &'static str)) -> Error { - Error::new(info.0, info.1) - } -} - -impl convert::From for Error { - fn from(info: std::io::Error) -> Error { - Error::new( - Errno::from_errno(info.raw_os_error().unwrap()), - "std::io::Error", - ) - } -} - -impl convert::From for Error { - fn from(info: std::ffi::NulError) -> Error { - Error::new(Errno::EINVAL, "std::ffi::NulError") - } -} - -impl error::Error for Error { - fn description(&self) -> &str { - self.desc - } - - fn cause(&self) -> Option<&error::Error> { - None - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Error: {} ({})", self.desc, self.errno) - } -} - -#[derive(Clone, Copy, Debug, PartialEq)] -#[repr(u8)] -pub enum Errno { - EUNDEF = 0, - EPERM = 1, - ENOENT = 2, - ESRCH = 3, - EINTR = 4, - EIO = 5, - ENXIO = 6, - E2BIG = 7, - ENOEXEC = 8, - EBADF = 9, - ECHILD = 10, - EAGAIN = 11, - ENOMEM = 12, - EACCES = 13, - EFAULT = 14, - ENOTBLK = 15, - EBUSY = 16, - EEXIST = 17, - EXDEV = 18, - ENODEV = 19, - ENOTDIR = 20, - EISDIR = 21, - EINVAL = 22, - ENFILE = 23, - EMFILE = 24, - ENOTTY = 25, - ETXTBSY = 26, - EFBIG = 27, - ENOSPC = 28, - ESPIPE = 29, - EROFS = 30, - EMLINK = 31, - EPIPE = 32, - EDOM = 33, - ERANGE = 34, - EDEADLK = 35, - ENAMETOOLONG = 36, - ENOLCK = 37, - ENOSYS = 38, - ENOTEMPTY = 39, - ELOOP = 40, - EWOULDBLOCK = 41, - ENOMSG = 42, - EIDRM = 43, - ECHRNG = 44, - EL2NSYNC = 45, - EL3HLT = 46, - EL3RST = 47, - ELNRNG = 48, - EUNATCH = 49, - ENOCSI = 50, - EL2HLT = 51, - EBADE = 52, - EBADR = 53, - EXFULL = 54, - ENOANO = 55, - EBADRQC = 56, - EBADSLT = 57, - EDEADLOCK = 58, - EBFONT = 59, - ENOSTR = 60, - ENODATA = 61, - ETIME = 62, - ENOSR = 63, - ENONET = 64, - ENOPKG = 65, - EREMOTE = 66, - ENOLINK = 67, - EADV = 68, - ESRMNT = 69, - ECOMM = 70, - EPROTO = 71, - EMULTIHOP = 72, - EDOTDOT = 73, - EBADMSG = 74, - EOVERFLOW = 75, - ENOTUNIQ = 76, - EBADFD = 77, - EREMCHG = 78, - ELIBACC = 79, - ELIBBAD = 80, - ELIBSCN = 81, - ELIBMAX = 82, - ELIBEXEC = 83, - EILSEQ = 84, - ERESTART = 85, - ESTRPIPE = 86, - EUSERS = 87, - ENOTSOCK = 88, - EDESTADDRREQ = 89, - EMSGSIZE = 90, - EPROTOTYPE = 91, - ENOPROTOOPT = 92, - EPROTONOSUPPORT = 93, - ESOCKTNOSUPPORT = 94, - EOPNOTSUPP = 95, - EPFNOSUPPORT = 96, - EAFNOSUPPORT = 97, - EADDRINUSE = 98, - EADDRNOTAVAIL = 99, - ENETDOWN = 100, - ENETUNREACH = 101, - ENETRESET = 102, - ECONNABORTED = 103, - ECONNRESET = 104, - ENOBUFS = 105, - EISCONN = 106, - ENOTCONN = 107, - ESHUTDOWN = 108, - ETOOMANYREFS = 109, - ETIMEDOUT = 110, - ECONNREFUSED = 111, - EHOSTDOWN = 112, - EHOSTUNREACH = 113, - EALREADY = 114, - EINPROGRESS = 115, - ESTALE = 116, - EUCLEAN = 117, - ENOTNAM = 118, - ENAVAIL = 119, - EISNAM = 120, - EREMOTEIO = 121, - EDQUOT = 122, - ENOMEDIUM = 123, - EMEDIUMTYPE = 124, - ECANCELED = 125, - ENOKEY = 126, - EKEYEXPIRED = 127, - EKEYREVOKED = 128, - EKEYREJECTED = 129, - EOWNERDEAD = 130, - ENOTRECOVERABLE = 131, - ERFKILL = 132, - EHWPOISON = 133, -} - -impl Errno { - pub fn as_retval(&self) -> i32 { - -(*self as i32) - } - pub fn from_errno(mut errno: i32) -> Self { - if errno < 0 || errno > 133 { - errno = 0; - } - unsafe { core::mem::transmute(errno as u8) } - } -} - -impl fmt::Display for Errno { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "errno = {}, \"{}\"", - *self as u32, - match *self { - Errno::EPERM => "Operation not permitted", - Errno::ENOENT => "No such file or directory", - Errno::ESRCH => "No such process", - Errno::EINTR => "Interrupted system call", - Errno::EIO => "I/O error", - Errno::ENXIO => "No such device or address", - Errno::E2BIG => "Argument list too long", - Errno::ENOEXEC => "Exec format error", - Errno::EBADF => "Bad file number", - Errno::ECHILD => "No child processes", - Errno::EAGAIN => "Try again", - Errno::ENOMEM => "Out of memory", - Errno::EACCES => "Permission denied", - Errno::EFAULT => "Bad address", - Errno::ENOTBLK => "Block device required", - Errno::EBUSY => "Device or resource busy", - Errno::EEXIST => "File exists", - Errno::EXDEV => "Cross-device link", - Errno::ENODEV => "No such device", - Errno::ENOTDIR => "Not a directory", - Errno::EISDIR => "Is a directory", - Errno::EINVAL => "Invalid argument", - Errno::ENFILE => "File table overflow", - Errno::EMFILE => "Too many open files", - Errno::ENOTTY => "Not a typewriter", - Errno::ETXTBSY => "Text file busy", - Errno::EFBIG => "File too large", - Errno::ENOSPC => "No space left on device", - Errno::ESPIPE => "Illegal seek", - Errno::EROFS => "Read-only file system", - Errno::EMLINK => "Too many links", - Errno::EPIPE => "Broken pipe", - Errno::EDOM => "Math argument out of domain of func", - Errno::ERANGE => "Math result not representable", - Errno::EDEADLK => "Resource deadlock would occur", - Errno::ENAMETOOLONG => "File name too long", - Errno::ENOLCK => "No record locks available", - Errno::ENOSYS => "Function not implemented", - Errno::ENOTEMPTY => "Directory not empty", - _ => "Unknown error", - }, - ) - } -} diff --git a/src/libos/src/error/backtrace.rs b/src/libos/src/error/backtrace.rs new file mode 100644 index 00000000..c45a3875 --- /dev/null +++ b/src/libos/src/error/backtrace.rs @@ -0,0 +1,65 @@ +use super::*; + +#[derive(Debug, Clone)] +pub struct ErrorBacktrace<'a> { + next_error: Option<&'a Error>, +} + +impl<'a> ErrorBacktrace<'a> { + fn new(last_error: &'a Error) -> ErrorBacktrace { + ErrorBacktrace { + next_error: Some(last_error), + } + } +} + +impl<'a> fmt::Display for ErrorBacktrace<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let error_strings: Vec = self.clone().map(|e| e.to_string()).collect(); + let error_backtrace = error_strings.join("\n Caused by "); + write!(f, "{}", error_backtrace) + } +} + +impl<'a> Iterator for ErrorBacktrace<'a> { + type Item = &'a Error; + + fn next(&mut self) -> Option<&'a Error> { + if let Some(this_error) = self.next_error { + self.next_error = this_error.get_cause().as_ref().map(|e| -> &Error { &e }); + return Some(this_error); + } + None + } +} + +impl Error { + pub fn cause_err(self, f: F) -> Error + where + F: FnOnce(&Error) -> Error, + { + let old_err = self; + let mut new_err = f(&old_err); + *new_err.get_cause_mut() = Some(Box::new(old_err)); + new_err + } + + pub fn backtrace(&self) -> ErrorBacktrace { + ErrorBacktrace::new(self) + } +} + +pub trait ResultExt { + fn cause_err(self, f: F) -> Result + where + F: FnOnce(&Error) -> Error; +} + +impl ResultExt for Result { + fn cause_err(self, f: F) -> Result + where + F: FnOnce(&Error) -> Error, + { + self.map_err(|old_e| old_e.cause_err(f)) + } +} diff --git a/src/libos/src/error/errno.rs b/src/libos/src/error/errno.rs new file mode 100644 index 00000000..ffcde387 --- /dev/null +++ b/src/libos/src/error/errno.rs @@ -0,0 +1,207 @@ +use super::*; + +/// POSIX errno +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(u8)] +pub enum Errno { + // Note: we don't define EUNDEF (=0) since a syscall cannot return 0 to + // indicate the occurance of an error + EPERM = 1, + ENOENT = 2, + ESRCH = 3, + EINTR = 4, + EIO = 5, + ENXIO = 6, + E2BIG = 7, + ENOEXEC = 8, + EBADF = 9, + ECHILD = 10, + EAGAIN = 11, + ENOMEM = 12, + EACCES = 13, + EFAULT = 14, + ENOTBLK = 15, + EBUSY = 16, + EEXIST = 17, + EXDEV = 18, + ENODEV = 19, + ENOTDIR = 20, + EISDIR = 21, + EINVAL = 22, + ENFILE = 23, + EMFILE = 24, + ENOTTY = 25, + ETXTBSY = 26, + EFBIG = 27, + ENOSPC = 28, + ESPIPE = 29, + EROFS = 30, + EMLINK = 31, + EPIPE = 32, + EDOM = 33, + ERANGE = 34, + EDEADLK = 35, + ENAMETOOLONG = 36, + ENOLCK = 37, + ENOSYS = 38, + ENOTEMPTY = 39, + ELOOP = 40, + EWOULDBLOCK = 41, + ENOMSG = 42, + EIDRM = 43, + ECHRNG = 44, + EL2NSYNC = 45, + EL3HLT = 46, + EL3RST = 47, + ELNRNG = 48, + EUNATCH = 49, + ENOCSI = 50, + EL2HLT = 51, + EBADE = 52, + EBADR = 53, + EXFULL = 54, + ENOANO = 55, + EBADRQC = 56, + EBADSLT = 57, + EDEADLOCK = 58, + EBFONT = 59, + ENOSTR = 60, + ENODATA = 61, + ETIME = 62, + ENOSR = 63, + ENONET = 64, + ENOPKG = 65, + EREMOTE = 66, + ENOLINK = 67, + EADV = 68, + ESRMNT = 69, + ECOMM = 70, + EPROTO = 71, + EMULTIHOP = 72, + EDOTDOT = 73, + EBADMSG = 74, + EOVERFLOW = 75, + ENOTUNIQ = 76, + EBADFD = 77, + EREMCHG = 78, + ELIBACC = 79, + ELIBBAD = 80, + ELIBSCN = 81, + ELIBMAX = 82, + ELIBEXEC = 83, + EILSEQ = 84, + ERESTART = 85, + ESTRPIPE = 86, + EUSERS = 87, + ENOTSOCK = 88, + EDESTADDRREQ = 89, + EMSGSIZE = 90, + EPROTOTYPE = 91, + ENOPROTOOPT = 92, + EPROTONOSUPPORT = 93, + ESOCKTNOSUPPORT = 94, + EOPNOTSUPP = 95, + EPFNOSUPPORT = 96, + EAFNOSUPPORT = 97, + EADDRINUSE = 98, + EADDRNOTAVAIL = 99, + ENETDOWN = 100, + ENETUNREACH = 101, + ENETRESET = 102, + ECONNABORTED = 103, + ECONNRESET = 104, + ENOBUFS = 105, + EISCONN = 106, + ENOTCONN = 107, + ESHUTDOWN = 108, + ETOOMANYREFS = 109, + ETIMEDOUT = 110, + ECONNREFUSED = 111, + EHOSTDOWN = 112, + EHOSTUNREACH = 113, + EALREADY = 114, + EINPROGRESS = 115, + ESTALE = 116, + EUCLEAN = 117, + ENOTNAM = 118, + ENAVAIL = 119, + EISNAM = 120, + EREMOTEIO = 121, + EDQUOT = 122, + ENOMEDIUM = 123, + EMEDIUMTYPE = 124, + ECANCELED = 125, + ENOKEY = 126, + EKEYEXPIRED = 127, + EKEYREVOKED = 128, + EKEYREJECTED = 129, + EOWNERDEAD = 130, + ENOTRECOVERABLE = 131, + ERFKILL = 132, + EHWPOISON = 133, + // Note: always keep the last item in sync with ERRNO_MAX +} +const ERRNO_MAX: u32 = Errno::EHWPOISON as u32; + +impl Errno { + pub(crate) fn as_str(&self) -> &'static str { + use self::Errno::*; + match *self { + EPERM => "Operation not permitted", + ENOENT => "No such file or directory", + ESRCH => "No such process", + EINTR => "Interrupted system call", + EIO => "I/O error", + ENXIO => "No such device or address", + E2BIG => "Argument list too long", + ENOEXEC => "Exec format error", + EBADF => "Bad file number", + ECHILD => "No child processes", + EAGAIN => "Try again", + ENOMEM => "Out of memory", + EACCES => "Permission denied", + EFAULT => "Bad address", + ENOTBLK => "Block device required", + EBUSY => "Device or resource busy", + EEXIST => "File exists", + EXDEV => "Cross-device link", + ENODEV => "No such device", + ENOTDIR => "Not a directory", + EISDIR => "Is a directory", + EINVAL => "Invalid argument", + ENFILE => "File table overflow", + EMFILE => "Too many open files", + ENOTTY => "Not a typewriter", + ETXTBSY => "Text file busy", + EFBIG => "File too large", + ENOSPC => "No space left on device", + ESPIPE => "Illegal seek", + EROFS => "Read-only file system", + EMLINK => "Too many links", + EPIPE => "Broken pipe", + EDOM => "Math argument out of domain of func", + ERANGE => "Math result not representable", + EDEADLK => "Resource deadlock would occur", + ENAMETOOLONG => "File name too long", + ENOLCK => "No record locks available", + ENOSYS => "Function not implemented", + ENOTEMPTY => "Directory not empty", + _ => "Unknown error", + } + } +} + +impl From for Errno { + fn from(mut raw_errno: u32) -> Self { + if raw_errno > ERRNO_MAX { + raw_errno = 0; + } + unsafe { core::mem::transmute(raw_errno as u8) } + } +} + +impl fmt::Display for Errno { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?} (#{}, {})", *self, *self as u32, self.as_str()) + } +} diff --git a/src/libos/src/error/error.rs b/src/libos/src/error/error.rs new file mode 100644 index 00000000..3951882d --- /dev/null +++ b/src/libos/src/error/error.rs @@ -0,0 +1,107 @@ +use super::*; + +#[derive(Debug)] +pub struct Error { + inner: Error__, + location: Option, + cause: Option>, +} + +#[derive(Debug)] +enum Error__ { + Embedded((Errno, &'static str)), + Boxed(Box), +} + +#[derive(Debug, Clone, Copy)] +pub struct ErrorLocation { + line: u32, + file: &'static str, +} + +impl Error { + pub fn embeded(inner: (Errno, &'static str), location: Option) -> Error { + Error { + inner: Error__::Embedded(inner), + location: location, + cause: None, + } + } + + pub fn boxed(inner: T, location: Option) -> Error + where + T: ToErrno + 'static, + { + Error { + inner: Error__::Boxed(Box::new(inner)), + location: location, + cause: None, + } + } + + pub fn errno(&self) -> Errno { + match &self.inner { + Error__::Embedded((errno, _)) => *errno, + Error__::Boxed(inner_error) => inner_error.errno(), + } + } + + pub fn get_cause_mut(&mut self) -> &mut Option> { + &mut self.cause + } + + pub fn get_cause(&self) -> &Option> { + &self.cause + } +} + +impl ErrorLocation { + pub fn new(file: &'static str, line: u32) -> ErrorLocation { + ErrorLocation { + file: file, + line: line, + } + } +} + +impl std::error::Error for Error { + fn description(&self) -> &str { + self.errno().as_str() + } + + fn cause(&self) -> Option<&dyn std::error::Error> { + self.cause.as_ref().map(|e| e as &dyn std::error::Error) + } + /* + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.cause + .as_ref() + .map(|e| e as &(dyn std::error::Error + 'static)) + } + */ +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.inner)?; + if let Some(location) = self.location { + write!(f, " {}", location)?; + } + Ok(()) + } +} + +impl fmt::Display for Error__ { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Error__::Embedded((errno, msg)) => write!(f, "{}: {}", errno, msg), + Error__::Boxed(inner_error) => write!(f, "{}: {}", inner_error.errno(), inner_error), + } + } +} + +impl fmt::Display for ErrorLocation { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "[line = {}, file = {}]", self.line, self.file) + } +} diff --git a/src/libos/src/error/mod.rs b/src/libos/src/error/mod.rs new file mode 100644 index 00000000..7fa192dd --- /dev/null +++ b/src/libos/src/error/mod.rs @@ -0,0 +1,53 @@ +use super::*; +use std::fmt; + +mod backtrace; +mod errno; +mod error; +mod to_errno; + +pub use self::backtrace::{ErrorBacktrace, ResultExt}; +pub use self::errno::Errno; +pub use self::errno::Errno::*; +pub use self::error::{Error, ErrorLocation}; +pub use self::to_errno::ToErrno; + +pub type Result = std::result::Result; + +macro_rules! errno { + ($errno_expr: expr, $error_msg: expr) => {{ + let inner_error = { + let errno: Errno = $errno_expr; + let msg: &'static str = $error_msg; + (errno, msg) + }; + let error = Error::embeded(inner_error, Some(ErrorLocation::new(file!(), line!()))); + error + }}; + ($error_expr: expr) => {{ + let inner_error = $error_expr; + let error = Error::boxed(inner_error, Some(ErrorLocation::new(file!(), line!()))); + error + }}; +} + +macro_rules! return_errno { + ($errno_expr: expr, $error_msg: expr) => {{ + return Err(errno!($errno_expr, $error_msg)); + }}; + ($error_expr: expr) => {{ + return Err(errno!($error_expr)); + }}; +} + +// return Err(errno) if libc return -1 +macro_rules! try_libc { + ($ret: expr) => {{ + let ret = unsafe { $ret }; + if ret == -1 { + let errno = unsafe { libc::errno() }; + return_errno!(Errno::from(errno as u32), "libc error"); + } + ret + }}; +} diff --git a/src/libos/src/error/to_errno.rs b/src/libos/src/error/to_errno.rs new file mode 100644 index 00000000..90735ae2 --- /dev/null +++ b/src/libos/src/error/to_errno.rs @@ -0,0 +1,100 @@ +use super::*; + +pub trait ToErrno: fmt::Display + fmt::Debug { + fn errno(&self) -> Errno; +} + +impl ToErrno for Errno { + fn errno(&self) -> Errno { + *self + } +} + +impl From for Error +where + T: ToErrno + 'static, +{ + fn from(t: T) -> Error { + Error::boxed(t, None) + } +} + +impl From for Errno { + fn from(kind: std::io::ErrorKind) -> Errno { + use std::io::ErrorKind::*; + match kind { + NotFound => ENOENT, + PermissionDenied => EPERM, + ConnectionRefused => ECONNREFUSED, + ConnectionReset => ECONNRESET, + ConnectionAborted => ECONNABORTED, + NotConnected => ENOTCONN, + AddrInUse => EADDRINUSE, + AddrNotAvailable => EADDRNOTAVAIL, + BrokenPipe => EPIPE, + AlreadyExists => EEXIST, + WouldBlock => EWOULDBLOCK, + InvalidInput => EINVAL, + InvalidData => EBADMSG, /* TODO: correct? */ + TimedOut => ETIMEDOUT, + Interrupted => EINTR, + WriteZero => EINVAL, + UnexpectedEof => EIO, + Other => EIO, + _ => EIO, + } + } +} + +impl ToErrno for std::io::Error { + fn errno(&self) -> Errno { + Errno::from(self.kind()) + } +} + +impl ToErrno for std::ffi::NulError { + fn errno(&self) -> Errno { + EINVAL + } +} + +impl ToErrno for std::num::ParseIntError { + fn errno(&self) -> Errno { + EINVAL + } +} + +impl ToErrno for serde_json::Error { + fn errno(&self) -> Errno { + EINVAL + } +} + +impl ToErrno for rcore_fs::vfs::FsError { + fn errno(&self) -> Errno { + use rcore_fs::vfs::FsError; + match *self { + FsError::NotSupported => ENOSYS, + FsError::NotFile => EISDIR, + FsError::IsDir => EISDIR, + FsError::NotDir => ENOTDIR, + FsError::EntryNotFound => ENOENT, + FsError::EntryExist => EEXIST, + FsError::NotSameFs => EXDEV, + FsError::InvalidParam => EINVAL, + FsError::NoDeviceSpace => ENOMEM, + FsError::DirRemoved => ENOENT, + FsError::DirNotEmpty => ENOTEMPTY, + FsError::WrongFs => EINVAL, + FsError::DeviceError => EIO, + FsError::SymLoop => ELOOP, + FsError::NoDevice => ENXIO, + FsError::IOCTLError => EINVAL, + FsError::Again => EAGAIN, + FsError::Busy => EBUSY, + FsError::WrProtected => EROFS, + FsError::NoIntegrity => EIO, + FsError::PermError => EPERM, + } + } +} diff --git a/src/libos/src/exception/cpuid.rs b/src/libos/src/exception/cpuid.rs index dbaa9049..2c829eec 100644 --- a/src/libos/src/exception/cpuid.rs +++ b/src/libos/src/exception/cpuid.rs @@ -167,11 +167,11 @@ impl CpuId { cpuid } - fn lookup_cpuid_from_cache(&self, cpuid_input: CpuIdInput) -> Result { + fn lookup_cpuid_from_cache(&self, cpuid_input: CpuIdInput) -> Result { self.cache .lookup(&cpuid_input) .map(|result| result.clone()) - .ok_or_else(|| Error::new(Errno::ENOENT, "cpuid_result not found")) + .ok_or_else(|| errno!(ENOENT, "cpuid_result not found")) } pub fn get_max_basic_leaf(&self) -> u32 { diff --git a/src/libos/src/fs/access.rs b/src/libos/src/fs/access.rs index 201c6864..1d7eaa5f 100644 --- a/src/libos/src/fs/access.rs +++ b/src/libos/src/fs/access.rs @@ -12,8 +12,8 @@ bitflags! { } impl AccessModes { - pub fn from_u32(bits: u32) -> Result { - AccessModes::from_bits(bits).ok_or_else(|| Error::new(Errno::EINVAL, "invalid mode")) + pub fn from_u32(bits: u32) -> Result { + AccessModes::from_bits(bits).ok_or_else(|| errno!(EINVAL, "invalid mode")) } } @@ -25,8 +25,8 @@ bitflags! { } impl AccessFlags { - pub fn from_u32(bits: u32) -> Result { - AccessFlags::from_bits(bits).ok_or_else(|| Error::new(Errno::EINVAL, "invalid flags")) + pub fn from_u32(bits: u32) -> Result { + AccessFlags::from_bits(bits).ok_or_else(|| errno!(EINVAL, "invalid flags")) } } @@ -37,19 +37,19 @@ pub fn do_faccessat( path: &str, mode: AccessModes, flags: AccessFlags, -) -> Result<(), Error> { +) -> Result<()> { info!( "faccessat: dirfd: {:?}, path: {:?}, mode: {:?}, flags: {:?}", dirfd, path, mode, flags ); match dirfd { // TODO: handle dirfd - Some(dirfd) => errno!(ENOSYS, "cannot accept dirfd"), + Some(dirfd) => return_errno!(ENOSYS, "cannot accept dirfd"), None => do_access(path, mode), } } -pub fn do_access(path: &str, mode: AccessModes) -> Result<(), Error> { +pub fn do_access(path: &str, mode: AccessModes) -> Result<()> { info!("access: path: {:?}, mode: {:?}", path, mode); let current_ref = process::get_current(); let mut current = current_ref.lock().unwrap(); diff --git a/src/libos/src/fs/dev_null.rs b/src/libos/src/fs/dev_null.rs index 6a3498d9..d5cb3380 100644 --- a/src/libos/src/fs/dev_null.rs +++ b/src/libos/src/fs/dev_null.rs @@ -4,52 +4,52 @@ use super::*; pub struct DevNull; impl File for DevNull { - fn write(&self, _buf: &[u8]) -> Result { + fn write(&self, _buf: &[u8]) -> Result { Ok(_buf.len()) } - fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result { + fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result { Ok(_buf.len()) } - fn writev(&self, bufs: &[&[u8]]) -> Result { + fn writev(&self, bufs: &[&[u8]]) -> Result { Ok(bufs.iter().map(|buf| buf.len()).sum()) } - fn read(&self, _buf: &mut [u8]) -> Result { - errno!(EINVAL, "device not support reads") + fn read(&self, _buf: &mut [u8]) -> Result { + return_errno!(EINVAL, "device not support reads") } - fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result { - errno!(EINVAL, "device not support reads") + fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result { + return_errno!(EINVAL, "device not support reads") } - fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { - errno!(EINVAL, "device not support reads") + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { + return_errno!(EINVAL, "device not support reads") } - fn seek(&self, pos: SeekFrom) -> Result { - errno!(EINVAL, "device not support seeks") + fn seek(&self, pos: SeekFrom) -> Result { + return_errno!(EINVAL, "device not support seeks") } - fn metadata(&self) -> Result { + fn metadata(&self) -> Result { unimplemented!() } - fn set_len(&self, len: u64) -> Result<(), Error> { - errno!(EINVAL, "device not support resizing") + fn set_len(&self, len: u64) -> Result<()> { + return_errno!(EINVAL, "device not support resizing") } - fn sync_all(&self) -> Result<(), Error> { + fn sync_all(&self) -> Result<()> { Ok(()) } - fn sync_data(&self) -> Result<(), Error> { + fn sync_data(&self) -> Result<()> { Ok(()) } - fn read_entry(&self) -> Result { - errno!(ENOTDIR, "device is not a directory") + fn read_entry(&self) -> Result { + return_errno!(ENOTDIR, "device is not a directory") } fn as_any(&self) -> &Any { diff --git a/src/libos/src/fs/dev_random.rs b/src/libos/src/fs/dev_random.rs index cfe9f96f..5ae9c382 100644 --- a/src/libos/src/fs/dev_random.rs +++ b/src/libos/src/fs/dev_random.rs @@ -8,21 +8,21 @@ extern "C" { } impl File for DevRandom { - fn read(&self, _buf: &mut [u8]) -> Result { + fn read(&self, _buf: &mut [u8]) -> Result { let buf = _buf.as_mut_ptr(); let size = _buf.len(); let status = unsafe { sgx_read_rand(buf, size) }; if status != sgx_status_t::SGX_SUCCESS { - return errno!(EAGAIN, "failed to get random number from sgx"); + return_errno!(EAGAIN, "failed to get random number from sgx"); } Ok(size) } - fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result { + fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result { self.read(_buf) } - fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { let mut total_nbytes = 0; for buf in bufs { match self.read(buf) { @@ -41,40 +41,40 @@ impl File for DevRandom { Ok(total_nbytes) } - fn write(&self, _buf: &[u8]) -> Result { - errno!(EINVAL, "device not support writes") + fn write(&self, _buf: &[u8]) -> Result { + return_errno!(EINVAL, "device not support writes") } - fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result { - errno!(EINVAL, "device not support writes") + fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result { + return_errno!(EINVAL, "device not support writes") } - fn writev(&self, bufs: &[&[u8]]) -> Result { - errno!(EINVAL, "device not support writes") + fn writev(&self, bufs: &[&[u8]]) -> Result { + return_errno!(EINVAL, "device not support writes") } - fn seek(&self, pos: SeekFrom) -> Result { - errno!(EINVAL, "device not support seeks") + fn seek(&self, pos: SeekFrom) -> Result { + return_errno!(EINVAL, "device not support seeks") } - fn metadata(&self) -> Result { + fn metadata(&self) -> Result { unimplemented!() } - fn set_len(&self, len: u64) -> Result<(), Error> { - errno!(EINVAL, "device not support resizing") + fn set_len(&self, len: u64) -> Result<()> { + return_errno!(EINVAL, "device not support resizing") } - fn sync_all(&self) -> Result<(), Error> { + fn sync_all(&self) -> Result<()> { Ok(()) } - fn sync_data(&self) -> Result<(), Error> { + fn sync_data(&self) -> Result<()> { Ok(()) } - fn read_entry(&self) -> Result { - errno!(ENOTDIR, "device is not a directory") + fn read_entry(&self) -> Result { + return_errno!(ENOTDIR, "device is not a directory") } fn as_any(&self) -> &Any { diff --git a/src/libos/src/fs/dev_zero.rs b/src/libos/src/fs/dev_zero.rs index db7bcc70..64d4ca53 100644 --- a/src/libos/src/fs/dev_zero.rs +++ b/src/libos/src/fs/dev_zero.rs @@ -4,18 +4,18 @@ use super::*; pub struct DevZero; impl File for DevZero { - fn read(&self, _buf: &mut [u8]) -> Result { + fn read(&self, _buf: &mut [u8]) -> Result { for b in _buf.iter_mut() { *b = 0; } Ok(_buf.len()) } - fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result { + fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result { self.read(_buf) } - fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { let mut total_nbytes = 0; for buf in bufs { total_nbytes += self.read(buf)?; @@ -23,40 +23,40 @@ impl File for DevZero { Ok(total_nbytes) } - fn write(&self, _buf: &[u8]) -> Result { - errno!(EINVAL, "device not support writes") + fn write(&self, _buf: &[u8]) -> Result { + return_errno!(EINVAL, "device not support writes") } - fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result { - errno!(EINVAL, "device not support writes") + fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result { + return_errno!(EINVAL, "device not support writes") } - fn writev(&self, bufs: &[&[u8]]) -> Result { - errno!(EINVAL, "device not support writes") + fn writev(&self, bufs: &[&[u8]]) -> Result { + return_errno!(EINVAL, "device not support writes") } - fn seek(&self, pos: SeekFrom) -> Result { - errno!(EINVAL, "device not support seeks") + fn seek(&self, pos: SeekFrom) -> Result { + return_errno!(EINVAL, "device not support seeks") } - fn metadata(&self) -> Result { + fn metadata(&self) -> Result { unimplemented!() } - fn set_len(&self, len: u64) -> Result<(), Error> { - errno!(EINVAL, "device not support resizing") + fn set_len(&self, len: u64) -> Result<()> { + return_errno!(EINVAL, "device not support resizing") } - fn sync_all(&self) -> Result<(), Error> { + fn sync_all(&self) -> Result<()> { Ok(()) } - fn sync_data(&self) -> Result<(), Error> { + fn sync_data(&self) -> Result<()> { Ok(()) } - fn read_entry(&self) -> Result { - errno!(ENOTDIR, "device is not a directory") + fn read_entry(&self) -> Result { + return_errno!(ENOTDIR, "device is not a directory") } fn as_any(&self) -> &Any { diff --git a/src/libos/src/fs/file.rs b/src/libos/src/fs/file.rs index 62c52762..c7b4cbf0 100644 --- a/src/libos/src/fs/file.rs +++ b/src/libos/src/fs/file.rs @@ -5,18 +5,18 @@ use std::fmt; use std::io::SeekFrom; pub trait File: Debug + Sync + Send + Any { - fn read(&self, buf: &mut [u8]) -> Result; - fn write(&self, buf: &[u8]) -> Result; - fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result; - fn write_at(&self, offset: usize, buf: &[u8]) -> Result; - fn readv(&self, bufs: &mut [&mut [u8]]) -> Result; - fn writev(&self, bufs: &[&[u8]]) -> Result; - fn seek(&self, pos: SeekFrom) -> Result; - fn metadata(&self) -> Result; - fn set_len(&self, len: u64) -> Result<(), Error>; - fn sync_all(&self) -> Result<(), Error>; - fn sync_data(&self) -> Result<(), Error>; - fn read_entry(&self) -> Result; + fn read(&self, buf: &mut [u8]) -> Result; + fn write(&self, buf: &[u8]) -> Result; + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result; + fn write_at(&self, offset: usize, buf: &[u8]) -> Result; + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result; + fn writev(&self, bufs: &[&[u8]]) -> Result; + fn seek(&self, pos: SeekFrom) -> Result; + fn metadata(&self) -> Result; + fn set_len(&self, len: u64) -> Result<()>; + fn sync_all(&self) -> Result<()>; + fn sync_data(&self) -> Result<()>; + fn read_entry(&self) -> Result; fn as_any(&self) -> &Any; } @@ -34,9 +34,9 @@ impl SgxFile { is_readable: bool, is_writable: bool, is_append: bool, - ) -> Result { + ) -> Result { if !is_readable && !is_writable { - return errno!(EINVAL, "Invalid permissions"); + return_errno!(EINVAL, "Invalid permissions"); } Ok(SgxFile { @@ -52,67 +52,67 @@ impl SgxFile { } impl File for SgxFile { - fn read(&self, buf: &mut [u8]) -> Result { + fn read(&self, buf: &mut [u8]) -> Result { let mut inner_guard = self.inner.lock().unwrap(); let inner = inner_guard.borrow_mut(); inner.read(buf) } - fn write(&self, buf: &[u8]) -> Result { + fn write(&self, buf: &[u8]) -> Result { let mut inner_guard = self.inner.lock().unwrap(); let inner = inner_guard.borrow_mut(); inner.write(buf) } - fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { let mut inner_guard = self.inner.lock().unwrap(); let inner = inner_guard.borrow_mut(); inner.seek(SeekFrom::Start(offset as u64))?; inner.read(buf) } - fn write_at(&self, offset: usize, buf: &[u8]) -> Result { + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { let mut inner_guard = self.inner.lock().unwrap(); let inner = inner_guard.borrow_mut(); inner.seek(SeekFrom::Start(offset as u64))?; inner.write(buf) } - fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { let mut inner_guard = self.inner.lock().unwrap(); let inner = inner_guard.borrow_mut(); inner.readv(bufs) } - fn writev(&self, bufs: &[&[u8]]) -> Result { + fn writev(&self, bufs: &[&[u8]]) -> Result { let mut inner_guard = self.inner.lock().unwrap(); let inner = inner_guard.borrow_mut(); inner.writev(bufs) } - fn seek(&self, pos: SeekFrom) -> Result { + fn seek(&self, pos: SeekFrom) -> Result { let mut inner_guard = self.inner.lock().unwrap(); let inner = inner_guard.borrow_mut(); inner.seek(pos) } - fn metadata(&self) -> Result { + fn metadata(&self) -> Result { unimplemented!() } - fn set_len(&self, len: u64) -> Result<(), Error> { + fn set_len(&self, len: u64) -> Result<()> { unimplemented!() } - fn sync_all(&self) -> Result<(), Error> { + fn sync_all(&self) -> Result<()> { unimplemented!() } - fn sync_data(&self) -> Result<(), Error> { + fn sync_data(&self) -> Result<()> { unimplemented!() } - fn read_entry(&self) -> Result { + fn read_entry(&self) -> Result { unimplemented!() } @@ -133,9 +133,9 @@ struct SgxFileInner { } impl SgxFileInner { - pub fn write(&mut self, buf: &[u8]) -> Result { + pub fn write(&mut self, buf: &[u8]) -> Result { if !self.is_writable { - return errno!(EINVAL, "File not writable"); + return_errno!(EINVAL, "File not writable"); } let mut file_guard = self.file.lock().unwrap(); @@ -147,13 +147,9 @@ impl SgxFileInner { SeekFrom::End(0) }; // TODO: recover from error - file.seek(seek_pos) - .map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?; + file.seek(seek_pos).map_err(|e| errno!(e))?; - let write_len = { - file.write(buf) - .map_err(|e| Error::new(Errno::EINVAL, "Failed to write"))? - }; + let write_len = { file.write(buf).map_err(|e| errno!(e))? }; if !self.is_append { self.pos += write_len; @@ -161,28 +157,24 @@ impl SgxFileInner { Ok(write_len) } - pub fn read(&mut self, buf: &mut [u8]) -> Result { + pub fn read(&mut self, buf: &mut [u8]) -> Result { if !self.is_readable { - return errno!(EINVAL, "File not readable"); + return_errno!(EINVAL, "File not readable"); } let mut file_guard = self.file.lock().unwrap(); let file = file_guard.borrow_mut(); let seek_pos = SeekFrom::Start(self.pos as u64); - file.seek(seek_pos) - .map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?; + file.seek(seek_pos).map_err(|e| errno!(e))?; - let read_len = { - file.read(buf) - .map_err(|e| Error::new(Errno::EINVAL, "Failed to write"))? - }; + let read_len = { file.read(buf).map_err(|e| errno!(e))? }; self.pos += read_len; Ok(read_len) } - pub fn seek(&mut self, pos: SeekFrom) -> Result { + pub fn seek(&mut self, pos: SeekFrom) -> Result { let mut file_guard = self.file.lock().unwrap(); let file = file_guard.borrow_mut(); @@ -196,23 +188,20 @@ impl SgxFileInner { let backward_offset = (-relative_offset) as usize; if self.pos < backward_offset { // underflow - return errno!(EINVAL, "Invalid seek position"); + return_errno!(EINVAL, "Invalid seek position"); } SeekFrom::Start((self.pos - backward_offset) as u64) } } }; - self.pos = file - .seek(pos) - .map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))? - as usize; + self.pos = file.seek(pos).map_err(|e| errno!(e))? as usize; Ok(self.pos as off_t) } - pub fn writev(&mut self, bufs: &[&[u8]]) -> Result { + pub fn writev(&mut self, bufs: &[&[u8]]) -> Result { if !self.is_writable { - return errno!(EINVAL, "File not writable"); + return_errno!(EINVAL, "File not writable"); } let mut file_guard = self.file.lock().unwrap(); @@ -223,8 +212,7 @@ impl SgxFileInner { } else { SeekFrom::End(0) }; - file.seek(seek_pos) - .map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?; + file.seek(seek_pos).map_err(|e| errno!(e))?; let mut total_bytes = 0; for buf in bufs { @@ -238,7 +226,7 @@ impl SgxFileInner { Err(e) => { match total_bytes { // a complete failure - 0 => return errno!(EINVAL, "Failed to write"), + 0 => return_errno!(EINVAL, "Failed to write"), // a partially failure _ => break, } @@ -250,17 +238,16 @@ impl SgxFileInner { Ok(total_bytes) } - fn readv(&mut self, bufs: &mut [&mut [u8]]) -> Result { + fn readv(&mut self, bufs: &mut [&mut [u8]]) -> Result { if !self.is_readable { - return errno!(EINVAL, "File not readable"); + return_errno!(EINVAL, "File not readable"); } let mut file_guard = self.file.lock().unwrap(); let file = file_guard.borrow_mut(); let seek_pos = SeekFrom::Start(self.pos as u64); - file.seek(seek_pos) - .map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?; + file.seek(seek_pos).map_err(|e| errno!(e))?; let mut total_bytes = 0; for buf in bufs { @@ -274,7 +261,7 @@ impl SgxFileInner { Err(e) => { match total_bytes { // a complete failure - 0 => return errno!(EINVAL, "Failed to write"), + 0 => return_errno!(EINVAL, "Failed to write"), // a partially failure _ => break, } @@ -309,33 +296,28 @@ impl StdoutFile { } impl File for StdoutFile { - fn read(&self, buf: &mut [u8]) -> Result { - errno!(EBADF, "Stdout does not support read") + fn read(&self, buf: &mut [u8]) -> Result { + return_errno!(EBADF, "Stdout does not support read") } - fn write(&self, buf: &[u8]) -> Result { - let write_len = { - self.inner - .lock() - .write(buf) - .map_err(|e| (Errno::EINVAL, "Failed to write"))? - }; + fn write(&self, buf: &[u8]) -> Result { + let write_len = { self.inner.lock().write(buf).map_err(|e| errno!(e))? }; Ok(write_len) } - fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result { + fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result { self.read(buf) } - fn write_at(&self, _offset: usize, buf: &[u8]) -> Result { + fn write_at(&self, _offset: usize, buf: &[u8]) -> Result { self.write(buf) } - fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { - errno!(EBADF, "Stdout does not support read") + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { + return_errno!(EBADF, "Stdout does not support read") } - fn writev(&self, bufs: &[&[u8]]) -> Result { + fn writev(&self, bufs: &[&[u8]]) -> Result { let mut guard = self.inner.lock(); let mut total_bytes = 0; for buf in bufs { @@ -349,7 +331,7 @@ impl File for StdoutFile { Err(e) => { match total_bytes { // a complete failure - 0 => return errno!(EINVAL, "Failed to write"), + 0 => return_errno!(EINVAL, "Failed to write"), // a partially failure _ => break, } @@ -359,11 +341,11 @@ impl File for StdoutFile { Ok(total_bytes) } - fn seek(&self, seek_pos: SeekFrom) -> Result { - errno!(ESPIPE, "Stdout does not support seek") + fn seek(&self, seek_pos: SeekFrom) -> Result { + return_errno!(ESPIPE, "Stdout does not support seek") } - fn metadata(&self) -> Result { + fn metadata(&self) -> Result { Ok(Metadata { dev: 0, inode: 0, @@ -382,21 +364,21 @@ impl File for StdoutFile { }) } - fn set_len(&self, _len: u64) -> Result<(), Error> { - errno!(EINVAL, "Stdout does not support set_len") + fn set_len(&self, _len: u64) -> Result<()> { + return_errno!(EINVAL, "Stdout does not support set_len") } - fn sync_all(&self) -> Result<(), Error> { + fn sync_all(&self) -> Result<()> { self.sync_data() } - fn sync_data(&self) -> Result<(), Error> { + fn sync_data(&self) -> Result<()> { self.inner.lock().flush()?; Ok(()) } - fn read_entry(&self) -> Result { - errno!(ENOTDIR, "Stdout does not support read_entry") + fn read_entry(&self) -> Result { + return_errno!(ENOTDIR, "Stdout does not support read_entry") } fn as_any(&self) -> &Any { @@ -426,29 +408,24 @@ impl StdinFile { } impl File for StdinFile { - fn read(&self, buf: &mut [u8]) -> Result { - let read_len = { - self.inner - .lock() - .read(buf) - .map_err(|e| (Errno::EINVAL, "Failed to read"))? - }; + fn read(&self, buf: &mut [u8]) -> Result { + let read_len = { self.inner.lock().read(buf).map_err(|e| errno!(e))? }; Ok(read_len) } - fn write(&self, buf: &[u8]) -> Result { - errno!(EBADF, "Stdin does not support write") + fn write(&self, buf: &[u8]) -> Result { + return_errno!(EBADF, "Stdin does not support write") } - fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { unimplemented!() } - fn write_at(&self, offset: usize, buf: &[u8]) -> Result { + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { unimplemented!() } - fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { let mut guard = self.inner.lock(); let mut total_bytes = 0; for buf in bufs { @@ -462,7 +439,7 @@ impl File for StdinFile { Err(e) => { match total_bytes { // a complete failure - 0 => return errno!(EINVAL, "Failed to write"), + 0 => return_errno!(EINVAL, "Failed to write"), // a partially failure _ => break, } @@ -472,15 +449,15 @@ impl File for StdinFile { Ok(total_bytes) } - fn writev(&self, bufs: &[&[u8]]) -> Result { - errno!(EBADF, "Stdin does not support write") + fn writev(&self, bufs: &[&[u8]]) -> Result { + return_errno!(EBADF, "Stdin does not support write") } - fn seek(&self, pos: SeekFrom) -> Result { - errno!(ESPIPE, "Stdin does not support seek") + fn seek(&self, pos: SeekFrom) -> Result { + return_errno!(ESPIPE, "Stdin does not support seek") } - fn metadata(&self) -> Result { + fn metadata(&self) -> Result { Ok(Metadata { dev: 0, inode: 0, @@ -499,20 +476,20 @@ impl File for StdinFile { }) } - fn set_len(&self, _len: u64) -> Result<(), Error> { - errno!(EINVAL, "Stdin does not support set_len") + fn set_len(&self, _len: u64) -> Result<()> { + return_errno!(EINVAL, "Stdin does not support set_len") } - fn sync_all(&self) -> Result<(), Error> { + fn sync_all(&self) -> Result<()> { self.sync_data() } - fn sync_data(&self) -> Result<(), Error> { + fn sync_data(&self) -> Result<()> { Ok(()) } - fn read_entry(&self) -> Result { - errno!(ENOTDIR, "Stdin does not support read_entry") + fn read_entry(&self) -> Result { + return_errno!(ENOTDIR, "Stdin does not support read_entry") } fn as_any(&self) -> &Any { diff --git a/src/libos/src/fs/file_table.rs b/src/libos/src/fs/file_table.rs index be80ba4b..04813aa4 100644 --- a/src/libos/src/fs/file_table.rs +++ b/src/libos/src/fs/file_table.rs @@ -24,7 +24,7 @@ impl FileTable { fd: FileDesc, min_fd: FileDesc, close_on_spawn: bool, - ) -> Result { + ) -> Result { let file_ref = self.get(fd)?; let min_fd = min_fd as usize; @@ -86,38 +86,38 @@ impl FileTable { } } - pub fn get(&self, fd: FileDesc) -> Result { + pub fn get(&self, fd: FileDesc) -> Result { let entry = self.get_entry(fd)?; Ok(entry.file.clone()) } - pub fn get_entry(&self, fd: FileDesc) -> Result<&FileTableEntry, Error> { + pub fn get_entry(&self, fd: FileDesc) -> Result<&FileTableEntry> { if fd as usize >= self.table.len() { - return errno!(EBADF, "Invalid file descriptor"); + return_errno!(EBADF, "Invalid file descriptor"); } let table = &self.table; match table[fd as usize].as_ref() { Some(table_entry) => Ok(table_entry), - None => errno!(EBADF, "Invalid file descriptor"), + None => return_errno!(EBADF, "Invalid file descriptor"), } } - pub fn get_entry_mut(&mut self, fd: FileDesc) -> Result<&mut FileTableEntry, Error> { + pub fn get_entry_mut(&mut self, fd: FileDesc) -> Result<&mut FileTableEntry> { if fd as usize >= self.table.len() { - return errno!(EBADF, "Invalid file descriptor"); + return_errno!(EBADF, "Invalid file descriptor"); } let table = &mut self.table; match table[fd as usize].as_mut() { Some(table_entry) => Ok(table_entry), - None => errno!(EBADF, "Invalid file descriptor"), + None => return_errno!(EBADF, "Invalid file descriptor"), } } - pub fn del(&mut self, fd: FileDesc) -> Result { + pub fn del(&mut self, fd: FileDesc) -> Result { if fd as usize >= self.table.len() { - return errno!(EBADF, "Invalid file descriptor"); + return_errno!(EBADF, "Invalid file descriptor"); } let mut del_table_entry = None; @@ -128,7 +128,7 @@ impl FileTable { self.num_fds -= 1; Ok(del_table_entry.file) } - None => errno!(EBADF, "Invalid file descriptor"), + None => return_errno!(EBADF, "Invalid file descriptor"), } } diff --git a/src/libos/src/fs/inode_file.rs b/src/libos/src/fs/inode_file.rs index 1db49291..b932df0e 100644 --- a/src/libos/src/fs/inode_file.rs +++ b/src/libos/src/fs/inode_file.rs @@ -18,19 +18,19 @@ pub struct OpenOptions { } impl File for INodeFile { - fn read(&self, buf: &mut [u8]) -> Result { + fn read(&self, buf: &mut [u8]) -> Result { if !self.options.read { - return errno!(EBADF, "File not readable"); + return_errno!(EBADF, "File not readable"); } let mut offset = self.offset.lock().unwrap(); - let len = self.inode.read_at(*offset, buf)?; + let len = self.inode.read_at(*offset, buf).map_err(|e| errno!(e))?; *offset += len; Ok(len) } - fn write(&self, buf: &[u8]) -> Result { + fn write(&self, buf: &[u8]) -> Result { if !self.options.write { - return errno!(EBADF, "File not writable"); + return_errno!(EBADF, "File not writable"); } let mut offset = self.offset.lock().unwrap(); if self.options.append { @@ -42,25 +42,25 @@ impl File for INodeFile { Ok(len) } - fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { if !self.options.read { - return errno!(EBADF, "File not readable"); + return_errno!(EBADF, "File not readable"); } let len = self.inode.read_at(offset, buf)?; Ok(len) } - fn write_at(&self, offset: usize, buf: &[u8]) -> Result { + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { if !self.options.write { - return errno!(EBADF, "File not writable"); + return_errno!(EBADF, "File not writable"); } let len = self.inode.write_at(offset, buf)?; Ok(len) } - fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { if !self.options.read { - return errno!(EBADF, "File not readable"); + return_errno!(EBADF, "File not readable"); } let mut offset = self.offset.lock().unwrap(); let mut total_len = 0; @@ -77,9 +77,9 @@ impl File for INodeFile { Ok(total_len) } - fn writev(&self, bufs: &[&[u8]]) -> Result { + fn writev(&self, bufs: &[&[u8]]) -> Result { if !self.options.write { - return errno!(EBADF, "File not writable"); + return_errno!(EBADF, "File not writable"); } let mut offset = self.offset.lock().unwrap(); if self.options.append { @@ -100,7 +100,7 @@ impl File for INodeFile { Ok(total_len) } - fn seek(&self, pos: SeekFrom) -> Result { + fn seek(&self, pos: SeekFrom) -> Result { let mut offset = self.offset.lock().unwrap(); *offset = match pos { SeekFrom::Start(off) => off as usize, @@ -110,32 +110,32 @@ impl File for INodeFile { Ok(*offset as i64) } - fn metadata(&self) -> Result { + fn metadata(&self) -> Result { let metadata = self.inode.metadata()?; Ok(metadata) } - fn set_len(&self, len: u64) -> Result<(), Error> { + fn set_len(&self, len: u64) -> Result<()> { if !self.options.write { - return errno!(EBADF, "File not writable. Can't set len."); + return_errno!(EBADF, "File not writable. Can't set len."); } self.inode.resize(len as usize)?; Ok(()) } - fn sync_all(&self) -> Result<(), Error> { + fn sync_all(&self) -> Result<()> { self.inode.sync_all()?; Ok(()) } - fn sync_data(&self) -> Result<(), Error> { + fn sync_data(&self) -> Result<()> { self.inode.sync_data()?; Ok(()) } - fn read_entry(&self) -> Result { + fn read_entry(&self) -> Result { if !self.options.read { - return errno!(EBADF, "File not readable. Can't read entry."); + return_errno!(EBADF, "File not readable. Can't read entry."); } let mut offset = self.offset.lock().unwrap(); let name = self.inode.get_entry(*offset)?; @@ -149,12 +149,12 @@ impl File for INodeFile { } impl INodeFile { - pub fn open(inode: Arc, options: OpenOptions) -> Result { + pub fn open(inode: Arc, options: OpenOptions) -> Result { if (options.read && !inode.allow_read()?) { - return errno!(EBADF, "File not readable"); + return_errno!(EBADF, "File not readable"); } if (options.write && !inode.allow_write()?) { - return errno!(EBADF, "File not writable"); + return_errno!(EBADF, "File not writable"); } Ok(INodeFile { @@ -165,36 +165,6 @@ impl INodeFile { } } -/// Convert VFS Error to libc error code -impl From for Error { - fn from(error: FsError) -> Self { - let errno = match error { - FsError::NotSupported => ENOSYS, - FsError::NotFile => EISDIR, - FsError::IsDir => EISDIR, - FsError::NotDir => ENOTDIR, - FsError::EntryNotFound => ENOENT, - FsError::EntryExist => EEXIST, - FsError::NotSameFs => EXDEV, - FsError::InvalidParam => EINVAL, - FsError::NoDeviceSpace => ENOMEM, - FsError::DirRemoved => ENOENT, - FsError::DirNotEmpty => ENOTEMPTY, - FsError::WrongFs => EINVAL, - FsError::DeviceError => EIO, - FsError::SymLoop => ELOOP, - FsError::NoDevice => ENXIO, - FsError::IOCTLError => EINVAL, - FsError::Again => EAGAIN, - FsError::Busy => EBUSY, - FsError::WrProtected => EROFS, - FsError::NoIntegrity => EROFS, - FsError::PermError => EPERM, - }; - Error::new(errno, "") - } -} - impl Debug for INodeFile { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( @@ -207,13 +177,13 @@ impl Debug for INodeFile { } pub trait INodeExt { - fn read_as_vec(&self) -> Result, Error>; - fn allow_write(&self) -> Result; - fn allow_read(&self) -> Result; + fn read_as_vec(&self) -> Result>; + fn allow_write(&self) -> Result; + fn allow_read(&self) -> Result; } impl INodeExt for INode { - fn read_as_vec(&self) -> Result, Error> { + fn read_as_vec(&self) -> Result> { let size = self.metadata()?.size; let mut buf = Vec::with_capacity(size); unsafe { @@ -223,14 +193,14 @@ impl INodeExt for INode { Ok(buf) } - fn allow_write(&self) -> Result { + fn allow_write(&self) -> Result { let info = self.metadata()?; let perms = info.mode as u32; let writable = (perms & S_IWUSR) == S_IWUSR; Ok(writable) } - fn allow_read(&self) -> Result { + fn allow_read(&self) -> Result { let info = self.metadata()?; let perms = info.mode as u32; let readable = (perms & S_IRUSR) == S_IRUSR; diff --git a/src/libos/src/fs/io_multiplexing.rs b/src/libos/src/fs/io_multiplexing.rs index 811ad9ef..4e45153e 100644 --- a/src/libos/src/fs/io_multiplexing.rs +++ b/src/libos/src/fs/io_multiplexing.rs @@ -13,7 +13,7 @@ pub fn do_select( writefds: &mut libc::fd_set, exceptfds: &mut libc::fd_set, timeout: Option, -) -> Result { +) -> Result { info!("select: nfds: {}", nfds); // convert libos fd to Linux fd let mut host_to_libos_fd = [0; libc::FD_SETSIZE]; @@ -108,7 +108,7 @@ pub fn do_select( Ok(ret as usize) } -pub fn do_poll(polls: &mut [libc::pollfd], timeout: c_int) -> Result { +pub fn do_poll(polls: &mut [libc::pollfd], timeout: c_int) -> Result { info!( "poll: {:?}, timeout: {}", polls.iter().map(|p| p.fd).collect::>(), @@ -143,7 +143,7 @@ pub fn do_poll(polls: &mut [libc::pollfd], timeout: c_int) -> Result Result Result { +pub fn do_epoll_create1(flags: c_int) -> Result { info!("epoll_create1: flags: {}", flags); let epoll = EpollFile::new()?; @@ -177,7 +177,7 @@ pub fn do_epoll_ctl( op: c_int, fd: FileDesc, event: *const libc::epoll_event, -) -> Result<(), Error> { +) -> Result<()> { info!("epoll_ctl: epfd: {}, op: {:?}, fd: {}", epfd, op, fd); let current_ref = process::get_current(); @@ -196,7 +196,7 @@ pub fn do_epoll_wait( epfd: FileDesc, events: &mut [libc::epoll_event], timeout: c_int, -) -> Result { +) -> Result { info!( "epoll_wait: epfd: {}, len: {:?}, timeout: {}", epfd, @@ -245,7 +245,7 @@ pub struct EpollFile { } impl EpollFile { - pub fn new() -> Result { + pub fn new() -> Result { Ok(Self { inner: SgxMutex::new(EpollFileInner::new()?), }) @@ -259,7 +259,7 @@ struct EpollFileInner { // FIXME: What if a Linux fd is closed but still in an epoll? impl EpollFileInner { /// Create a new Linux epoll file descriptor - pub fn new() -> Result { + pub fn new() -> Result { let ret = try_libc!(libc::ocall::epoll_create1(0)); Ok(EpollFileInner { epoll_fd: ret }) } @@ -269,7 +269,7 @@ impl EpollFileInner { op: c_int, host_fd: FileDesc, event: *const libc::epoll_event, - ) -> Result<(), Error> { + ) -> Result<()> { let ret = try_libc!(libc::ocall::epoll_ctl( self.epoll_fd, op, @@ -281,11 +281,7 @@ impl EpollFileInner { /// Wait for an I/O event on the epoll. /// Returns the number of file descriptors ready for the requested I/O. - pub fn wait( - &mut self, - events: &mut [libc::epoll_event], - timeout: c_int, - ) -> Result { + pub fn wait(&mut self, events: &mut [libc::epoll_event], timeout: c_int) -> Result { let ret = try_libc!(libc::ocall::epoll_wait( self.epoll_fd, events.as_mut_ptr(), @@ -305,51 +301,51 @@ impl Drop for EpollFileInner { } impl File for EpollFile { - fn read(&self, buf: &mut [u8]) -> Result { + fn read(&self, buf: &mut [u8]) -> Result { unimplemented!() } - fn write(&self, buf: &[u8]) -> Result { + fn write(&self, buf: &[u8]) -> Result { unimplemented!() } - fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { unimplemented!() } - fn write_at(&self, offset: usize, buf: &[u8]) -> Result { + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { unimplemented!() } - fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { unimplemented!() } - fn writev(&self, bufs: &[&[u8]]) -> Result { + fn writev(&self, bufs: &[&[u8]]) -> Result { unimplemented!() } - fn seek(&self, pos: SeekFrom) -> Result { - errno!(ESPIPE, "Epoll does not support seek") + fn seek(&self, pos: SeekFrom) -> Result { + return_errno!(ESPIPE, "Epoll does not support seek") } - fn metadata(&self) -> Result { + fn metadata(&self) -> Result { unimplemented!() } - fn set_len(&self, len: u64) -> Result<(), Error> { + fn set_len(&self, len: u64) -> Result<()> { unimplemented!() } - fn sync_all(&self) -> Result<(), Error> { + fn sync_all(&self) -> Result<()> { unimplemented!() } - fn sync_data(&self) -> Result<(), Error> { + fn sync_data(&self) -> Result<()> { unimplemented!() } - fn read_entry(&self) -> Result { + fn read_entry(&self) -> Result { unimplemented!() } @@ -368,13 +364,13 @@ impl Debug for EpollFile { } pub trait AsEpoll { - fn as_epoll(&self) -> Result<&EpollFile, Error>; + fn as_epoll(&self) -> Result<&EpollFile>; } impl AsEpoll for FileRef { - fn as_epoll(&self) -> Result<&EpollFile, Error> { + fn as_epoll(&self) -> Result<&EpollFile> { self.as_any() .downcast_ref::() - .ok_or(Error::new(Errno::EBADF, "not a epoll")) + .ok_or_else(|| errno!(EBADF, "not a epoll")) } } diff --git a/src/libos/src/fs/mod.rs b/src/libos/src/fs/mod.rs index 8753ff91..0f788da5 100644 --- a/src/libos/src/fs/mod.rs +++ b/src/libos/src/fs/mod.rs @@ -1,11 +1,11 @@ -use prelude::*; +use super::*; + use process::Process; use rcore_fs::vfs::{FileType, FsError, INode, Metadata, Timespec}; +use std::io::{Read, Seek, SeekFrom, Write}; use std::sgxfs as fs_impl; use {process, std}; -use super::*; - pub use self::access::{do_access, do_faccessat, AccessFlags, AccessModes, AT_FDCWD}; use self::dev_null::DevNull; use self::dev_random::DevRandom; @@ -38,7 +38,7 @@ mod sgx_impl; mod socket_file; mod unix_socket; -pub fn do_open(path: &str, flags: u32, mode: u32) -> Result { +pub fn do_open(path: &str, flags: u32, mode: u32) -> Result { let flags = OpenFlags::from_bits_truncate(flags); info!( "open: path: {:?}, flags: {:?}, mode: {:#o}", @@ -61,7 +61,7 @@ pub fn do_open(path: &str, flags: u32, mode: u32) -> Result { Ok(fd) } -pub fn do_write(fd: FileDesc, buf: &[u8]) -> Result { +pub fn do_write(fd: FileDesc, buf: &[u8]) -> Result { info!("write: fd: {}", fd); let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); @@ -69,7 +69,7 @@ pub fn do_write(fd: FileDesc, buf: &[u8]) -> Result { file_ref.write(buf) } -pub fn do_read(fd: FileDesc, buf: &mut [u8]) -> Result { +pub fn do_read(fd: FileDesc, buf: &mut [u8]) -> Result { info!("read: fd: {}", fd); let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); @@ -77,7 +77,7 @@ pub fn do_read(fd: FileDesc, buf: &mut [u8]) -> Result { file_ref.read(buf) } -pub fn do_writev(fd: FileDesc, bufs: &[&[u8]]) -> Result { +pub fn do_writev(fd: FileDesc, bufs: &[&[u8]]) -> Result { info!("writev: fd: {}", fd); let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); @@ -85,7 +85,7 @@ pub fn do_writev(fd: FileDesc, bufs: &[&[u8]]) -> Result { file_ref.writev(bufs) } -pub fn do_readv(fd: FileDesc, bufs: &mut [&mut [u8]]) -> Result { +pub fn do_readv(fd: FileDesc, bufs: &mut [&mut [u8]]) -> Result { info!("readv: fd: {}", fd); let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); @@ -93,7 +93,7 @@ pub fn do_readv(fd: FileDesc, bufs: &mut [&mut [u8]]) -> Result { file_ref.readv(bufs) } -pub fn do_pwrite(fd: FileDesc, buf: &[u8], offset: usize) -> Result { +pub fn do_pwrite(fd: FileDesc, buf: &[u8], offset: usize) -> Result { info!("pwrite: fd: {}, offset: {}", fd, offset); let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); @@ -101,7 +101,7 @@ pub fn do_pwrite(fd: FileDesc, buf: &[u8], offset: usize) -> Result Result { +pub fn do_pread(fd: FileDesc, buf: &mut [u8], offset: usize) -> Result { info!("pread: fd: {}, offset: {}", fd, offset); let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); @@ -109,12 +109,12 @@ pub fn do_pread(fd: FileDesc, buf: &mut [u8], offset: usize) -> Result Result { +pub fn do_stat(path: &str) -> Result { warn!("stat is partial implemented as lstat"); do_lstat(path) } -pub fn do_fstat(fd: u32) -> Result { +pub fn do_fstat(fd: u32) -> Result { info!("fstat: fd: {}", fd); let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); @@ -124,7 +124,7 @@ pub fn do_fstat(fd: u32) -> Result { Ok(stat) } -pub fn do_lstat(path: &str) -> Result { +pub fn do_lstat(path: &str) -> Result { info!("lstat: path: {}", path); let current_ref = process::get_current(); @@ -134,14 +134,14 @@ pub fn do_lstat(path: &str) -> Result { Ok(stat) } -pub fn do_lseek(fd: FileDesc, offset: SeekFrom) -> Result { +pub fn do_lseek(fd: FileDesc, offset: SeekFrom) -> Result { let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); let file_ref = current_process.get_files().lock().unwrap().get(fd)?; file_ref.seek(offset) } -pub fn do_fsync(fd: FileDesc) -> Result<(), Error> { +pub fn do_fsync(fd: FileDesc) -> Result<()> { info!("fsync: fd: {}", fd); let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); @@ -150,7 +150,7 @@ pub fn do_fsync(fd: FileDesc) -> Result<(), Error> { Ok(()) } -pub fn do_fdatasync(fd: FileDesc) -> Result<(), Error> { +pub fn do_fdatasync(fd: FileDesc) -> Result<()> { info!("fdatasync: fd: {}", fd); let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); @@ -159,7 +159,7 @@ pub fn do_fdatasync(fd: FileDesc) -> Result<(), Error> { Ok(()) } -pub fn do_truncate(path: &str, len: usize) -> Result<(), Error> { +pub fn do_truncate(path: &str, len: usize) -> Result<()> { info!("truncate: path: {:?}, len: {}", path, len); let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); @@ -167,7 +167,7 @@ pub fn do_truncate(path: &str, len: usize) -> Result<(), Error> { Ok(()) } -pub fn do_ftruncate(fd: FileDesc, len: usize) -> Result<(), Error> { +pub fn do_ftruncate(fd: FileDesc, len: usize) -> Result<()> { info!("ftruncate: fd: {}, len: {}", fd, len); let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); @@ -176,7 +176,7 @@ pub fn do_ftruncate(fd: FileDesc, len: usize) -> Result<(), Error> { Ok(()) } -pub fn do_getdents64(fd: FileDesc, buf: &mut [u8]) -> Result { +pub fn do_getdents64(fd: FileDesc, buf: &mut [u8]) -> Result { info!( "getdents64: fd: {}, buf: {:?}, buf_size: {}", fd, @@ -188,24 +188,30 @@ pub fn do_getdents64(fd: FileDesc, buf: &mut [u8]) -> Result { let file_ref = current_process.get_files().lock().unwrap().get(fd)?; let info = file_ref.metadata()?; if info.type_ != FileType::Dir { - return errno!(ENOTDIR, ""); + return_errno!(ENOTDIR, ""); } let mut writer = unsafe { DirentBufWriter::new(buf) }; loop { let name = match file_ref.read_entry() { - Err(e) if e.errno == ENOENT => break, - r => r, - }?; + Err(e) => { + let errno = e.errno(); + if errno == ENOENT { + break; + } + return Err(e.cause_err(|_| errno!(errno, "failed to read entry"))); + } + Ok(name) => name, + }; // TODO: get ino from dirent let ok = writer.try_write(0, 0, &name); if !ok { - break; + return_errno!(EINVAL, "the given buffer is too small"); } } Ok(writer.written_size) } -pub fn do_close(fd: FileDesc) -> Result<(), Error> { +pub fn do_close(fd: FileDesc) -> Result<()> { info!("close: fd: {}", fd); let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); @@ -215,7 +221,7 @@ pub fn do_close(fd: FileDesc) -> Result<(), Error> { Ok(()) } -pub fn do_pipe2(flags: u32) -> Result<[FileDesc; 2], Error> { +pub fn do_pipe2(flags: u32) -> Result<[FileDesc; 2]> { info!("pipe2: flags: {:#x}", flags); let flags = OpenFlags::from_bits_truncate(flags); let current_ref = process::get_current(); @@ -231,7 +237,7 @@ pub fn do_pipe2(flags: u32) -> Result<[FileDesc; 2], Error> { Ok([reader_fd, writer_fd]) } -pub fn do_dup(old_fd: FileDesc) -> Result { +pub fn do_dup(old_fd: FileDesc) -> Result { let current_ref = process::get_current(); let current = current_ref.lock().unwrap(); let file_table_ref = current.get_files(); @@ -241,7 +247,7 @@ pub fn do_dup(old_fd: FileDesc) -> Result { Ok(new_fd) } -pub fn do_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result { +pub fn do_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result { let current_ref = process::get_current(); let current = current_ref.lock().unwrap(); let file_table_ref = current.get_files(); @@ -253,7 +259,7 @@ pub fn do_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result { Ok(new_fd) } -pub fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result { +pub fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result { let flags = OpenFlags::from_bits_truncate(flags); let current_ref = process::get_current(); let current = current_ref.lock().unwrap(); @@ -261,20 +267,20 @@ pub fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result Result<(), Error> { +pub fn do_sync() -> Result<()> { info!("sync:"); ROOT_INODE.fs().sync()?; Ok(()) } -pub fn do_chdir(path: &str) -> Result<(), Error> { +pub fn do_chdir(path: &str) -> Result<()> { let current_ref = process::get_current(); let mut current_process = current_ref.lock().unwrap(); info!("chdir: path: {:?}", path); @@ -282,13 +288,13 @@ pub fn do_chdir(path: &str) -> Result<(), Error> { let inode = current_process.lookup_inode(path)?; let info = inode.metadata()?; if info.type_ != FileType::Dir { - return errno!(ENOTDIR, ""); + return_errno!(ENOTDIR, ""); } current_process.change_cwd(path); Ok(()) } -pub fn do_rename(oldpath: &str, newpath: &str) -> Result<(), Error> { +pub fn do_rename(oldpath: &str, newpath: &str) -> Result<()> { let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); info!("rename: oldpath: {:?}, newpath: {:?}", oldpath, newpath); @@ -301,7 +307,7 @@ pub fn do_rename(oldpath: &str, newpath: &str) -> Result<(), Error> { Ok(()) } -pub fn do_mkdir(path: &str, mode: usize) -> Result<(), Error> { +pub fn do_mkdir(path: &str, mode: usize) -> Result<()> { let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); // TODO: check pathname @@ -310,16 +316,16 @@ pub fn do_mkdir(path: &str, mode: usize) -> Result<(), Error> { let (dir_path, file_name) = split_path(&path); let inode = current_process.lookup_inode(dir_path)?; if inode.find(file_name).is_ok() { - return errno!(EEXIST, ""); + return_errno!(EEXIST, ""); } if !inode.allow_write()? { - return errno!(EPERM, "dir cannot be written"); + return_errno!(EPERM, "dir cannot be written"); } inode.create(file_name, FileType::Dir, mode as u32)?; Ok(()) } -pub fn do_rmdir(path: &str) -> Result<(), Error> { +pub fn do_rmdir(path: &str) -> Result<()> { let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); info!("rmdir: path: {:?}", path); @@ -328,13 +334,13 @@ pub fn do_rmdir(path: &str) -> Result<(), Error> { let dir_inode = current_process.lookup_inode(dir_path)?; let file_inode = dir_inode.find(file_name)?; if file_inode.metadata()?.type_ != FileType::Dir { - return errno!(ENOTDIR, "rmdir on not directory"); + return_errno!(ENOTDIR, "rmdir on not directory"); } dir_inode.unlink(file_name)?; Ok(()) } -pub fn do_link(oldpath: &str, newpath: &str) -> Result<(), Error> { +pub fn do_link(oldpath: &str, newpath: &str) -> Result<()> { let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); info!("link: oldpath: {:?}, newpath: {:?}", oldpath, newpath); @@ -346,7 +352,7 @@ pub fn do_link(oldpath: &str, newpath: &str) -> Result<(), Error> { Ok(()) } -pub fn do_unlink(path: &str) -> Result<(), Error> { +pub fn do_unlink(path: &str) -> Result<()> { let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); info!("unlink: path: {:?}", path); @@ -355,7 +361,7 @@ pub fn do_unlink(path: &str) -> Result<(), Error> { let dir_inode = current_process.lookup_inode(dir_path)?; let file_inode = dir_inode.find(file_name)?; if file_inode.metadata()?.type_ == FileType::Dir { - return errno!(EISDIR, "unlink on directory"); + return_errno!(EISDIR, "unlink on directory"); } dir_inode.unlink(file_name)?; Ok(()) @@ -366,7 +372,7 @@ pub fn do_sendfile( in_fd: FileDesc, offset: Option, count: usize, -) -> Result<(usize, usize), Error> { +) -> Result<(usize, usize)> { // (len, offset) info!( "sendfile: out: {}, in: {}, offset: {:?}, count: {}", @@ -400,7 +406,7 @@ pub fn do_sendfile( while bytes_written < read_len { let write_len = out_file.write(&buffer[bytes_written..])?; if write_len == 0 { - return errno!(EBADF, "sendfile write return 0"); + return_errno!(EBADF, "sendfile write return 0"); } bytes_written += write_len; } @@ -418,7 +424,7 @@ extern "C" { impl Process { /// Open a file on the process. But DO NOT add it to file table. - pub fn open_file(&self, path: &str, flags: OpenFlags, mode: u32) -> Result, Error> { + pub fn open_file(&self, path: &str, flags: OpenFlags, mode: u32) -> Result> { if path == "/dev/null" { return Ok(Box::new(DevNull)); } @@ -434,13 +440,13 @@ impl Process { match dir_inode.find(file_name) { Ok(file_inode) => { if flags.contains(OpenFlags::EXCLUSIVE) { - return errno!(EEXIST, "file exists"); + return_errno!(EEXIST, "file exists"); } file_inode } Err(FsError::EntryNotFound) => { if !dir_inode.allow_write()? { - return errno!(EPERM, "file cannot be created"); + return_errno!(EPERM, "file cannot be created"); } dir_inode.create(file_name, FileType::File, mode)? } @@ -453,7 +459,7 @@ impl Process { } /// Lookup INode from the cwd of the process - pub fn lookup_inode(&self, path: &str) -> Result, Error> { + pub fn lookup_inode(&self, path: &str) -> Result> { debug!("lookup_inode: cwd: {:?}, path: {:?}", self.get_cwd(), path); if path.len() > 0 && path.as_bytes()[0] == b'/' { // absolute path @@ -727,7 +733,7 @@ pub enum FcntlCmd { impl FcntlCmd { #[deny(unreachable_patterns)] - pub fn from_raw(cmd: u32, arg: u64) -> Result { + pub fn from_raw(cmd: u32, arg: u64) -> Result { Ok(match cmd as c_int { libc::F_DUPFD => FcntlCmd::DupFd(arg as FileDesc), libc::F_DUPFD_CLOEXEC => FcntlCmd::DupFdCloexec(arg as FileDesc), @@ -735,12 +741,12 @@ impl FcntlCmd { libc::F_SETFD => FcntlCmd::SetFd(arg as u32), libc::F_GETFL => FcntlCmd::GetFl(), libc::F_SETFL => FcntlCmd::SetFl(arg as u32), - _ => return errno!(EINVAL, "invalid command"), + _ => return_errno!(EINVAL, "invalid command"), }) } } -pub fn do_fcntl(fd: FileDesc, cmd: &FcntlCmd) -> Result { +pub fn do_fcntl(fd: FileDesc, cmd: &FcntlCmd) -> Result { info!("fcntl: fd: {:?}, cmd: {:?}", &fd, cmd); let current_ref = process::get_current(); let mut current = current_ref.lock().unwrap(); @@ -796,7 +802,7 @@ pub fn do_fcntl(fd: FileDesc, cmd: &FcntlCmd) -> Result { }) } -pub fn do_readlink(path: &str, buf: &mut [u8]) -> Result { +pub fn do_readlink(path: &str, buf: &mut [u8]) -> Result { info!("readlink: path: {:?}", path); match path { "/proc/self/exe" => { @@ -810,7 +816,7 @@ pub fn do_readlink(path: &str, buf: &mut [u8]) -> Result { } _ => { // TODO: support symbolic links - errno!(EINVAL, "not a symbolic link") + return_errno!(EINVAL, "not a symbolic link") } } } diff --git a/src/libos/src/fs/pipe.rs b/src/libos/src/fs/pipe.rs index d0aab595..5350b414 100644 --- a/src/libos/src/fs/pipe.rs +++ b/src/libos/src/fs/pipe.rs @@ -12,7 +12,7 @@ pub struct Pipe { } impl Pipe { - pub fn new() -> Result { + pub fn new() -> Result { let mut ring_buf = RingBuf::new(PIPE_BUF_SIZE); Ok(Pipe { reader: PipeReader { @@ -31,24 +31,24 @@ pub struct PipeReader { } impl File for PipeReader { - fn read(&self, buf: &mut [u8]) -> Result { + fn read(&self, buf: &mut [u8]) -> Result { let ringbuf = self.inner.lock().unwrap(); ringbuf.read(buf) } - fn write(&self, buf: &[u8]) -> Result { - errno!(EBADF, "PipeReader does not support write") + fn write(&self, buf: &[u8]) -> Result { + return_errno!(EBADF, "PipeReader does not support write") } - fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { unimplemented!() } - fn write_at(&self, offset: usize, buf: &[u8]) -> Result { + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { unimplemented!() } - fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { let mut ringbuf = self.inner.lock().unwrap(); let mut total_bytes = 0; for buf in bufs { @@ -72,31 +72,31 @@ impl File for PipeReader { Ok(total_bytes) } - fn writev(&self, bufs: &[&[u8]]) -> Result { - errno!(EBADF, "PipeReader does not support write") + fn writev(&self, bufs: &[&[u8]]) -> Result { + return_errno!(EBADF, "PipeReader does not support write") } - fn seek(&self, pos: SeekFrom) -> Result { - errno!(ESPIPE, "Pipe does not support seek") + fn seek(&self, pos: SeekFrom) -> Result { + return_errno!(ESPIPE, "Pipe does not support seek") } - fn metadata(&self) -> Result { + fn metadata(&self) -> Result { unimplemented!() } - fn set_len(&self, len: u64) -> Result<(), Error> { + fn set_len(&self, len: u64) -> Result<()> { unimplemented!() } - fn sync_all(&self) -> Result<(), Error> { + fn sync_all(&self) -> Result<()> { unimplemented!() } - fn sync_data(&self) -> Result<(), Error> { + fn sync_data(&self) -> Result<()> { unimplemented!() } - fn read_entry(&self) -> Result { + fn read_entry(&self) -> Result { unimplemented!() } @@ -114,27 +114,27 @@ pub struct PipeWriter { } impl File for PipeWriter { - fn read(&self, buf: &mut [u8]) -> Result { - errno!(EBADF, "PipeWriter does not support read") + fn read(&self, buf: &mut [u8]) -> Result { + return_errno!(EBADF, "PipeWriter does not support read") } - fn write(&self, buf: &[u8]) -> Result { + fn write(&self, buf: &[u8]) -> Result { let ringbuf = self.inner.lock().unwrap(); ringbuf.write(buf) } - fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { unimplemented!() } - fn write_at(&self, offset: usize, buf: &[u8]) -> Result { + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { unimplemented!() } - fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { - errno!(EBADF, "PipeWriter does not support read") + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { + return_errno!(EBADF, "PipeWriter does not support read") } - fn writev(&self, bufs: &[&[u8]]) -> Result { + fn writev(&self, bufs: &[&[u8]]) -> Result { let ringbuf = self.inner.lock().unwrap(); let mut total_bytes = 0; for buf in bufs { @@ -158,27 +158,27 @@ impl File for PipeWriter { Ok(total_bytes) } - fn seek(&self, seek_pos: SeekFrom) -> Result { - errno!(ESPIPE, "Pipe does not support seek") + fn seek(&self, seek_pos: SeekFrom) -> Result { + return_errno!(ESPIPE, "Pipe does not support seek") } - fn metadata(&self) -> Result { + fn metadata(&self) -> Result { unimplemented!() } - fn set_len(&self, len: u64) -> Result<(), Error> { + fn set_len(&self, len: u64) -> Result<()> { unimplemented!() } - fn sync_all(&self) -> Result<(), Error> { + fn sync_all(&self) -> Result<()> { unimplemented!() } - fn sync_data(&self) -> Result<(), Error> { + fn sync_data(&self) -> Result<()> { unimplemented!() } - fn read_entry(&self) -> Result { + fn read_entry(&self) -> Result { unimplemented!() } diff --git a/src/libos/src/fs/root_inode.rs b/src/libos/src/fs/root_inode.rs index 11f6fea9..86751ce4 100644 --- a/src/libos/src/fs/root_inode.rs +++ b/src/libos/src/fs/root_inode.rs @@ -13,34 +13,38 @@ use rcore_fs_sefs::SEFS; lazy_static! { /// The root of file system pub static ref ROOT_INODE: Arc = { - let mount_config = &config::LIBOS_CONFIG.mount; + fn init_root_inode() -> Result> { + let mount_config = &config::LIBOS_CONFIG.mount; + let root_inode = { + let rootfs = open_root_fs_according_to(mount_config)?; + rootfs.root_inode() + }; + mount_nonroot_fs_according_to(mount_config, &root_inode)?; + Ok(root_inode) + } - let rootfs = open_root_fs_according_to(mount_config) - .expect("failed to create or open SEFS for /"); - let root = rootfs.root_inode(); - - mount_nonroot_fs_according_to(mount_config, &root) - .expect("failed to create or open other FS"); - - root + init_root_inode().unwrap_or_else(|e| { + error!("failed to init root inode: {}", e.backtrace()); + panic!(); + }) }; } -fn open_root_fs_according_to(mount_config: &Vec) -> Result, Error> { +fn open_root_fs_according_to(mount_config: &Vec) -> Result> { let (root_sefs_mac, root_sefs_source) = { let root_mount_config = mount_config .iter() .find(|m| m.target == Path::new("/")) - .ok_or_else(|| Error::new(Errno::ENOENT, "The mount point at / is not specified"))?; + .ok_or_else(|| errno!(Errno::ENOENT, "the mount point at / is not specified"))?; if root_mount_config.type_ != ConfigMountFsType::TYPE_SEFS { - return errno!(EINVAL, "The mount point at / must be SEFS"); + return_errno!(EINVAL, "The mount point at / must be SEFS"); } if !root_mount_config.options.integrity_only { - return errno!(EINVAL, "The root SEFS at / must be integrity-only"); + return_errno!(EINVAL, "The root SEFS at / must be integrity-only"); } if root_mount_config.source.is_none() { - return errno!( + return_errno!( EINVAL, "The root SEFS must be given a source path (on host)" ); @@ -60,20 +64,17 @@ fn open_root_fs_according_to(mount_config: &Vec) -> Result, - root: &MNode, -) -> Result<(), Error> { +fn mount_nonroot_fs_according_to(mount_config: &Vec, root: &MNode) -> Result<()> { for mc in mount_config { if mc.target == Path::new("/") { continue; } if !mc.target.is_absolute() { - return errno!(EINVAL, "The target path must be absolute"); + return_errno!(EINVAL, "The target path must be absolute"); } if mc.target.parent().unwrap() != Path::new("/") { - return errno!(EINVAL, "The target mount point must be under /"); + return_errno!(EINVAL, "The target mount point must be under /"); } let target_dirname = mc.target.file_name().unwrap().to_str().unwrap(); @@ -81,10 +82,10 @@ fn mount_nonroot_fs_according_to( match mc.type_ { TYPE_SEFS => { if mc.options.integrity_only { - return errno!(EINVAL, "Cannot mount integrity-only SEFS at non-root path"); + return_errno!(EINVAL, "Cannot mount integrity-only SEFS at non-root path"); } if mc.source.is_none() { - return errno!(EINVAL, "Source is expected for SEFS"); + return_errno!(EINVAL, "Source is expected for SEFS"); } let source_path = mc.source.as_ref().unwrap(); let sefs = { @@ -105,7 +106,7 @@ fn mount_nonroot_fs_according_to( } TYPE_HOSTFS => { if mc.source.is_none() { - return errno!(EINVAL, "Source is expected for HostFS"); + return_errno!(EINVAL, "Source is expected for HostFS"); } let source_path = mc.source.as_ref().unwrap(); @@ -121,15 +122,15 @@ fn mount_nonroot_fs_according_to( Ok(()) } -fn mount_fs_at(fs: Arc, parent_inode: &MNode, dirname: &str) -> Result<(), Error> { +fn mount_fs_at(fs: Arc, parent_inode: &MNode, dirname: &str) -> Result<()> { let mount_dir = match parent_inode.find(false, dirname) { Ok(existing_dir) => { if existing_dir.metadata()?.type_ != FileType::Dir { - return errno!(EIO, "not a directory"); + return_errno!(EIO, "not a directory"); } existing_dir } - Err(_) => return errno!(ENOENT, "Mount point does not exist"), + Err(_) => return_errno!(ENOENT, "Mount point does not exist"), }; mount_dir.mount(fs); Ok(()) diff --git a/src/libos/src/fs/sgx_impl.rs b/src/libos/src/fs/sgx_impl.rs index 14ed4cfb..f8eae5d9 100644 --- a/src/libos/src/fs/sgx_impl.rs +++ b/src/libos/src/fs/sgx_impl.rs @@ -129,8 +129,8 @@ impl Storage for SgxStorage { if file_id == "metadata" && self.root_mac.is_some() { let root_file_mac = file.get_mac().expect("Failed to get mac"); if root_file_mac != self.root_mac.unwrap() { - println!( - "Expected MAC = {:#?}, actual MAC = {:?}", + error!( + "MAC validation for metadata file failed: expected = {:#?}, found = {:?}", self.root_mac.unwrap(), root_file_mac ); diff --git a/src/libos/src/fs/socket_file.rs b/src/libos/src/fs/socket_file.rs index 52a79b15..510088bc 100644 --- a/src/libos/src/fs/socket_file.rs +++ b/src/libos/src/fs/socket_file.rs @@ -8,7 +8,7 @@ pub struct SocketFile { } impl SocketFile { - pub fn new(domain: c_int, socket_type: c_int, protocol: c_int) -> Result { + pub fn new(domain: c_int, socket_type: c_int, protocol: c_int) -> Result { let ret = try_libc!(libc::ocall::socket(domain, socket_type, protocol)); Ok(SocketFile { fd: ret }) } @@ -18,7 +18,7 @@ impl SocketFile { addr: *mut libc::sockaddr, addr_len: *mut libc::socklen_t, flags: c_int, - ) -> Result { + ) -> Result { let ret = try_libc!(libc::ocall::accept4(self.fd, addr, addr_len, flags)); Ok(SocketFile { fd: ret }) } @@ -42,7 +42,7 @@ impl Drop for SocketFile { } impl File for SocketFile { - fn read(&self, buf: &mut [u8]) -> Result { + fn read(&self, buf: &mut [u8]) -> Result { let ret = try_libc!(libc::ocall::read( self.fd, buf.as_mut_ptr() as *mut c_void, @@ -51,7 +51,7 @@ impl File for SocketFile { Ok(ret as usize) } - fn write(&self, buf: &[u8]) -> Result { + fn write(&self, buf: &[u8]) -> Result { let ret = try_libc!(libc::ocall::write( self.fd, buf.as_ptr() as *const c_void, @@ -60,15 +60,15 @@ impl File for SocketFile { Ok(ret as usize) } - fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result { + fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result { self.read(buf) } - fn write_at(&self, _offset: usize, buf: &[u8]) -> Result { + fn write_at(&self, _offset: usize, buf: &[u8]) -> Result { self.write(buf) } - fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { let mut total_len = 0; for buf in bufs { match self.read(buf) { @@ -82,7 +82,7 @@ impl File for SocketFile { Ok(total_len) } - fn writev(&self, bufs: &[&[u8]]) -> Result { + fn writev(&self, bufs: &[&[u8]]) -> Result { let mut total_len = 0; for buf in bufs { match self.write(buf) { @@ -96,11 +96,11 @@ impl File for SocketFile { Ok(total_len) } - fn seek(&self, pos: SeekFrom) -> Result { - errno!(ESPIPE, "Socket does not support seek") + fn seek(&self, pos: SeekFrom) -> Result { + return_errno!(ESPIPE, "Socket does not support seek") } - fn metadata(&self) -> Result { + fn metadata(&self) -> Result { Ok(Metadata { dev: 0, inode: 0, @@ -119,19 +119,19 @@ impl File for SocketFile { }) } - fn set_len(&self, len: u64) -> Result<(), Error> { + fn set_len(&self, len: u64) -> Result<()> { unimplemented!() } - fn sync_all(&self) -> Result<(), Error> { + fn sync_all(&self) -> Result<()> { unimplemented!() } - fn sync_data(&self) -> Result<(), Error> { + fn sync_data(&self) -> Result<()> { unimplemented!() } - fn read_entry(&self) -> Result { + fn read_entry(&self) -> Result { unimplemented!() } @@ -141,13 +141,13 @@ impl File for SocketFile { } pub trait AsSocket { - fn as_socket(&self) -> Result<&SocketFile, Error>; + fn as_socket(&self) -> Result<&SocketFile>; } impl AsSocket for FileRef { - fn as_socket(&self) -> Result<&SocketFile, Error> { + fn as_socket(&self) -> Result<&SocketFile> { self.as_any() .downcast_ref::() - .ok_or(Error::new(Errno::EBADF, "not a socket")) + .ok_or_else(|| errno!(EBADF, "not a socket")) } } diff --git a/src/libos/src/fs/unix_socket.rs b/src/libos/src/fs/unix_socket.rs index eb20731a..9aad9815 100644 --- a/src/libos/src/fs/unix_socket.rs +++ b/src/libos/src/fs/unix_socket.rs @@ -11,25 +11,25 @@ pub struct UnixSocketFile { } impl File for UnixSocketFile { - fn read(&self, buf: &mut [u8]) -> Result { + fn read(&self, buf: &mut [u8]) -> Result { let mut inner = self.inner.lock().unwrap(); inner.read(buf) } - fn write(&self, buf: &[u8]) -> Result { + fn write(&self, buf: &[u8]) -> Result { let mut inner = self.inner.lock().unwrap(); inner.write(buf) } - fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result { + fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result { self.read(buf) } - fn write_at(&self, _offset: usize, buf: &[u8]) -> Result { + fn write_at(&self, _offset: usize, buf: &[u8]) -> Result { self.write(buf) } - fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { let mut inner = self.inner.lock().unwrap(); let mut total_len = 0; for buf in bufs { @@ -44,7 +44,7 @@ impl File for UnixSocketFile { Ok(total_len) } - fn writev(&self, bufs: &[&[u8]]) -> Result { + fn writev(&self, bufs: &[&[u8]]) -> Result { let mut inner = self.inner.lock().unwrap(); let mut total_len = 0; for buf in bufs { @@ -59,11 +59,11 @@ impl File for UnixSocketFile { Ok(total_len) } - fn seek(&self, pos: SeekFrom) -> Result { - errno!(ESPIPE, "UnixSocket does not support seek") + fn seek(&self, pos: SeekFrom) -> Result { + return_errno!(ESPIPE, "UnixSocket does not support seek") } - fn metadata(&self) -> Result { + fn metadata(&self) -> Result { Ok(Metadata { dev: 0, inode: 0, @@ -82,19 +82,19 @@ impl File for UnixSocketFile { }) } - fn set_len(&self, len: u64) -> Result<(), Error> { + fn set_len(&self, len: u64) -> Result<()> { unimplemented!() } - fn sync_all(&self) -> Result<(), Error> { + fn sync_all(&self) -> Result<()> { unimplemented!() } - fn sync_data(&self) -> Result<(), Error> { + fn sync_data(&self) -> Result<()> { unimplemented!() } - fn read_entry(&self) -> Result { + fn read_entry(&self) -> Result { unimplemented!() } @@ -104,24 +104,24 @@ impl File for UnixSocketFile { } impl UnixSocketFile { - pub fn new(socket_type: c_int, protocol: c_int) -> Result { + pub fn new(socket_type: c_int, protocol: c_int) -> Result { let inner = UnixSocket::new(socket_type, protocol)?; Ok(UnixSocketFile { inner: Mutex::new(inner), }) } - pub fn bind(&self, path: impl AsRef) -> Result<(), Error> { + pub fn bind(&self, path: impl AsRef) -> Result<()> { let mut inner = self.inner.lock().unwrap(); inner.bind(path) } - pub fn listen(&self) -> Result<(), Error> { + pub fn listen(&self) -> Result<()> { let mut inner = self.inner.lock().unwrap(); inner.listen() } - pub fn accept(&self) -> Result { + pub fn accept(&self) -> Result { let mut inner = self.inner.lock().unwrap(); let new_socket = inner.accept()?; Ok(UnixSocketFile { @@ -129,17 +129,17 @@ impl UnixSocketFile { }) } - pub fn connect(&self, path: impl AsRef) -> Result<(), Error> { + pub fn connect(&self, path: impl AsRef) -> Result<()> { let mut inner = self.inner.lock().unwrap(); inner.connect(path) } - pub fn poll(&self) -> Result<(bool, bool, bool), Error> { + pub fn poll(&self) -> Result<(bool, bool, bool)> { let mut inner = self.inner.lock().unwrap(); inner.poll() } - pub fn ioctl(&self, cmd: c_int, argp: *mut c_int) -> Result<(), Error> { + pub fn ioctl(&self, cmd: c_int, argp: *mut c_int) -> Result<()> { let mut inner = self.inner.lock().unwrap(); inner.ioctl(cmd, argp) } @@ -152,14 +152,14 @@ impl Debug for UnixSocketFile { } pub trait AsUnixSocket { - fn as_unix_socket(&self) -> Result<&UnixSocketFile, Error>; + fn as_unix_socket(&self) -> Result<&UnixSocketFile>; } impl AsUnixSocket for FileRef { - fn as_unix_socket(&self) -> Result<&UnixSocketFile, Error> { + fn as_unix_socket(&self) -> Result<&UnixSocketFile> { self.as_any() .downcast_ref::() - .ok_or(Error::new(Errno::EBADF, "not a unix socket")) + .ok_or_else(|| errno!(EBADF, "not a unix socket")) } } @@ -176,38 +176,38 @@ enum Status { impl UnixSocket { /// C/S 1: Create a new unix socket - pub fn new(socket_type: c_int, protocol: c_int) -> Result { + pub fn new(socket_type: c_int, protocol: c_int) -> Result { if socket_type == libc::SOCK_STREAM && protocol == 0 { Ok(UnixSocket { obj: None, status: Status::None, }) } else { - errno!(ENOSYS, "unimplemented unix socket type") + return_errno!(ENOSYS, "unimplemented unix socket type") } } /// Server 2: Bind the socket to a file system path - pub fn bind(&mut self, path: impl AsRef) -> Result<(), Error> { + pub fn bind(&mut self, path: impl AsRef) -> Result<()> { // TODO: check permission if self.obj.is_some() { - return errno!(EINVAL, "The socket is already bound to an address."); + return_errno!(EINVAL, "The socket is already bound to an address."); } self.obj = Some(UnixSocketObject::create(path)?); Ok(()) } /// Server 3: Listen to a socket - pub fn listen(&mut self) -> Result<(), Error> { + pub fn listen(&mut self) -> Result<()> { self.status = Status::Listening; Ok(()) } /// Server 4: Accept a connection on listening. - pub fn accept(&mut self) -> Result { + pub fn accept(&mut self) -> Result { match self.status { Status::Listening => {} - _ => return errno!(EINVAL, "unix socket is not listening"), + _ => return_errno!(EINVAL, "unix socket is not listening"), }; // FIXME: Block. Now spin loop. let socket = loop { @@ -220,12 +220,12 @@ impl UnixSocket { } /// Client 2: Connect to a path - pub fn connect(&mut self, path: impl AsRef) -> Result<(), Error> { + pub fn connect(&mut self, path: impl AsRef) -> Result<()> { if let Status::Listening = self.status { - return errno!(EINVAL, "unix socket is listening?"); + return_errno!(EINVAL, "unix socket is listening?"); } - let obj = - UnixSocketObject::get(path).ok_or(Error::new(EINVAL, "unix socket path not found"))?; + let obj = UnixSocketObject::get(path) + .ok_or_else(|| errno!(EINVAL, "unix socket path not found"))?; let (channel1, channel2) = Channel::new_pair(); self.status = Status::Connected(channel1); obj.push(UnixSocket { @@ -235,15 +235,15 @@ impl UnixSocket { Ok(()) } - pub fn read(&self, buf: &mut [u8]) -> Result { + pub fn read(&self, buf: &mut [u8]) -> Result { self.channel()?.reader.read(buf) } - pub fn write(&self, buf: &[u8]) -> Result { + pub fn write(&self, buf: &[u8]) -> Result { self.channel()?.writer.write(buf) } - pub fn poll(&self) -> Result<(bool, bool, bool), Error> { + pub fn poll(&self) -> Result<(bool, bool, bool)> { // (read, write, error) let channel = self.channel()?; let r = channel.reader.can_read(); @@ -251,7 +251,7 @@ impl UnixSocket { Ok((r, w, false)) } - pub fn ioctl(&self, cmd: c_int, argp: *mut c_int) -> Result<(), Error> { + pub fn ioctl(&self, cmd: c_int, argp: *mut c_int) -> Result<()> { const FIONREAD: c_int = 0x541B; // Get the number of bytes to read if cmd == FIONREAD { let bytes_to_read = self.channel()?.reader.bytes_to_read(); @@ -261,15 +261,15 @@ impl UnixSocket { Ok(()) } else { warn!("ioctl for unix socket is unimplemented"); - errno!(ENOSYS, "ioctl for unix socket is unimplemented") + return_errno!(ENOSYS, "ioctl for unix socket is unimplemented") } } - fn channel(&self) -> Result<&Channel, Error> { + fn channel(&self) -> Result<&Channel> { if let Status::Connected(channel) = &self.status { Ok(channel) } else { - errno!(EBADF, "UnixSocket is not connected") + return_errno!(EBADF, "UnixSocket is not connected") } } } @@ -301,10 +301,10 @@ impl UnixSocketObject { let mut paths = UNIX_SOCKET_OBJS.lock().unwrap(); paths.get(path.as_ref()).map(|obj| obj.clone()) } - fn create(path: impl AsRef) -> Result, Error> { + fn create(path: impl AsRef) -> Result> { let mut paths = UNIX_SOCKET_OBJS.lock().unwrap(); if paths.contains_key(path.as_ref()) { - return errno!(EADDRINUSE, "unix socket path already exists"); + return_errno!(EADDRINUSE, "unix socket path already exists"); } let obj = Arc::new(UnixSocketObject { path: path.as_ref().to_string(), diff --git a/src/libos/src/lib.rs b/src/libos/src/lib.rs index 89342d92..dbafaa67 100644 --- a/src/libos/src/lib.rs +++ b/src/libos/src/lib.rs @@ -37,11 +37,18 @@ use std::backtrace::{self, PrintFormat}; use std::ffi::CStr; // a borrowed C string use std::panic; +use error::*; +use prelude::*; + +// Override prelude::Result with error::Result +use error::Result; + #[macro_use] mod prelude; +#[macro_use] +mod error; mod config; mod entry; -mod errno; mod exception; mod fs; mod misc; @@ -51,8 +58,6 @@ mod time; mod util; mod vm; -use prelude::*; - // Export system calls pub use syscall::*; // Export ECalls diff --git a/src/libos/src/misc/rlimit.rs b/src/libos/src/misc/rlimit.rs index 96754780..6c21e1ba 100644 --- a/src/libos/src/misc/rlimit.rs +++ b/src/libos/src/misc/rlimit.rs @@ -65,7 +65,7 @@ pub enum resource_t { const RLIMIT_COUNT: usize = 15; impl resource_t { - pub fn from_u32(bits: u32) -> Result { + pub fn from_u32(bits: u32) -> Result { match bits { 0 => Ok(resource_t::RLIMIT_CPU), 1 => Ok(resource_t::RLIMIT_FSIZE), @@ -82,7 +82,7 @@ impl resource_t { 12 => Ok(resource_t::RLIMIT_MSGQUEUE), 13 => Ok(resource_t::RLIMIT_NICE), 14 => Ok(resource_t::RLIMIT_RTPRIO), - _ => errno!(EINVAL, "invalid resource"), + _ => return_errno!(EINVAL, "invalid resource"), } } } @@ -92,11 +92,11 @@ pub fn do_prlimit( resource: resource_t, new_limit: Option<&rlimit_t>, old_limit: Option<&mut rlimit_t>, -) -> Result<(), Error> { +) -> Result<()> { let process_ref = if pid == 0 { process::get_current() } else { - process::get(pid)? + process::get(pid).cause_err(|_| errno!(ESRCH, "invalid pid"))? }; let mut process = process_ref.lock().unwrap(); let rlimits_ref = process.get_rlimits(); @@ -110,10 +110,10 @@ pub fn do_prlimit( Ok(()) } -pub fn do_getrlimit(resource: resource_t, old_limit: &mut rlimit_t) -> Result<(), Error> { +pub fn do_getrlimit(resource: resource_t, old_limit: &mut rlimit_t) -> Result<()> { do_prlimit(0 as pid_t, resource, None, Some(old_limit)) } -pub fn do_setrlimit(resource: resource_t, new_limit: &rlimit_t) -> Result<(), Error> { +pub fn do_setrlimit(resource: resource_t, new_limit: &rlimit_t) -> Result<()> { do_prlimit(0 as pid_t, resource, Some(new_limit), None) } diff --git a/src/libos/src/misc/uname.rs b/src/libos/src/misc/uname.rs index 12d33595..ee99451f 100644 --- a/src/libos/src/misc/uname.rs +++ b/src/libos/src/misc/uname.rs @@ -23,7 +23,7 @@ pub struct utsname_t { domainname: [u8; 65], } -pub fn do_uname(name: &mut utsname_t) -> Result<(), Error> { +pub fn do_uname(name: &mut utsname_t) -> Result<()> { copy_from_cstr_to_u8_array(&SYSNAME, &mut name.sysname); copy_from_cstr_to_u8_array(&NODENAME, &mut name.nodename); copy_from_cstr_to_u8_array(&RELEASE, &mut name.release); diff --git a/src/libos/src/prelude.rs b/src/libos/src/prelude.rs index 4ed5ef12..d3658527 100644 --- a/src/libos/src/prelude.rs +++ b/src/libos/src/prelude.rs @@ -1,32 +1,16 @@ pub use sgx_trts::libc; pub use sgx_trts::libc::off_t; pub use sgx_types::*; + use std; - -//pub use {elf_helper, errno, file, file_table, fs, mm, process, syscall, vma, }; - pub use std::cell::{Cell, RefCell}; -pub use std::marker::{Send, Sync}; -pub use std::result::Result; +pub use std::cmp::{max, min}; +pub use std::collections::{HashMap, VecDeque}; +pub use std::fmt::{Debug, Display}; +pub use std::prelude::v1::*; pub use std::sync::{ Arc, SgxMutex, SgxMutexGuard, SgxRwLock, SgxRwLockReadGuard, SgxRwLockWriteGuard, }; -//pub use std::borrow::BorrowMut; -pub use std::borrow::ToOwned; -pub use std::boxed::Box; -pub use std::cmp::{max, min}; -pub use std::cmp::{Ordering, PartialOrd}; -pub use std::collections::{HashMap, VecDeque}; -pub use std::fmt::{Debug, Display}; -pub use std::io::{Read, Seek, SeekFrom, Write}; -pub use std::iter::Iterator; -pub use std::rc::Rc; -pub use std::string::{String, ToString}; -pub use std::vec::Vec; - -pub use errno::Errno; -pub use errno::Errno::*; -pub use errno::Error; macro_rules! debug_trace { () => { @@ -34,38 +18,6 @@ macro_rules! debug_trace { }; } -macro_rules! errno { - ($errno: ident, $msg: expr) => {{ - error!( - "ERROR: {} ({}, line {} in file {})", - $errno, - $msg, - line!(), - file!() - ); - Err(Error::new($errno, $msg)) - }}; -} - -// return Err(errno) if libc return -1 -macro_rules! try_libc { - ($ret: expr) => {{ - let ret = unsafe { $ret }; - if ret == -1 { - let errno = unsafe { libc::errno() }; - // println will cause libc ocall and overwrite errno - error!( - "ERROR from libc: {} (line {} in file {})", - errno, - line!(), - file!() - ); - return Err(Error::new(Errno::from_errno(errno), "libc error")); - } - ret - }}; -} - pub fn align_up(addr: usize, align: usize) -> usize { debug_assert!(align != 0 && align.is_power_of_two()); align_down(addr + (align - 1), align) diff --git a/src/libos/src/process/arch_prctl.rs b/src/libos/src/process/arch_prctl.rs index 8d0f36d9..730fa31f 100644 --- a/src/libos/src/process/arch_prctl.rs +++ b/src/libos/src/process/arch_prctl.rs @@ -10,18 +10,18 @@ pub enum ArchPrctlCode { } impl ArchPrctlCode { - pub fn from_u32(bits: u32) -> Result { + pub fn from_u32(bits: u32) -> Result { match bits { 0x1001 => Ok(ArchPrctlCode::ARCH_SET_GS), 0x1002 => Ok(ArchPrctlCode::ARCH_SET_FS), 0x1003 => Ok(ArchPrctlCode::ARCH_GET_FS), 0x1004 => Ok(ArchPrctlCode::ARCH_GET_GS), - _ => errno!(EINVAL, "Unknown code for arch_prctl"), + _ => return_errno!(EINVAL, "Unknown code for arch_prctl"), } } } -pub fn do_arch_prctl(code: ArchPrctlCode, addr: *mut usize) -> Result<(), Error> { +pub fn do_arch_prctl(code: ArchPrctlCode, addr: *mut usize) -> Result<()> { info!( "do_arch_prctl: code: {:?}, addr: {:#o}", code, addr as usize @@ -42,7 +42,7 @@ pub fn do_arch_prctl(code: ArchPrctlCode, addr: *mut usize) -> Result<(), Error> } } ArchPrctlCode::ARCH_SET_GS | ArchPrctlCode::ARCH_GET_GS => { - return errno!(EINVAL, "GS cannot be accessed from the user space"); + return_errno!(EINVAL, "GS cannot be accessed from the user space"); } } Ok(()) diff --git a/src/libos/src/process/exit.rs b/src/libos/src/process/exit.rs index 19cd96fc..5f275ae5 100644 --- a/src/libos/src/process/exit.rs +++ b/src/libos/src/process/exit.rs @@ -64,7 +64,7 @@ pub fn do_exit(exit_status: i32) { }); } -pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32) -> Result { +pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32) -> Result { let current_ref = get_current(); let waiter = { let mut current = current_ref.lock().unwrap(); @@ -91,7 +91,7 @@ pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32) -> Res any_child_to_wait_for = true; } if !any_child_to_wait_for { - return errno!(ECHILD, "No such child"); + return_errno!(ECHILD, "No such child"); } let waiter = Waiter::new(child_filter); diff --git a/src/libos/src/process/futex.rs b/src/libos/src/process/futex.rs index 6c68fa2e..aaad69dc 100644 --- a/src/libos/src/process/futex.rs +++ b/src/libos/src/process/futex.rs @@ -21,7 +21,7 @@ pub enum FutexOp { const FUTEX_OP_MASK: u32 = 0x0000_000F; impl FutexOp { - pub fn from_u32(bits: u32) -> Result { + pub fn from_u32(bits: u32) -> Result { match bits { 0 => Ok(FutexOp::FUTEX_WAIT), 1 => Ok(FutexOp::FUTEX_WAKE), @@ -33,7 +33,7 @@ impl FutexOp { 7 => Ok(FutexOp::FUTEX_UNLOCK_PI), 8 => Ok(FutexOp::FUTEX_TRYLOCK_PI), 9 => Ok(FutexOp::FUTEX_WAIT_BITSET), - _ => errno!(EINVAL, "Unknown futex op"), + _ => return_errno!(EINVAL, "Unknown futex op"), } } } @@ -47,12 +47,12 @@ bitflags! { const FUTEX_FLAGS_MASK: u32 = 0xFFFF_FFF0; impl FutexFlags { - pub fn from_u32(bits: u32) -> Result { - FutexFlags::from_bits(bits).ok_or_else(|| Error::new(Errno::EINVAL, "Unknown futex flags")) + pub fn from_u32(bits: u32) -> Result { + FutexFlags::from_bits(bits).ok_or_else(|| errno!(EINVAL, "unknown futex flags")) } } -pub fn futex_op_and_flags_from_u32(bits: u32) -> Result<(FutexOp, FutexFlags), Error> { +pub fn futex_op_and_flags_from_u32(bits: u32) -> Result<(FutexOp, FutexFlags)> { let op = { let op_bits = bits & FUTEX_OP_MASK; FutexOp::from_u32(op_bits)? @@ -65,7 +65,7 @@ pub fn futex_op_and_flags_from_u32(bits: u32) -> Result<(FutexOp, FutexFlags), E } /// Do futex wait -pub fn futex_wait(futex_addr: *const i32, futex_val: i32) -> Result<(), Error> { +pub fn futex_wait(futex_addr: *const i32, futex_val: i32) -> Result<()> { let futex_key = FutexKey::new(futex_addr); let futex_item = FUTEX_TABLE.lock().unwrap().get_or_new_item(futex_key); @@ -76,7 +76,7 @@ pub fn futex_wait(futex_addr: *const i32, futex_val: i32) -> Result<(), Error> { } /// Do futex wake -pub fn futex_wake(futex_addr: *const i32, max_count: usize) -> Result { +pub fn futex_wake(futex_addr: *const i32, max_count: usize) -> Result { let futex_key = FutexKey::new(futex_addr); let futex_item = FUTEX_TABLE.lock().unwrap().get_item(futex_key)?; let count = futex_item.wake(max_count); @@ -167,12 +167,12 @@ impl FutexTable { item.clone() } - pub fn get_item(&mut self, key: FutexKey) -> Result { + pub fn get_item(&mut self, key: FutexKey) -> Result { let table = &mut self.table; table .get_mut(&key) .map(|item| item.clone()) - .ok_or_else(|| Error::new(Errno::ENOENT, "futex key cannot be found")) + .ok_or_else(|| errno!(ENOENT, "futex key cannot be found")) } pub fn put_item(&mut self, item: FutexItemRef) { diff --git a/src/libos/src/process/process.rs b/src/libos/src/process/process.rs index 2a67da51..c71302d4 100644 --- a/src/libos/src/process/process.rs +++ b/src/libos/src/process/process.rs @@ -33,7 +33,7 @@ impl Process { vm_ref: ProcessVMRef, file_table_ref: FileTableRef, rlimits_ref: ResourceLimitsRef, - ) -> Result<(pid_t, ProcessRef), Error> { + ) -> Result<(pid_t, ProcessRef)> { let new_pid = process_table::alloc_pid(); let new_process_ref = Arc::new(SgxMutex::new(Process { task: task, diff --git a/src/libos/src/process/process_table.rs b/src/libos/src/process/process_table.rs index 0c624dd4..b0e3056e 100644 --- a/src/libos/src/process/process_table.rs +++ b/src/libos/src/process/process_table.rs @@ -14,13 +14,13 @@ pub fn remove(pid: pid_t) { PROCESS_TABLE.lock().unwrap().remove(&pid); } -pub fn get(pid: pid_t) -> Result { +pub fn get(pid: pid_t) -> Result { PROCESS_TABLE .lock() .unwrap() .get(&pid) .map(|pr| pr.clone()) - .ok_or_else(|| Error::new(Errno::ENOENT, "process not found")) + .ok_or_else(|| errno!(ENOENT, "process not found")) } static NEXT_PID: AtomicU32 = AtomicU32::new(1); diff --git a/src/libos/src/process/sched.rs b/src/libos/src/process/sched.rs index 5a115c07..8acc6bf3 100644 --- a/src/libos/src/process/sched.rs +++ b/src/libos/src/process/sched.rs @@ -61,7 +61,7 @@ impl CpuSet { } impl std::fmt::LowerHex for CpuSet { - fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result { for byte in &(self.vec) { try!(fmtr.write_fmt(format_args!("{:02x}", byte))); } @@ -70,7 +70,7 @@ impl std::fmt::LowerHex for CpuSet { } impl std::fmt::UpperHex for CpuSet { - fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result { for byte in &(self.vec) { try!(fmtr.write_fmt(format_args!("{:02X}", byte))); } @@ -78,14 +78,14 @@ impl std::fmt::UpperHex for CpuSet { } } -fn find_host_tid(pid: pid_t) -> Result { +fn find_host_tid(pid: pid_t) -> Result { let process_ref = if pid == 0 { get_current() } else { get(pid)? }; let mut process = process_ref.lock().unwrap(); let host_tid = process.get_host_tid(); Ok(host_tid) } -pub fn do_sched_getaffinity(pid: pid_t, cpu_set: &mut CpuSet) -> Result { +pub fn do_sched_getaffinity(pid: pid_t, cpu_set: &mut CpuSet) -> Result { let host_tid = match pid { 0 => 0, _ => find_host_tid(pid)?, @@ -98,13 +98,13 @@ pub fn do_sched_getaffinity(pid: pid_t, cpu_set: &mut CpuSet) -> Result Result { +pub fn do_sched_setaffinity(pid: pid_t, cpu_set: &CpuSet) -> Result { let host_tid = match pid { 0 => 0, _ => find_host_tid(pid)?, @@ -117,8 +117,8 @@ pub fn do_sched_setaffinity(pid: pid_t, cpu_set: &CpuSet) -> Result ocall_sched_setaffinity(&mut ret, &mut error, host_tid as i32, cpusize, buf); } if (ret < 0) { - let errno = Errno::from_errno(error); - return errno!(errno, "ocall_sched_setaffinity failed"); + let errno = Errno::from(error as u32); + return_errno!(errno, "ocall_sched_setaffinity failed"); } Ok(ret) } diff --git a/src/libos/src/process/spawn/elf_helper.rs b/src/libos/src/process/spawn/elf_helper.rs index 14c69214..81bb1a50 100644 --- a/src/libos/src/process/spawn/elf_helper.rs +++ b/src/libos/src/process/spawn/elf_helper.rs @@ -13,7 +13,7 @@ pub struct ProgramHeaderInfo { pub entry_num: usize, } -pub fn get_program_header_info(elf_file: &ElfFile) -> Result { +pub fn get_program_header_info(elf_file: &ElfFile) -> Result { let elf_header = &elf_file.header.pt2; Ok(ProgramHeaderInfo { addr: elf_header.ph_offset() as usize, @@ -22,37 +22,37 @@ pub fn get_program_header_info(elf_file: &ElfFile) -> Result Result<(), Error> { +pub fn print_program_headers(elf_file: &ElfFile) -> Result<()> { println!("Program headers:"); let ph_iter = elf_file.program_iter(); for sect in ph_iter { program::sanity_check(sect, &elf_file) - .map_err(|e| (Errno::ENOEXEC, "Sanity check for program header failed"))?; + .map_err(|e| errno!(ENOEXEC, "sanity check for program header failed"))?; println!("\t{:?}", sect.get_type()); } Ok(()) } -pub fn print_sections(elf_file: &ElfFile) -> Result<(), Error> { +pub fn print_sections(elf_file: &ElfFile) -> Result<()> { println!("Sections:"); let mut sect_iter = elf_file.section_iter(); sect_iter.next(); // Skip the first, dummy section for sect in sect_iter { sections::sanity_check(sect, &elf_file) - .map_err(|e| (Errno::ENOEXEC, "Sanity check for program header failed"))?; + .map_err(|e| errno!(ENOEXEC, "sanity check for program header failed"))?; let sec_name = sect .get_name(&elf_file) - .map_err(|e| (Errno::ENOEXEC, "Failed to get section name"))?; + .map_err(|e| errno!(ENOEXEC, "failed to get section name"))?; println!("\t{}\n{:?}", sec_name, sect); } Ok(()) } -pub fn print_rela_plt_section(elf_file: &ElfFile) -> Result<(), Error> { +pub fn print_rela_plt_section(elf_file: &ElfFile) -> Result<()> { let rela_entries = get_rela_entries(elf_file, ".rela.plt") - .map_err(|e| (Errno::ENOEXEC, "Failed to get .pltrel entries"))?; + .map_err(|e| errno!(ENOEXEC, "failed to get .pltrel entries"))?; let dynsym_entries = get_dynsym_entries(elf_file) - .map_err(|e| (Errno::ENOEXEC, "Failed to get .dynsym entries"))?; + .map_err(|e| errno!(ENOEXEC, "failed to get .dynsym entries"))?; println!(".rela.plt section:"); for entry in rela_entries { @@ -68,15 +68,13 @@ pub fn print_rela_plt_section(elf_file: &ElfFile) -> Result<(), Error> { let dynsym_entry = &dynsym_entries[symidx]; let dynsym_name = dynsym_entry .get_name(&elf_file) - .map_err(|e| (Errno::ENOEXEC, "Failed to get the name of a dynamic symbol"))?; + .map_err(|e| errno!(ENOEXEC, "failed to get the name of a dynamic symbol"))?; println!("\t\t{} = {:?}", dynsym_name, dynsym_entry); } Ok(()) } -pub fn get_data_program_header<'b, 'a: 'b>( - elf_file: &'b ElfFile<'a>, -) -> Result, Error> { +pub fn get_data_program_header<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result> { let mut ph_iter = elf_file.program_iter(); ph_iter .find(|&ph| { @@ -85,12 +83,10 @@ pub fn get_data_program_header<'b, 'a: 'b>( && ph.flags().is_write() && ph.flags().is_read() }) - .ok_or_else(|| (Errno::ENOEXEC, "Failed to get the data segment").into()) + .ok_or_else(|| errno!(ENOEXEC, "failed to get the data segment")) } -pub fn get_code_program_header<'b, 'a: 'b>( - elf_file: &'b ElfFile<'a>, -) -> Result, Error> { +pub fn get_code_program_header<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result> { let mut ph_iter = elf_file.program_iter(); ph_iter .find(|&ph| { @@ -99,15 +95,15 @@ pub fn get_code_program_header<'b, 'a: 'b>( && !ph.flags().is_write() && ph.flags().is_read() }) - .ok_or_else(|| (Errno::ENOEXEC, "Failed to get the code segment").into()) + .ok_or_else(|| errno!(ENOEXEC, "failed to get the code segment")) } -pub fn get_start_address<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result { +pub fn get_start_address<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result { let elf_header = &elf_file.header.pt2; Ok(elf_header.entry_point() as usize) } -pub fn get_sym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<&'a [Entry64], Error> { +pub fn get_sym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<&'a [Entry64]> { elf_file .find_section_by_name(".symtab") .and_then(|symtab_section| symtab_section.get_data(&elf_file).ok()) @@ -115,13 +111,13 @@ pub fn get_sym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<&'a [Ent sections::SectionData::SymbolTable64(entries) => Some(entries), _ => None, }) - .ok_or_else(|| (Errno::ENOEXEC, "Failed get the symbol entries").into()) + .ok_or_else(|| errno!(ENOEXEC, "failed get the symbol entries")) } pub fn get_rela_entries<'b, 'a: 'b>( elf_file: &'b ElfFile<'a>, sec_name: &'b str, -) -> Result<&'a [Rela], Error> { +) -> Result<&'a [Rela]> { elf_file .find_section_by_name(sec_name) .and_then(|plt_rela_section| plt_rela_section.get_data(&elf_file).ok()) @@ -129,12 +125,10 @@ pub fn get_rela_entries<'b, 'a: 'b>( sections::SectionData::Rela64(entries) => Some(entries), _ => None, }) - .ok_or_else(|| (Errno::ENOEXEC, "Failed to get .rela.plt entries").into()) + .ok_or_else(|| errno!(ENOEXEC, "failed to get .rela.plt entries")) } -pub fn get_dynsym_entries<'b, 'a: 'b>( - elf_file: &'b ElfFile<'a>, -) -> Result<&'a [DynEntry64], Error> { +pub fn get_dynsym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<&'a [DynEntry64]> { elf_file .find_section_by_name(".dynsym") .and_then(|dynamic_section| dynamic_section.get_data(&elf_file).ok()) @@ -142,5 +136,5 @@ pub fn get_dynsym_entries<'b, 'a: 'b>( sections::SectionData::DynSymbolTable64(entries) => Some(entries), _ => None, }) - .ok_or_else(|| (Errno::ENOEXEC, "Failed to get .dynsym entries").into()) + .ok_or_else(|| errno!(ENOEXEC, "failed to get .dynsym entries")) } diff --git a/src/libos/src/process/spawn/init_stack.rs b/src/libos/src/process/spawn/init_stack.rs index 40e70e96..5bcaf51a 100644 --- a/src/libos/src/process/spawn/init_stack.rs +++ b/src/libos/src/process/spawn/init_stack.rs @@ -53,7 +53,7 @@ pub fn do_init( argv: &[CString], envp: &[CString], auxtbl: &AuxTable, -) -> Result { +) -> Result { let stack_buf = unsafe { StackBuf::new(stack_top, init_area_size)? }; let envp_cloned = clone_cstrings_on_stack(&stack_buf, envp)?; let argv_cloned = clone_cstrings_on_stack(&stack_buf, argv)?; @@ -75,9 +75,9 @@ pub struct StackBuf { } impl StackBuf { - pub unsafe fn new(stack_top: usize, stack_size: usize) -> Result { + pub unsafe fn new(stack_top: usize, stack_size: usize) -> Result { if stack_top % 16 != 0 || stack_size == 0 || stack_top < stack_size { - return errno!(EINVAL, "Invalid stack range"); + return_errno!(EINVAL, "Invalid stack range"); }; Ok(StackBuf { stack_top: stack_top, @@ -86,7 +86,7 @@ impl StackBuf { }) } - pub fn put(&self, val: u64) -> Result<*const u64, Error> { + pub fn put(&self, val: u64) -> Result<*const u64> { let val_ptr = self.alloc(8, 8)? as *mut u64; unsafe { ptr::write(val_ptr, val); @@ -94,7 +94,7 @@ impl StackBuf { Ok(val_ptr as *const u64) } - pub fn put_slice(&self, vals: &[T]) -> Result<*const T, Error> + pub fn put_slice(&self, vals: &[T]) -> Result<*const T> where T: Copy, { @@ -120,7 +120,7 @@ impl StackBuf { Ok(base_ptr as *const T) } - pub fn put_cstr(&self, cstr: &CStr) -> Result<*const u8, Error> { + pub fn put_cstr(&self, cstr: &CStr) -> Result<*const u8> { let bytes = cstr.to_bytes_with_nul(); self.put_slice(bytes) } @@ -129,12 +129,12 @@ impl StackBuf { self.stack_pos.get() } - fn alloc(&self, size: usize, align: usize) -> Result<*mut u8, Error> { + fn alloc(&self, size: usize, align: usize) -> Result<*mut u8> { let new_pos = { let old_pos = self.stack_pos.get(); let new_pos = align_down(old_pos - size, align); if new_pos < self.stack_bottom { - return errno!(ENOMEM, "No enough space in buffer"); + return_errno!(ENOMEM, "No enough space in buffer"); } new_pos }; @@ -147,7 +147,7 @@ impl StackBuf { fn clone_cstrings_on_stack<'a, 'b>( stack: &'a StackBuf, cstrings: &'b [CString], -) -> Result, Error> { +) -> Result> { let mut cstrs_cloned = Vec::new(); for cs in cstrings.iter().rev() { let cstrp_cloned = stack.put_cstr(cs)?; @@ -158,7 +158,7 @@ fn clone_cstrings_on_stack<'a, 'b>( Ok(cstrs_cloned) } -fn dump_auxtbl_on_stack<'a, 'b>(stack: &'a StackBuf, auxtbl: &'b AuxTable) -> Result<(), Error> { +fn dump_auxtbl_on_stack<'a, 'b>(stack: &'a StackBuf, auxtbl: &'b AuxTable) -> Result<()> { // For every key-value pair, dump the value first, then the key stack.put(0 as u64); stack.put(AuxKey::AT_NULL as u64); @@ -169,10 +169,7 @@ fn dump_auxtbl_on_stack<'a, 'b>(stack: &'a StackBuf, auxtbl: &'b AuxTable) -> Re Ok(()) } -fn dump_cstrptrs_on_stack<'a, 'b>( - stack: &'a StackBuf, - strptrs: &'b [&'a CStr], -) -> Result<(), Error> { +fn dump_cstrptrs_on_stack<'a, 'b>(stack: &'a StackBuf, strptrs: &'b [&'a CStr]) -> Result<()> { stack.put(0 as u64); // End with a NULL pointer for sp in strptrs.iter().rev() { stack.put(sp.as_ptr() as u64); @@ -233,9 +230,9 @@ impl AuxTable { } impl AuxTable { - pub fn set(&mut self, key: AuxKey, val: u64) -> Result<(), Error> { + pub fn set(&mut self, key: AuxKey, val: u64) -> Result<()> { if key == AuxKey::AT_NULL || key == AuxKey::AT_IGNORE { - return errno!(EINVAL, "Illegal key"); + return_errno!(EINVAL, "Illegal key"); } self.table .entry(key) diff --git a/src/libos/src/process/spawn/init_vm.rs b/src/libos/src/process/spawn/init_vm.rs index b1e7bf29..8dca7986 100644 --- a/src/libos/src/process/spawn/init_vm.rs +++ b/src/libos/src/process/spawn/init_vm.rs @@ -8,7 +8,7 @@ pub fn do_init( elf_buf: &[u8], ldso_elf_file: &ElfFile, ldso_elf_buf: &[u8], -) -> Result { +) -> Result { // Alloc all virtual memory areas let mut code_seg = get_code_segment(elf_file)?; let mut data_seg = get_data_segment(elf_file)?; @@ -34,7 +34,8 @@ pub fn do_init( let mut process_vm = ProcessVMBuilder::new(code_size, data_size) .ldso_code_size(ldso_code_size) .ldso_data_size(ldso_data_size) - .build()?; + .build() + .cause_err(|e| errno!(e.errno(), "failed to create process VM"))?; // Load code and data let process_base_addr = process_vm.get_code_range().start(); @@ -57,7 +58,7 @@ pub fn do_init( Ok(process_vm) } -fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile) -> Result<(), Error> { +fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile) -> Result<()> { let rela_entries = elf_helper::get_rela_entries(elf_file, ".rela.dyn")?; for rela_entry in rela_entries { /* @@ -84,7 +85,7 @@ fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile) -> Result<(), Err Ok(()) } /* -fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile) -> Result<(), Error> { +fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile) -> Result<()> { let syscall_addr = __occlum_syscall as *const () as usize; let rela_entries = elf_helper::get_rela_entries(elf_file, ".rela.plt")?; diff --git a/src/libos/src/process/spawn/mod.rs b/src/libos/src/process/spawn/mod.rs index c8db7397..03273df0 100644 --- a/src/libos/src/process/spawn/mod.rs +++ b/src/libos/src/process/spawn/mod.rs @@ -38,17 +38,23 @@ pub fn do_spawn>( envp: &[CString], file_actions: &[FileAction], parent_ref: &ProcessRef, -) -> Result { +) -> Result { let mut elf_buf = { let path = elf_path.as_ref().to_str().unwrap(); - let inode = parent_ref.lock().unwrap().lookup_inode(path)?; - inode.read_as_vec()? + let inode = parent_ref + .lock() + .unwrap() + .lookup_inode(path) + .map_err(|e| errno!(e.errno(), "cannot find the executable"))?; + inode + .read_as_vec() + .map_err(|e| errno!(e.errno(), "failed to read the executable ELF"))? }; let elf_file = { - let elf_file = - ElfFile::new(&elf_buf).map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?; + let elf_file = ElfFile::new(&elf_buf) + .map_err(|e| errno!(ENOEXEC, "failed to parse the executable ELF"))?; header::sanity_check(&elf_file) - .map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?; + .map_err(|e| errno!(ENOEXEC, "failed to parse the executable ELF"))?; /* elf_helper::print_program_headers(&elf_file)?; elf_helper::print_sections(&elf_file)?; @@ -59,15 +65,22 @@ pub fn do_spawn>( let mut ldso_elf_buf = { let ldso_path = "/lib/ld-musl-x86_64.so.1"; - let ldso_inode = ROOT_INODE.lookup(ldso_path)?; - ldso_inode.read_as_vec()? + let ldso_inode = ROOT_INODE.lookup(ldso_path).map_err(|e| { + errno!( + e.errno(), + "cannot find the loader at /lib/ld-musl-x86_64.so.1" + ) + })?; + ldso_inode + .read_as_vec() + .map_err(|e| errno!(e.errno(), "failed to read the ld.so ELF"))? }; let ldso_elf_file = { let ldso_elf_file = ElfFile::new(&ldso_elf_buf) - .map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?; + .map_err(|e| errno!(ENOEXEC, "failed to parse the ld.so ELF"))?; header::sanity_check(&ldso_elf_file) - .map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?; + .map_err(|e| errno!(ENOEXEC, "failed to parse the ld.so ELF"))?; /* elf_helper::print_program_headers(&elf_file)?; elf_helper::print_sections(&elf_file)?; @@ -86,7 +99,7 @@ pub fn do_spawn>( let ldso_base_addr = vm.get_ldso_code_range().start(); let ldso_entry = ldso_base_addr + elf_helper::get_start_address(&ldso_elf_file)?; if !vm.get_ldso_code_range().contains(ldso_entry) { - return errno!(EINVAL, "Invalid program entry"); + return_errno!(EINVAL, "Invalid program entry"); } ldso_entry }; @@ -117,7 +130,7 @@ pub fn do_spawn>( Ok(new_pid) } -fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction]) -> Result { +fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction]) -> Result { // Usually, we just inherit the file table from the parent let parent = parent_ref.lock().unwrap(); let should_inherit_file_table = parent.get_pid() > 0; @@ -170,7 +183,7 @@ fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction]) -> Result Result { +fn init_auxtbl(process_vm: &ProcessVM, elf_file: &ElfFile) -> Result { let mut auxtbl = AuxTable::new(); auxtbl.set(AuxKey::AT_PAGESZ, 4096)?; auxtbl.set(AuxKey::AT_UID, 0)?; diff --git a/src/libos/src/process/spawn/segment.rs b/src/libos/src/process/spawn/segment.rs index 85dd82ef..2efac24a 100644 --- a/src/libos/src/process/spawn/segment.rs +++ b/src/libos/src/process/spawn/segment.rs @@ -29,25 +29,24 @@ impl Segment { self.mem_size } - pub fn from_program_header(ph: &ProgramHeader) -> Result { + pub fn from_program_header(ph: &ProgramHeader) -> Result { let ph64 = match ph { ProgramHeader::Ph32(ph) => { - return Err((Errno::ENOEXEC, "Not support 32-bit ELF").into()); + return_errno!(ENOEXEC, "not support 32-bit ELF"); } ProgramHeader::Ph64(ph64) => ph64, }; if ph64.align > 1 && ((ph64.offset % ph64.align) != (ph64.virtual_addr % ph64.align)) { - return Err(( - Errno::EINVAL, - "Memory address and file offset is not equal, per modulo", - ) - .into()); + return_errno!( + EINVAL, + "memory address and file offset is not equal, per modulo" + ); } if ph64.mem_size < ph64.file_size { - return Err((Errno::EINVAL, "Memory size must be greater than file size").into()); + return_errno!(EINVAL, "memory size must be greater than file size"); } if !ph64.align.is_power_of_two() { - return Err((Errno::EINVAL, "Memory alignment must be a power of two").into()); + return_errno!(EINVAL, "memory alignment must be a power of two"); } Ok(Segment { @@ -90,15 +89,15 @@ impl Segment { } } -pub fn get_code_segment(elf_file: &ElfFile) -> Result { +pub fn get_code_segment(elf_file: &ElfFile) -> Result { let code_ph = elf_helper::get_code_program_header(elf_file) - .map_err(|e| (Errno::ENOEXEC, "Failed to get the program header of code"))?; + .map_err(|e| errno!(ENOEXEC, "failed to get the program header of code"))?; Segment::from_program_header(&code_ph) } -pub fn get_data_segment(elf_file: &ElfFile) -> Result { +pub fn get_data_segment(elf_file: &ElfFile) -> Result { let data_ph = elf_helper::get_data_program_header(elf_file) - .map_err(|e| (Errno::ENOEXEC, "Failed to get the program header of code"))?; + .map_err(|e| errno!(ENOEXEC, "failed to get the program header of code"))?; Segment::from_program_header(&data_ph) } diff --git a/src/libos/src/process/task.rs b/src/libos/src/process/task.rs index a0e3beaa..16834deb 100644 --- a/src/libos/src/process/task.rs +++ b/src/libos/src/process/task.rs @@ -23,9 +23,9 @@ impl Task { user_stack_base: usize, user_stack_limit: usize, user_fs: Option, - ) -> Result { + ) -> Result { if !(user_stack_base >= user_rsp && user_rsp > user_stack_limit) { - return errno!(EINVAL, "Invalid user stack"); + return_errno!(EINVAL, "Invalid user stack"); } // Set the default user fsbase to an address on user stack, which is @@ -71,9 +71,9 @@ fn dequeue_task() -> Option { NEW_PROCESS_QUEUE.lock().unwrap().pop_front() } -pub fn run_task(host_tid: pid_t) -> Result { +pub fn run_task(host_tid: pid_t) -> Result { let new_process: ProcessRef = - dequeue_task().ok_or_else(|| (Errno::EAGAIN, "No new processes to run"))?; + dequeue_task().ok_or_else(|| errno!(EAGAIN, "no new processes to run"))?; set_current(&new_process); let (pid, task) = { diff --git a/src/libos/src/process/thread.rs b/src/libos/src/process/thread.rs index 39620167..c4ac0f93 100644 --- a/src/libos/src/process/thread.rs +++ b/src/libos/src/process/thread.rs @@ -39,7 +39,7 @@ pub fn do_clone( ptid: Option<*mut pid_t>, ctid: Option<*mut pid_t>, new_tls: Option, -) -> Result { +) -> Result { info!( "clone: flags: {:?}, stack_addr: {:?}, ptid: {:?}, ctid: {:?}, new_tls: {:?}", flags, user_rsp, ptid, ctid, new_tls @@ -107,7 +107,7 @@ pub fn do_clone( Ok(new_thread_pid) } -pub fn do_set_tid_address(tidptr: *mut pid_t) -> Result { +pub fn do_set_tid_address(tidptr: *mut pid_t) -> Result { info!("set_tid_address: tidptr: {:#x}", tidptr as usize); let current_ref = get_current(); let mut current = current_ref.lock().unwrap(); @@ -115,7 +115,7 @@ pub fn do_set_tid_address(tidptr: *mut pid_t) -> Result { Ok(current.get_tid()) } -fn guess_user_stack_bound(vm: &ProcessVM, user_rsp: usize) -> Result<&VMRange, Error> { +fn guess_user_stack_bound(vm: &ProcessVM, user_rsp: usize) -> Result<&VMRange> { // The first case is most likely if let Ok(stack_range) = vm.find_mmap_region(user_rsp) { Ok(stack_range) @@ -130,6 +130,6 @@ fn guess_user_stack_bound(vm: &ProcessVM, user_rsp: usize) -> Result<&VMRange, E } // Invalid else { - errno!(ESRCH, "invalid rsp") + return_errno!(ESRCH, "invalid rsp") } } diff --git a/src/libos/src/syscall/mod.rs b/src/libos/src/syscall/mod.rs index a2d46f92..180c3f80 100644 --- a/src/libos/src/syscall/mod.rs +++ b/src/libos/src/syscall/mod.rs @@ -9,7 +9,6 @@ use fs::*; use misc::{resource_t, rlimit_t, utsname_t}; -use prelude::*; use process::{pid_t, ChildProcessFilter, CloneFlags, CpuSet, FileAction, FutexFlags, FutexOp}; use std::ffi::{CStr, CString}; use std::ptr; @@ -22,6 +21,7 @@ use super::*; use self::consts::*; use std::any::Any; +use std::io::{Read, Seek, SeekFrom, Write}; // Use the internal syscall wrappers from sgx_tstd //use std::libc_fs as fs; @@ -302,9 +302,14 @@ pub extern "C" fn dispatch_syscall( info!("=> {:?}", ret); match ret { - Ok(code) => code as isize, - Err(e) if e.errno.as_retval() == 0 => panic!("undefined errno"), - Err(e) => e.errno.as_retval() as isize, + Ok(retval) => retval as isize, + Err(e) => { + warn!("{}", e.backtrace()); + + let retval = -(e.errno() as isize); + debug_assert!(retval == 0); + retval + } } } @@ -350,7 +355,7 @@ pub struct FdOp { path: *const i8, } -fn clone_file_actions_safely(fdop_ptr: *const FdOp) -> Result, Error> { +fn clone_file_actions_safely(fdop_ptr: *const FdOp) -> Result> { let mut file_actions = Vec::new(); let mut fdop_ptr = fdop_ptr; @@ -370,7 +375,7 @@ fn clone_file_actions_safely(fdop_ptr: *const FdOp) -> Result, E fd: fdop.fd, }, _ => { - return errno!(EINVAL, "Unknown file action command"); + return_errno!(EINVAL, "Unknown file action command"); } }; file_actions.push(file_action); @@ -387,7 +392,7 @@ fn do_spawn( argv: *const *const i8, envp: *const *const i8, fdop_list: *const FdOp, -) -> Result { +) -> Result { check_mut_ptr(child_pid_ptr)?; let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); let argv = clone_cstrings_safely(argv)?; @@ -411,7 +416,7 @@ pub fn do_clone( ptid: *mut pid_t, ctid: *mut pid_t, new_tls: usize, -) -> Result { +) -> Result { let flags = CloneFlags::from_bits_truncate(flags); check_mut_ptr(stack_addr as *mut u64)?; let ptid = { @@ -444,7 +449,7 @@ pub fn do_clone( Ok(child_pid as isize) } -pub fn do_futex(futex_addr: *const i32, futex_op: u32, futex_val: i32) -> Result { +pub fn do_futex(futex_addr: *const i32, futex_op: u32, futex_val: i32) -> Result { check_ptr(futex_addr)?; let (futex_op, futex_flags) = process::futex_op_and_flags_from_u32(futex_op)?; match futex_op { @@ -452,28 +457,28 @@ pub fn do_futex(futex_addr: *const i32, futex_op: u32, futex_val: i32) -> Result FutexOp::FUTEX_WAKE => { let max_count = { if futex_val < 0 { - return errno!(EINVAL, "the count must not be negative"); + return_errno!(EINVAL, "the count must not be negative"); } futex_val as usize }; process::futex_wake(futex_addr, max_count).map(|count| count as isize) } - _ => errno!(ENOSYS, "the futex operation is not supported"), + _ => return_errno!(ENOSYS, "the futex operation is not supported"), } } -fn do_open(path: *const i8, flags: u32, mode: u32) -> Result { +fn do_open(path: *const i8, flags: u32, mode: u32) -> Result { let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); let fd = fs::do_open(&path, flags, mode)?; Ok(fd as isize) } -fn do_close(fd: FileDesc) -> Result { +fn do_close(fd: FileDesc) -> Result { fs::do_close(fd)?; Ok(0) } -fn do_read(fd: FileDesc, buf: *mut u8, size: usize) -> Result { +fn do_read(fd: FileDesc, buf: *mut u8, size: usize) -> Result { let safe_buf = { check_mut_array(buf, size)?; unsafe { std::slice::from_raw_parts_mut(buf, size) } @@ -482,7 +487,7 @@ fn do_read(fd: FileDesc, buf: *mut u8, size: usize) -> Result { Ok(len as isize) } -fn do_write(fd: FileDesc, buf: *const u8, size: usize) -> Result { +fn do_write(fd: FileDesc, buf: *const u8, size: usize) -> Result { let safe_buf = { check_array(buf, size)?; unsafe { std::slice::from_raw_parts(buf, size) } @@ -491,10 +496,10 @@ fn do_write(fd: FileDesc, buf: *const u8, size: usize) -> Result { Ok(len as isize) } -fn do_writev(fd: FileDesc, iov: *const iovec_t, count: i32) -> Result { +fn do_writev(fd: FileDesc, iov: *const iovec_t, count: i32) -> Result { let count = { if count < 0 { - return errno!(EINVAL, "Invalid count of iovec"); + return_errno!(EINVAL, "Invalid count of iovec"); } count as usize }; @@ -516,10 +521,10 @@ fn do_writev(fd: FileDesc, iov: *const iovec_t, count: i32) -> Result Result { +fn do_readv(fd: FileDesc, iov: *mut iovec_t, count: i32) -> Result { let count = { if count < 0 { - return errno!(EINVAL, "Invalid count of iovec"); + return_errno!(EINVAL, "Invalid count of iovec"); } count as usize }; @@ -541,7 +546,7 @@ fn do_readv(fd: FileDesc, iov: *mut iovec_t, count: i32) -> Result Ok(len as isize) } -fn do_pread(fd: FileDesc, buf: *mut u8, size: usize, offset: usize) -> Result { +fn do_pread(fd: FileDesc, buf: *mut u8, size: usize, offset: usize) -> Result { let safe_buf = { check_mut_array(buf, size)?; unsafe { std::slice::from_raw_parts_mut(buf, size) } @@ -550,7 +555,7 @@ fn do_pread(fd: FileDesc, buf: *mut u8, size: usize, offset: usize) -> Result Result { +fn do_pwrite(fd: FileDesc, buf: *const u8, size: usize, offset: usize) -> Result { let safe_buf = { check_array(buf, size)?; unsafe { std::slice::from_raw_parts(buf, size) } @@ -559,7 +564,7 @@ fn do_pwrite(fd: FileDesc, buf: *const u8, size: usize, offset: usize) -> Result Ok(len as isize) } -fn do_stat(path: *const i8, stat_buf: *mut fs::Stat) -> Result { +fn do_stat(path: *const i8, stat_buf: *mut fs::Stat) -> Result { let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); check_mut_ptr(stat_buf)?; @@ -570,7 +575,7 @@ fn do_stat(path: *const i8, stat_buf: *mut fs::Stat) -> Result { Ok(0) } -fn do_fstat(fd: FileDesc, stat_buf: *mut fs::Stat) -> Result { +fn do_fstat(fd: FileDesc, stat_buf: *mut fs::Stat) -> Result { check_mut_ptr(stat_buf)?; let stat = fs::do_fstat(fd)?; @@ -580,7 +585,7 @@ fn do_fstat(fd: FileDesc, stat_buf: *mut fs::Stat) -> Result { Ok(0) } -fn do_lstat(path: *const i8, stat_buf: *mut fs::Stat) -> Result { +fn do_lstat(path: *const i8, stat_buf: *mut fs::Stat) -> Result { let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); check_mut_ptr(stat_buf)?; @@ -591,12 +596,12 @@ fn do_lstat(path: *const i8, stat_buf: *mut fs::Stat) -> Result { Ok(0) } -fn do_lseek(fd: FileDesc, offset: off_t, whence: i32) -> Result { +fn do_lseek(fd: FileDesc, offset: off_t, whence: i32) -> Result { let seek_from = match whence { 0 => { // SEEK_SET if offset < 0 { - return errno!(EINVAL, "Invalid offset"); + return_errno!(EINVAL, "Invalid offset"); } SeekFrom::Start(offset as u64) } @@ -609,7 +614,7 @@ fn do_lseek(fd: FileDesc, offset: off_t, whence: i32) -> Result { SeekFrom::End(offset) } _ => { - return errno!(EINVAL, "Invalid whence"); + return_errno!(EINVAL, "Invalid whence"); } }; @@ -617,28 +622,28 @@ fn do_lseek(fd: FileDesc, offset: off_t, whence: i32) -> Result { Ok(offset as isize) } -fn do_fsync(fd: FileDesc) -> Result { +fn do_fsync(fd: FileDesc) -> Result { fs::do_fsync(fd)?; Ok(0) } -fn do_fdatasync(fd: FileDesc) -> Result { +fn do_fdatasync(fd: FileDesc) -> Result { fs::do_fdatasync(fd)?; Ok(0) } -fn do_truncate(path: *const i8, len: usize) -> Result { +fn do_truncate(path: *const i8, len: usize) -> Result { let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); fs::do_truncate(&path, len)?; Ok(0) } -fn do_ftruncate(fd: FileDesc, len: usize) -> Result { +fn do_ftruncate(fd: FileDesc, len: usize) -> Result { fs::do_ftruncate(fd, len)?; Ok(0) } -fn do_getdents64(fd: FileDesc, buf: *mut u8, buf_size: usize) -> Result { +fn do_getdents64(fd: FileDesc, buf: *mut u8, buf_size: usize) -> Result { let safe_buf = { check_mut_array(buf, buf_size)?; unsafe { std::slice::from_raw_parts_mut(buf, buf_size) } @@ -647,7 +652,7 @@ fn do_getdents64(fd: FileDesc, buf: *mut u8, buf_size: usize) -> Result Result { +fn do_sync() -> Result { fs::do_sync()?; Ok(0) } @@ -659,14 +664,14 @@ fn do_mmap( flags: i32, fd: FileDesc, offset: off_t, -) -> Result { +) -> Result { let perms = VMPerms::from_u32(perms as u32)?; let flags = MMapFlags::from_u32(flags as u32)?; let addr = vm::do_mmap(addr, size, perms, flags, fd, offset as usize)?; Ok(addr as isize) } -fn do_munmap(addr: usize, size: usize) -> Result { +fn do_munmap(addr: usize, size: usize) -> Result { vm::do_munmap(addr, size)?; Ok(0) } @@ -677,22 +682,22 @@ fn do_mremap( new_size: usize, flags: i32, new_addr: usize, -) -> Result { +) -> Result { warn!("mremap: not implemented!"); - errno!(ENOSYS, "not supported yet") + return_errno!(ENOSYS, "not supported yet") } -fn do_mprotect(addr: usize, len: usize, prot: u32) -> Result { +fn do_mprotect(addr: usize, len: usize, prot: u32) -> Result { // TODO: implement it Ok(0) } -fn do_brk(new_brk_addr: usize) -> Result { +fn do_brk(new_brk_addr: usize) -> Result { let ret_brk_addr = vm::do_brk(new_brk_addr)?; Ok(ret_brk_addr as isize) } -fn do_wait4(pid: i32, _exit_status: *mut i32) -> Result { +fn do_wait4(pid: i32, _exit_status: *mut i32) -> Result { if !_exit_status.is_null() { check_mut_ptr(_exit_status)?; } @@ -723,45 +728,45 @@ fn do_wait4(pid: i32, _exit_status: *mut i32) -> Result { } } -fn do_getpid() -> Result { +fn do_getpid() -> Result { let pid = process::do_getpid(); Ok(pid as isize) } -fn do_gettid() -> Result { +fn do_gettid() -> Result { let tid = process::do_gettid(); Ok(tid as isize) } -fn do_getppid() -> Result { +fn do_getppid() -> Result { let ppid = process::do_getppid(); Ok(ppid as isize) } -fn do_getpgid() -> Result { +fn do_getpgid() -> Result { let pgid = process::do_getpgid(); Ok(pgid as isize) } // TODO: implement uid, gid, euid, egid -fn do_getuid() -> Result { +fn do_getuid() -> Result { Ok(0) } -fn do_getgid() -> Result { +fn do_getgid() -> Result { Ok(0) } -fn do_geteuid() -> Result { +fn do_geteuid() -> Result { Ok(0) } -fn do_getegid() -> Result { +fn do_getegid() -> Result { Ok(0) } -fn do_pipe2(fds_u: *mut i32, flags: u32) -> Result { +fn do_pipe2(fds_u: *mut i32, flags: u32) -> Result { check_mut_array(fds_u, 2)?; // TODO: how to deal with open flags??? let fds = fs::do_pipe2(flags as u32)?; @@ -772,23 +777,23 @@ fn do_pipe2(fds_u: *mut i32, flags: u32) -> Result { Ok(0) } -fn do_dup(old_fd: FileDesc) -> Result { +fn do_dup(old_fd: FileDesc) -> Result { let new_fd = fs::do_dup(old_fd)?; Ok(new_fd as isize) } -fn do_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result { +fn do_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result { let new_fd = fs::do_dup2(old_fd, new_fd)?; Ok(new_fd as isize) } -fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result { +fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result { let new_fd = fs::do_dup3(old_fd, new_fd, flags)?; Ok(new_fd as isize) } // TODO: handle tz: timezone_t -fn do_gettimeofday(tv_u: *mut timeval_t) -> Result { +fn do_gettimeofday(tv_u: *mut timeval_t) -> Result { check_mut_ptr(tv_u)?; let tv = time::do_gettimeofday(); unsafe { @@ -797,7 +802,7 @@ fn do_gettimeofday(tv_u: *mut timeval_t) -> Result { Ok(0) } -fn do_clock_gettime(clockid: clockid_t, ts_u: *mut timespec_t) -> Result { +fn do_clock_gettime(clockid: clockid_t, ts_u: *mut timespec_t) -> Result { check_mut_ptr(ts_u)?; let clockid = time::ClockID::from_raw(clockid)?; let ts = time::do_clock_gettime(clockid)?; @@ -829,15 +834,15 @@ fn do_unknown( arg3: isize, arg4: isize, arg5: isize, -) -> Result { +) -> Result { warn!( "unknown or unsupported syscall (# = {}): {:#x}, {:#x}, {:#x}, {:#x}, {:#x}, {:#x}", num, arg0, arg1, arg2, arg3, arg4, arg5 ); - errno!(ENOSYS, "Unknown syscall") + return_errno!(ENOSYS, "Unknown syscall") } -fn do_getcwd(buf: *mut u8, size: usize) -> Result { +fn do_getcwd(buf: *mut u8, size: usize) -> Result { let safe_buf = { check_mut_array(buf, size)?; unsafe { std::slice::from_raw_parts_mut(buf, size) } @@ -846,20 +851,20 @@ fn do_getcwd(buf: *mut u8, size: usize) -> Result { let mut proc = proc_ref.lock().unwrap(); let cwd = proc.get_cwd(); if cwd.len() + 1 > safe_buf.len() { - return errno!(ERANGE, "buf is not long enough"); + return_errno!(ERANGE, "buf is not long enough"); } safe_buf[..cwd.len()].copy_from_slice(cwd.as_bytes()); safe_buf[cwd.len()] = 0; Ok(buf as isize) } -fn do_chdir(path: *const i8) -> Result { +fn do_chdir(path: *const i8) -> Result { let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); fs::do_chdir(&path)?; Ok(0) } -fn do_rename(oldpath: *const i8, newpath: *const i8) -> Result { +fn do_rename(oldpath: *const i8, newpath: *const i8) -> Result { let oldpath = clone_cstring_safely(oldpath)? .to_string_lossy() .into_owned(); @@ -870,19 +875,19 @@ fn do_rename(oldpath: *const i8, newpath: *const i8) -> Result { Ok(0) } -fn do_mkdir(path: *const i8, mode: usize) -> Result { +fn do_mkdir(path: *const i8, mode: usize) -> Result { let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); fs::do_mkdir(&path, mode)?; Ok(0) } -fn do_rmdir(path: *const i8) -> Result { +fn do_rmdir(path: *const i8) -> Result { let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); fs::do_rmdir(&path)?; Ok(0) } -fn do_link(oldpath: *const i8, newpath: *const i8) -> Result { +fn do_link(oldpath: *const i8, newpath: *const i8) -> Result { let oldpath = clone_cstring_safely(oldpath)? .to_string_lossy() .into_owned(); @@ -893,13 +898,13 @@ fn do_link(oldpath: *const i8, newpath: *const i8) -> Result { Ok(0) } -fn do_unlink(path: *const i8) -> Result { +fn do_unlink(path: *const i8) -> Result { let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); fs::do_unlink(&path)?; Ok(0) } -fn do_readlink(path: *const i8, buf: *mut u8, size: usize) -> Result { +fn do_readlink(path: *const i8, buf: *mut u8, size: usize) -> Result { let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); let buf = { check_array(buf, size)?; @@ -914,7 +919,7 @@ fn do_sendfile( in_fd: FileDesc, offset_ptr: *mut off_t, count: usize, -) -> Result { +) -> Result { let offset = if offset_ptr.is_null() { None } else { @@ -931,12 +936,12 @@ fn do_sendfile( Ok(len as isize) } -fn do_fcntl(fd: FileDesc, cmd: u32, arg: u64) -> Result { +fn do_fcntl(fd: FileDesc, cmd: u32, arg: u64) -> Result { let cmd = FcntlCmd::from_raw(cmd, arg)?; fs::do_fcntl(fd, &cmd) } -fn do_ioctl(fd: FileDesc, cmd: c_int, argp: *mut c_int) -> Result { +fn do_ioctl(fd: FileDesc, cmd: c_int, argp: *mut c_int) -> Result { info!("ioctl: fd: {}, cmd: {}, argp: {:?}", fd, cmd, argp); let current_ref = process::get_current(); let mut proc = current_ref.lock().unwrap(); @@ -950,30 +955,30 @@ fn do_ioctl(fd: FileDesc, cmd: c_int, argp: *mut c_int) -> Result Ok(0) } else { warn!("ioctl is unimplemented"); - errno!(ENOSYS, "ioctl is unimplemented") + return_errno!(ENOSYS, "ioctl is unimplemented") } } -fn do_arch_prctl(code: u32, addr: *mut usize) -> Result { +fn do_arch_prctl(code: u32, addr: *mut usize) -> Result { let code = process::ArchPrctlCode::from_u32(code)?; check_mut_ptr(addr)?; process::do_arch_prctl(code, addr).map(|_| 0) } -fn do_set_tid_address(tidptr: *mut pid_t) -> Result { +fn do_set_tid_address(tidptr: *mut pid_t) -> Result { check_mut_ptr(tidptr)?; process::do_set_tid_address(tidptr).map(|tid| tid as isize) } -fn do_sched_getaffinity(pid: pid_t, cpusize: size_t, buf: *mut c_uchar) -> Result { +fn do_sched_getaffinity(pid: pid_t, cpusize: size_t, buf: *mut c_uchar) -> Result { // Construct safe Rust types let mut buf_slice = { check_mut_array(buf, cpusize)?; if cpusize == 0 { - return errno!(EINVAL, "cpuset size must be greater than zero"); + return_errno!(EINVAL, "cpuset size must be greater than zero"); } if buf as *const _ == std::ptr::null() { - return errno!(EFAULT, "cpuset mask must NOT be null"); + return_errno!(EFAULT, "cpuset mask must NOT be null"); } unsafe { std::slice::from_raw_parts_mut(buf, cpusize) } }; @@ -986,15 +991,15 @@ fn do_sched_getaffinity(pid: pid_t, cpusize: size_t, buf: *mut c_uchar) -> Resul Ok(ret as isize) } -fn do_sched_setaffinity(pid: pid_t, cpusize: size_t, buf: *const c_uchar) -> Result { +fn do_sched_setaffinity(pid: pid_t, cpusize: size_t, buf: *const c_uchar) -> Result { // Convert unsafe C types into safe Rust types let cpuset = { check_array(buf, cpusize)?; if cpusize == 0 { - return errno!(EINVAL, "cpuset size must be greater than zero"); + return_errno!(EINVAL, "cpuset size must be greater than zero"); } if buf as *const _ == std::ptr::null() { - return errno!(EFAULT, "cpuset mask must NOT be null"); + return_errno!(EFAULT, "cpuset mask must NOT be null"); } CpuSet::from_raw_buf(buf, cpusize) }; @@ -1004,7 +1009,7 @@ fn do_sched_setaffinity(pid: pid_t, cpusize: size_t, buf: *const c_uchar) -> Res Ok(ret as isize) } -fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result { +fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result { info!( "socket: domain: {}, socket_type: {}, protocol: {}", domain, socket_type, protocol @@ -1028,11 +1033,7 @@ fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result Result { +fn do_connect(fd: c_int, addr: *const libc::sockaddr, addr_len: libc::socklen_t) -> Result { info!( "connect: fd: {}, addr: {:?}, addr_len: {}", fd, addr, addr_len @@ -1052,7 +1053,7 @@ fn do_connect( unix_socket.connect(path)?; Ok(0) } else { - errno!(EBADF, "not a socket") + return_errno!(EBADF, "not a socket") } } @@ -1061,7 +1062,7 @@ fn do_accept4( addr: *mut libc::sockaddr, addr_len: *mut libc::socklen_t, flags: c_int, -) -> Result { +) -> Result { info!( "accept4: fd: {}, addr: {:?}, addr_len: {:?}, flags: {:#x}", fd, addr, addr_len, flags @@ -1087,11 +1088,11 @@ fn do_accept4( Ok(new_fd as isize) } else { - errno!(EBADF, "not a socket") + return_errno!(EBADF, "not a socket") } } -fn do_shutdown(fd: c_int, how: c_int) -> Result { +fn do_shutdown(fd: c_int, how: c_int) -> Result { info!("shutdown: fd: {}, how: {}", fd, how); let current_ref = process::get_current(); let mut proc = current_ref.lock().unwrap(); @@ -1100,15 +1101,11 @@ fn do_shutdown(fd: c_int, how: c_int) -> Result { let ret = try_libc!(libc::ocall::shutdown(socket.fd(), how)); Ok(ret as isize) } else { - errno!(EBADF, "not a socket") + return_errno!(EBADF, "not a socket") } } -fn do_bind( - fd: c_int, - addr: *const libc::sockaddr, - addr_len: libc::socklen_t, -) -> Result { +fn do_bind(fd: c_int, addr: *const libc::sockaddr, addr_len: libc::socklen_t) -> Result { info!("bind: fd: {}, addr: {:?}, addr_len: {}", fd, addr, addr_len); let current_ref = process::get_current(); let mut proc = current_ref.lock().unwrap(); @@ -1126,11 +1123,11 @@ fn do_bind( unix_socket.bind(path)?; Ok(0) } else { - errno!(EBADF, "not a socket") + return_errno!(EBADF, "not a socket") } } -fn do_listen(fd: c_int, backlog: c_int) -> Result { +fn do_listen(fd: c_int, backlog: c_int) -> Result { info!("listen: fd: {}, backlog: {}", fd, backlog); let current_ref = process::get_current(); let mut proc = current_ref.lock().unwrap(); @@ -1142,7 +1139,7 @@ fn do_listen(fd: c_int, backlog: c_int) -> Result { unix_socket.listen()?; Ok(0) } else { - errno!(EBADF, "not a socket") + return_errno!(EBADF, "not a socket") } } @@ -1152,7 +1149,7 @@ fn do_setsockopt( optname: c_int, optval: *const c_void, optlen: libc::socklen_t, -) -> Result { +) -> Result { info!( "setsockopt: fd: {}, level: {}, optname: {}, optval: {:?}, optlen: {:?}", fd, level, optname, optval, optlen @@ -1173,7 +1170,7 @@ fn do_setsockopt( warn!("setsockopt for unix socket is unimplemented"); Ok(0) } else { - errno!(EBADF, "not a socket") + return_errno!(EBADF, "not a socket") } } @@ -1183,7 +1180,7 @@ fn do_getsockopt( optname: c_int, optval: *mut c_void, optlen: *mut libc::socklen_t, -) -> Result { +) -> Result { info!( "getsockopt: fd: {}, level: {}, optname: {}, optval: {:?}, optlen: {:?}", fd, level, optname, optval, optlen @@ -1207,7 +1204,7 @@ fn do_getpeername( fd: c_int, addr: *mut libc::sockaddr, addr_len: *mut libc::socklen_t, -) -> Result { +) -> Result { info!( "getpeername: fd: {}, addr: {:?}, addr_len: {:?}", fd, addr, addr_len @@ -1220,12 +1217,12 @@ fn do_getpeername( Ok(ret as isize) } else if let Ok(unix_socket) = file_ref.as_unix_socket() { warn!("getpeername for unix socket is unimplemented"); - errno!( + return_errno!( ENOTCONN, "hack for php: Transport endpoint is not connected" ) } else { - errno!(EBADF, "not a socket") + return_errno!(EBADF, "not a socket") } } @@ -1233,7 +1230,7 @@ fn do_getsockname( fd: c_int, addr: *mut libc::sockaddr, addr_len: *mut libc::socklen_t, -) -> Result { +) -> Result { info!( "getsockname: fd: {}, addr: {:?}, addr_len: {:?}", fd, addr, addr_len @@ -1248,7 +1245,7 @@ fn do_getsockname( warn!("getsockname for unix socket is unimplemented"); Ok(0) } else { - errno!(EBADF, "not a socket") + return_errno!(EBADF, "not a socket") } } @@ -1259,7 +1256,7 @@ fn do_sendto( flags: c_int, addr: *const libc::sockaddr, addr_len: libc::socklen_t, -) -> Result { +) -> Result { info!( "sendto: fd: {}, base: {:?}, len: {}, addr: {:?}, addr_len: {}", fd, base, len, addr, addr_len @@ -1287,7 +1284,7 @@ fn do_recvfrom( flags: c_int, addr: *mut libc::sockaddr, addr_len: *mut libc::socklen_t, -) -> Result { +) -> Result { info!( "recvfrom: fd: {}, base: {:?}, len: {}, flags: {}, addr: {:?}, addr_len: {:?}", fd, base, len, flags, addr, addr_len @@ -1314,10 +1311,10 @@ fn do_select( writefds: *mut libc::fd_set, exceptfds: *mut libc::fd_set, timeout: *const libc::timeval, -) -> Result { +) -> Result { // check arguments if nfds < 0 || nfds >= libc::FD_SETSIZE as c_int { - return errno!(EINVAL, "nfds is negative or exceeds the resource limit"); + return_errno!(EINVAL, "nfds is negative or exceeds the resource limit"); } let nfds = nfds as usize; @@ -1354,7 +1351,7 @@ fn do_select( Ok(n as isize) } -fn do_poll(fds: *mut libc::pollfd, nfds: libc::nfds_t, timeout: c_int) -> Result { +fn do_poll(fds: *mut libc::pollfd, nfds: libc::nfds_t, timeout: c_int) -> Result { check_mut_array(fds, nfds as usize)?; let polls = unsafe { std::slice::from_raw_parts_mut(fds, nfds as usize) }; @@ -1362,14 +1359,14 @@ fn do_poll(fds: *mut libc::pollfd, nfds: libc::nfds_t, timeout: c_int) -> Result Ok(n as isize) } -fn do_epoll_create(size: c_int) -> Result { +fn do_epoll_create(size: c_int) -> Result { if size <= 0 { - return errno!(EINVAL, "size is not positive"); + return_errno!(EINVAL, "size is not positive"); } do_epoll_create1(0) } -fn do_epoll_create1(flags: c_int) -> Result { +fn do_epoll_create1(flags: c_int) -> Result { let fd = fs::do_epoll_create1(flags)?; Ok(fd as isize) } @@ -1379,7 +1376,7 @@ fn do_epoll_ctl( op: c_int, fd: c_int, event: *const libc::epoll_event, -) -> Result { +) -> Result { if !event.is_null() { check_ptr(event)?; } @@ -1392,10 +1389,10 @@ fn do_epoll_wait( events: *mut libc::epoll_event, maxevents: c_int, timeout: c_int, -) -> Result { +) -> Result { let maxevents = { if maxevents <= 0 { - return errno!(EINVAL, "maxevents <= 0"); + return_errno!(EINVAL, "maxevents <= 0"); } maxevents as usize }; @@ -1407,7 +1404,7 @@ fn do_epoll_wait( Ok(count as isize) } -fn do_uname(name: *mut utsname_t) -> Result { +fn do_uname(name: *mut utsname_t) -> Result { check_mut_ptr(name)?; let name = unsafe { &mut *name }; misc::do_uname(name).map(|_| 0) @@ -1418,7 +1415,7 @@ fn do_prlimit( resource: u32, new_limit: *const rlimit_t, old_limit: *mut rlimit_t, -) -> Result { +) -> Result { let resource = resource_t::from_u32(resource)?; let new_limit = { if new_limit != ptr::null() { @@ -1439,19 +1436,19 @@ fn do_prlimit( misc::do_prlimit(pid, resource, new_limit, old_limit).map(|_| 0) } -fn do_access(path: *const i8, mode: u32) -> Result { +fn do_access(path: *const i8, mode: u32) -> Result { let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); let mode = AccessModes::from_u32(mode)?; fs::do_access(&path, mode).map(|_| 0) } -fn do_faccessat(dirfd: i32, path: *const i8, mode: u32, flags: u32) -> Result { +fn do_faccessat(dirfd: i32, path: *const i8, mode: u32, flags: u32) -> Result { let dirfd = if dirfd >= 0 { Some(dirfd as FileDesc) } else if dirfd == AT_FDCWD { None } else { - return errno!(EINVAL, "invalid dirfd"); + return_errno!(EINVAL, "invalid dirfd"); }; let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); let mode = AccessModes::from_u32(mode)?; @@ -1461,10 +1458,10 @@ fn do_faccessat(dirfd: i32, path: *const i8, mode: u32, flags: u32) -> Result Result { +fn do_rt_sigaction() -> Result { Ok(0) } -fn do_rt_sigprocmask() -> Result { +fn do_rt_sigprocmask() -> Result { Ok(0) } diff --git a/src/libos/src/time/mod.rs b/src/libos/src/time/mod.rs index 21fb3c8a..2e1f07aa 100644 --- a/src/libos/src/time/mod.rs +++ b/src/libos/src/time/mod.rs @@ -61,7 +61,7 @@ pub enum ClockID { impl ClockID { #[deny(unreachable_patterns)] - pub fn from_raw(clockid: clockid_t) -> Result { + pub fn from_raw(clockid: clockid_t) -> Result { Ok(match clockid as i32 { 0 => ClockID::CLOCK_REALTIME, 1 => ClockID::CLOCK_MONOTONIC, @@ -71,12 +71,12 @@ impl ClockID { 5 => ClockID::CLOCK_REALTIME_COARSE, 6 => ClockID::CLOCK_MONOTONIC_COARSE, 7 => ClockID::CLOCK_BOOTTIME, - _ => return errno!(EINVAL, "invalid command"), + _ => return_errno!(EINVAL, "invalid command"), }) } } -pub fn do_clock_gettime(clockid: ClockID) -> Result { +pub fn do_clock_gettime(clockid: ClockID) -> Result { let mut sec = 0; let mut nsec = 0; unsafe { diff --git a/src/libos/src/util/log.rs b/src/libos/src/util/log.rs index 621db02c..a7fd4a63 100644 --- a/src/libos/src/util/log.rs +++ b/src/libos/src/util/log.rs @@ -2,14 +2,14 @@ use log::*; pub fn init() { static LOGGER: SimpleLogger = SimpleLogger; - log::set_logger(&LOGGER).unwrap(); - log::set_max_level(match option_env!("LOG") { + log::set_logger(&LOGGER).expect("logger cannot be set twice"); + log::set_max_level(match option_env!("LIBOS_LOG") { Some("error") => LevelFilter::Error, Some("warn") => LevelFilter::Warn, Some("info") => LevelFilter::Info, Some("debug") => LevelFilter::Debug, Some("trace") => LevelFilter::Trace, - _ => LevelFilter::Off, + _ => LevelFilter::Error, // errors are printed be default }); } @@ -22,11 +22,13 @@ impl Log for SimpleLogger { fn log(&self, record: &Record) { if self.enabled(record.metadata()) { let color = Color::from(record.level()); + // TODO: add process info println!( - "\u{1B}[{}m[{:>5}][{}] {}\u{1B}[0m", + //"\u{1B}[{}m[{:>5}][{}] {}\u{1B}[0m", + "\u{1B}[{}m[{:>5}] {}\u{1B}[0m", color as u8, record.level(), - crate::process::current_pid(), + //crate::process::current_pid(), record.args() ); } diff --git a/src/libos/src/util/mem_util.rs b/src/libos/src/util/mem_util.rs index b59d8b57..a41ab222 100644 --- a/src/libos/src/util/mem_util.rs +++ b/src/libos/src/util/mem_util.rs @@ -8,27 +8,27 @@ pub mod from_user { use super::*; /// Check the user pointer is within the readable memory range of the user process - pub fn check_ptr(user_ptr: *const T) -> Result<(), Error> { + pub fn check_ptr(user_ptr: *const T) -> Result<()> { Ok(()) } /// Check the mutable user pointer is within the writable memory of the user process - pub fn check_mut_ptr(user_ptr: *mut T) -> Result<(), Error> { + pub fn check_mut_ptr(user_ptr: *mut T) -> Result<()> { Ok(()) } /// Check the readonly array is within the readable memory of the user process - pub fn check_array(user_buf: *const T, count: usize) -> Result<(), Error> { + pub fn check_array(user_buf: *const T, count: usize) -> Result<()> { Ok(()) } /// Check the mutable array is within the writable memory of the user process - pub fn check_mut_array(user_buf: *mut T, count: usize) -> Result<(), Error> { + pub fn check_mut_array(user_buf: *mut T, count: usize) -> Result<()> { Ok(()) } /// Clone a C-string from the user process safely - pub fn clone_cstring_safely(out_ptr: *const c_char) -> Result { + pub fn clone_cstring_safely(out_ptr: *const c_char) -> Result { check_ptr(out_ptr)?; // TODO: using from_ptr directly is not safe let cstr = unsafe { CStr::from_ptr(out_ptr) }; @@ -39,7 +39,7 @@ pub mod from_user { /// 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, Error> { + pub fn clone_cstrings_safely(user_ptr: *const *const c_char) -> Result> { let mut cstrings = Vec::new(); if user_ptr == ptr::null() { return Ok(cstrings); @@ -70,17 +70,20 @@ pub mod from_untrusted { use super::*; /// Check the untrusted pointer is outside the enclave - pub fn check_ptr(out_ptr: *const T) -> Result<(), Error> { + // TODO: implement this! + pub fn check_ptr(out_ptr: *const T) -> Result<()> { Ok(()) } /// Check the untrusted array is outside the enclave - pub fn check_array(out_ptr: *const T, count: usize) -> Result<(), Error> { + // TODO: implement this! + pub fn check_array(out_ptr: *const T, count: usize) -> Result<()> { Ok(()) } /// Clone a C-string from outside the enclave - pub fn clone_cstring_safely(out_ptr: *const c_char) -> Result { + // TODO: strict check! + pub fn clone_cstring_safely(out_ptr: *const c_char) -> Result { check_ptr(out_ptr)?; // TODO: using from_ptr directly is not safe let cstr = unsafe { CStr::from_ptr(out_ptr) }; @@ -91,7 +94,8 @@ pub mod from_untrusted { /// 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, Error> { + // TODO: strict check! + pub fn clone_cstrings_safely(out_ptr: *const *const c_char) -> Result> { let mut cstrings = Vec::new(); if out_ptr == ptr::null() { return Ok(cstrings); diff --git a/src/libos/src/util/mpx_util.rs b/src/libos/src/util/mpx_util.rs index 5d309001..91b68539 100644 --- a/src/libos/src/util/mpx_util.rs +++ b/src/libos/src/util/mpx_util.rs @@ -1,9 +1,9 @@ use super::*; -pub fn mpx_enable() -> Result<(), Error> { +pub fn mpx_enable() -> Result<()> { match unsafe { __mpx_enable() } { 0 => Ok(()), - _ => errno!(EPERM, "MPX cannot be enabled"), + _ => Err(errno!(EPERM, "MPX cannot be enabled")), } } @@ -14,10 +14,10 @@ pub enum MpxReg { BND3, } -pub fn mpx_bndmk(bndreg: MpxReg, base: usize, size: usize) -> Result<(), Error> { +pub fn mpx_bndmk(bndreg: MpxReg, base: usize, size: usize) -> Result<()> { /* Check whether the upper bound overflows the max of 64-bit */ if base.checked_add(size).is_none() { - return errno!(ERANGE, "Upper bound overflows"); + return_errno!(ERANGE, "Upper bound overflows"); } match bndreg { diff --git a/src/libos/src/util/ring_buf.rs b/src/libos/src/util/ring_buf.rs index 591f3218..72560a8e 100644 --- a/src/libos/src/util/ring_buf.rs +++ b/src/libos/src/util/ring_buf.rs @@ -122,7 +122,7 @@ impl Drop for RingBufInner { } impl RingBufReader { - pub fn read(&self, buf: &mut [u8]) -> Result { + pub fn read(&self, buf: &mut [u8]) -> Result { let mut tail = self.inner.get_tail(); let mut buf_remain = buf.len(); let mut buf_pos = 0; @@ -179,9 +179,9 @@ impl Drop for RingBufReader { } impl RingBufWriter { - pub fn write(&self, buf: &[u8]) -> Result { + pub fn write(&self, buf: &[u8]) -> Result { if self.inner.is_closed() { - return errno!(EPIPE, "Reader has been closed"); + return_errno!(EPIPE, "Reader has been closed"); } let mut head = self.inner.get_head(); diff --git a/src/libos/src/vm/mod.rs b/src/libos/src/vm/mod.rs index c5e0bc15..d3c463aa 100644 --- a/src/libos/src/vm/mod.rs +++ b/src/libos/src/vm/mod.rs @@ -1,5 +1,5 @@ +use super::*; use fs::{File, FileDesc, FileRef}; -use prelude::*; use process::{get_current, Process, ProcessRef}; use std::fmt; @@ -17,7 +17,7 @@ pub fn do_mmap( flags: MMapFlags, fd: FileDesc, offset: usize, -) -> Result { +) -> Result { if flags.contains(MMapFlags::MAP_ANONYMOUS) { info!( "mmap: addr: {:#x}, size: {:#x}, perms: {:?}, flags: {:?}", @@ -39,7 +39,7 @@ pub fn do_mmap( current_vm.mmap(addr, size, perms, flags, fd, offset) } -pub fn do_munmap(addr: usize, size: usize) -> Result<(), Error> { +pub fn do_munmap(addr: usize, size: usize) -> Result<()> { info!("munmap: addr: {:#x}, size: {:#x}", addr, size); let mut current_vm_ref = { let current_ref = get_current(); @@ -50,7 +50,7 @@ pub fn do_munmap(addr: usize, size: usize) -> Result<(), Error> { current_vm.munmap(addr, size) } -pub fn do_brk(addr: usize) -> Result { +pub fn do_brk(addr: usize) -> Result { info!("brk: addr: {:#x}", addr); let current_ref = get_current(); let current_process = current_ref.lock().unwrap(); diff --git a/src/libos/src/vm/process_vm.rs b/src/libos/src/vm/process_vm.rs index 91f82aa8..1954e1f1 100644 --- a/src/libos/src/vm/process_vm.rs +++ b/src/libos/src/vm/process_vm.rs @@ -41,7 +41,7 @@ impl ProcessVMBuilder { impl_setter_for_process_vm_builder!(stack_size); impl_setter_for_process_vm_builder!(mmap_size); - pub fn build(self) -> Result { + pub fn build(self) -> Result { self.validate()?; let code_size = self.code_size; @@ -111,7 +111,7 @@ impl ProcessVMBuilder { } // TODO: implement this! - fn validate(&self) -> Result<(), Error> { + fn validate(&self) -> Result<()> { Ok(()) } } @@ -191,16 +191,16 @@ impl ProcessVM { self.brk } - pub fn brk(&mut self, new_brk: usize) -> Result { + pub fn brk(&mut self, new_brk: usize) -> Result { let heap_start = self.heap_range.start(); let heap_end = self.heap_range.end(); if new_brk == 0 { return Ok(self.get_brk()); } else if new_brk < heap_start { - return errno!(EINVAL, "New brk address is too low"); + return_errno!(EINVAL, "New brk address is too low"); } else if new_brk > heap_end { - return errno!(EINVAL, "New brk address is too high"); + return_errno!(EINVAL, "New brk address is too high"); } if self.brk < new_brk { @@ -219,11 +219,11 @@ impl ProcessVM { flags: MMapFlags, fd: FileDesc, offset: usize, - ) -> Result { + ) -> Result { let addr_option = { if flags.contains(MMapFlags::MAP_FIXED) { if !self.process_range.range().contains(addr) { - return errno!(EINVAL, "Beyond valid memory range"); + return_errno!(EINVAL, "Beyond valid memory range"); } VMMapAddr::Fixed(addr) } else { @@ -256,11 +256,11 @@ impl ProcessVM { Ok(mmap_addr) } - pub fn munmap(&mut self, addr: usize, size: usize) -> Result<(), Error> { + pub fn munmap(&mut self, addr: usize, size: usize) -> Result<()> { self.mmap_manager.munmap(addr, size) } - pub fn find_mmap_region(&self, addr: usize) -> Result<&VMRange, Error> { + pub fn find_mmap_region(&self, addr: usize) -> Result<&VMRange> { self.mmap_manager.find_mmap_region(addr) } } @@ -289,9 +289,9 @@ bitflags! { } impl MMapFlags { - pub fn from_u32(bits: u32) -> Result { + pub fn from_u32(bits: u32) -> Result { // TODO: detect non-supporting flags - MMapFlags::from_bits(bits).ok_or_else(|| (Errno::EINVAL, "Unknown mmap flags").into()) + MMapFlags::from_bits(bits).ok_or_else(|| errno!(EINVAL, "unknown mmap flags")) } } @@ -316,8 +316,8 @@ impl VMPerms { self.contains(VMPerms::EXEC) } - pub fn from_u32(bits: u32) -> Result { - VMPerms::from_bits(bits).ok_or_else(|| (Errno::EINVAL, "Unknown permission bits").into()) + pub fn from_u32(bits: u32) -> Result { + VMPerms::from_bits(bits).ok_or_else(|| errno!(EINVAL, "unknown permission bits")) } } diff --git a/src/libos/src/vm/user_space_vm.rs b/src/libos/src/vm/user_space_vm.rs index cf6643fe..096240a7 100644 --- a/src/libos/src/vm/user_space_vm.rs +++ b/src/libos/src/vm/user_space_vm.rs @@ -8,12 +8,12 @@ pub struct UserSpaceVMManager { } impl UserSpaceVMManager { - pub unsafe fn from(addr: usize, size: usize) -> Result { + pub unsafe fn from(addr: usize, size: usize) -> Result { let vm_manager = Arc::new(SgxMutex::new(VMManager::from(addr, size)?)); Ok(UserSpaceVMManager { vm_manager }) } - pub fn alloc(&self, size: usize) -> Result { + pub fn alloc(&self, size: usize) -> Result { let user_vm_range = unsafe { let mmap_options = VMMapOptionsBuilder::default().size(size).build()?; diff --git a/src/libos/src/vm/vm_manager.rs b/src/libos/src/vm/vm_manager.rs index 369cc35c..a3744e9a 100644 --- a/src/libos/src/vm/vm_manager.rs +++ b/src/libos/src/vm/vm_manager.rs @@ -1,5 +1,4 @@ use super::*; -use std::slice; #[derive(Clone, Debug)] pub enum VMInitializer { @@ -15,7 +14,7 @@ impl Default for VMInitializer { } impl VMInitializer { - pub fn initialize(&self, buf: &mut [u8]) -> Result<(), Error> { + pub fn initialize(&self, buf: &mut [u8]) -> Result<()> { match self { VMInitializer::DoNothing() => { // Do nothing @@ -27,7 +26,9 @@ impl VMInitializer { } VMInitializer::LoadFromFile { file, offset } => { // TODO: make sure that read_at does not move file cursor - let len = file.read_at(*offset, buf)?; + let len = file + .read_at(*offset, buf) + .cause_err(|_| errno!(EIO, "failed to init memory from file"))?; for b in &mut buf[len..] { *b = 0; } @@ -61,20 +62,20 @@ pub struct VMMapOptions { // VMMapOptionsBuilder is generated automatically, except the build function impl VMMapOptionsBuilder { - pub fn build(&self) -> Result { + pub fn build(&self) -> Result { let size = { let size = self .size - .ok_or_else(|| (Errno::EINVAL, "Invalid size for mmap"))?; + .ok_or_else(|| errno!(EINVAL, "invalid size for mmap"))?; if size == 0 { - return errno!(EINVAL, "Invalid size for mmap"); + return_errno!(EINVAL, "invalid size for mmap"); } align_up(size, PAGE_SIZE) }; let align = { let align = self.align.unwrap_or(PAGE_SIZE); if align == 0 || align % PAGE_SIZE != 0 { - return errno!(EINVAL, "Invalid size for mmap"); + return_errno!(EINVAL, "invalid size for mmap"); } align }; @@ -89,7 +90,7 @@ impl VMMapOptionsBuilder { } VMMapAddr::Fixed(addr) => { if addr % align != 0 { - return errno!(EINVAL, "Unaligned addr for fixed mmap"); + return_errno!(EINVAL, "unaligned addr for fixed mmap"); } VMMapAddr::Fixed(addr) } @@ -129,7 +130,7 @@ pub struct VMManager { } impl VMManager { - pub fn from(addr: usize, size: usize) -> Result { + pub fn from(addr: usize, size: usize) -> Result { let range = VMRange::from(addr, addr + size)?; let sub_ranges = { let start = range.start(); @@ -145,7 +146,7 @@ impl VMManager { &self.range } - pub fn mmap(&mut self, options: &VMMapOptions) -> Result { + pub fn mmap(&mut self, options: &VMMapOptions) -> Result { // TODO: respect options.align when mmap let addr = *options.addr(); let size = *options.size(); @@ -163,7 +164,7 @@ impl VMManager { unsafe { let buf_ptr = new_subrange.start() as *mut u8; let buf_size = new_subrange.size() as usize; - let buf = slice::from_raw_parts_mut(buf_ptr, buf_size); + let buf = std::slice::from_raw_parts_mut(buf_ptr, buf_size); options.initializer.initialize(buf)?; } @@ -173,10 +174,10 @@ impl VMManager { Ok(new_subrange_addr) } - pub fn munmap(&mut self, addr: usize, size: usize) -> Result<(), Error> { + pub fn munmap(&mut self, addr: usize, size: usize) -> Result<()> { let size = { if size == 0 { - return errno!(EINVAL, "size of munmap must not be zero"); + return_errno!(EINVAL, "size of munmap must not be zero"); } align_up(size, PAGE_SIZE) }; @@ -211,22 +212,15 @@ impl VMManager { Ok(()) } - pub fn find_mmap_region(&self, addr: usize) -> Result<&VMRange, Error> { + pub fn find_mmap_region(&self, addr: usize) -> Result<&VMRange> { self.sub_ranges .iter() .find(|subrange| subrange.contains(addr)) - .ok_or(Error::new( - Errno::ESRCH, - "no mmap regions that contains the address", - )) + .ok_or_else(|| errno!(ESRCH, "no mmap regions that contains the address")) } // Find the free subrange that satisfies the constraints of size and address - fn find_free_subrange( - &mut self, - size: usize, - addr: VMMapAddr, - ) -> Result<(usize, VMRange), Error> { + fn find_free_subrange(&mut self, size: usize, addr: VMMapAddr) -> Result<(usize, VMRange)> { // TODO: reduce the complexity from O(N) to O(log(N)), where N is // the number of existing subranges. @@ -268,13 +262,13 @@ impl VMManager { // Must have free_range.start == addr VMMapAddr::Fixed(addr) => { if free_range.start() > addr { - return errno!(ENOMEM, "Not enough memory for fixed mmap"); + return_errno!(ENOMEM, "not enough memory for fixed mmap"); } if !free_range.contains(addr) { continue; } if free_range.end() - addr < size { - return errno!(ENOMEM, "Not enough memory for fixed mmap"); + return_errno!(ENOMEM, "not enough memory for fixed mmap"); } free_range.start = addr; let insert_idx = idx + 1; @@ -291,7 +285,7 @@ impl VMManager { } if result_free_range.is_none() { - return errno!(ENOMEM, "Cannot find enough memory"); + return_errno!(ENOMEM, "not enough memory"); } let free_range = result_free_range.unwrap(); @@ -324,9 +318,9 @@ pub struct VMRange { } impl VMRange { - pub fn from(start: usize, end: usize) -> Result { + pub fn from(start: usize, end: usize) -> Result { if start % PAGE_SIZE != 0 || end % PAGE_SIZE != 0 || start > end { - return errno!(EINVAL, "invalid start or end"); + return_errno!(EINVAL, "invalid start or end"); } Ok(VMRange { start: start,