diff --git a/deps/sefs b/deps/sefs
index 166616e5..2865c419 160000
--- a/deps/sefs
+++ b/deps/sefs
@@ -1 +1 @@
-Subproject commit 166616e5ade1a5c929f705fd1564ef0ea337ba72
+Subproject commit 2865c419b3d36a8b0e7ef843b115cb1ecb3176f8
diff --git a/src/Enclave.edl b/src/Enclave.edl
index 71bbdd60..82e084fd 100644
--- a/src/Enclave.edl
+++ b/src/Enclave.edl
@@ -4,11 +4,14 @@ enclave {
from "sgx_tstdc.edl" import *;
from "sgx_tstd.edl" import *;
from "sgx_tprotected_fs.edl" import *;
+ from "sgx_net.edl" import *;
trusted {
/* define ECALLs here. */
public int libos_boot([in, string] const char* executable_path, [user_check] const char** argv);
public int libos_run(void);
+ /* This is only for debug usage */
+ public int dummy_ecall(void);
};
untrusted {
diff --git a/src/libos/Cargo.toml b/src/libos/Cargo.toml
index 71e1fec9..86a75d71 100644
--- a/src/libos/Cargo.toml
+++ b/src/libos/Cargo.toml
@@ -14,7 +14,10 @@ rcore-fs = { path = "../../deps/sefs/rcore-fs" }
rcore-fs-sefs = { path = "../../deps/sefs/rcore-fs-sefs" }
[features]
-default = []
+default = ["integrity_only_opt", "sgx_file_cache"]
+syscall_timing = [] # Timing for each syscall. But it has cost from more ocall.
+integrity_only_opt = [] # Clear bss only. It should be disabled if checking memory reads.
+sgx_file_cache = [] # Cache SgxFile objects. Invalidation is unimplemented.
[target.'cfg(not(target_env = "sgx"))'.dependencies]
xmas-elf = { path = "../../deps/xmas-elf" }
diff --git a/src/libos/Enclave_config.xml b/src/libos/Enclave_config.xml
index 5f853be5..7d9f7639 100644
--- a/src/libos/Enclave_config.xml
+++ b/src/libos/Enclave_config.xml
@@ -3,7 +3,7 @@
0
0
0x100000
- 0x1000000
+ 0x2000000
8
1
0
diff --git a/src/libos/src/entry.rs b/src/libos/src/entry.rs
index f0de3087..66e34afb 100644
--- a/src/libos/src/entry.rs
+++ b/src/libos/src/entry.rs
@@ -35,6 +35,10 @@ pub extern "C" fn libos_run() -> i32 {
.unwrap_or(EXIT_STATUS_INTERNAL_ERROR)
}
+#[no_mangle]
+pub extern "C" fn dummy_ecall() -> i32 {
+ 0
+}
// Use 127 as a special value to indicate internal error from libos, not from
// user programs, although it is completely ok for a user program to return 127.
const EXIT_STATUS_INTERNAL_ERROR: i32 = 127;
@@ -64,7 +68,7 @@ fn parse_arguments(
// TODO: make sure do_boot can only be called once
fn do_boot(path_str: &str, argv: &Vec) -> Result<(), Error> {
- info!("boot: path: {:?}, argv: {:?}", path_str, argv);
+ // info!("boot: path: {:?}, argv: {:?}", path_str, argv);
util::mpx_util::mpx_enable()?;
let envp = std::vec::Vec::new();
@@ -78,5 +82,11 @@ fn do_boot(path_str: &str, argv: &Vec) -> Result<(), Error> {
// TODO: make sure do_run() cannot be called after do_boot()
fn do_run() -> Result {
let exit_status = process::run_task()?;
+
+ // sync file system
+ // TODO: only sync when all processes exit
+ use rcore_fs::vfs::FileSystem;
+ crate::fs::ROOT_INODE.fs().sync()?;
+
Ok(exit_status)
}
diff --git a/src/libos/src/errno.rs b/src/libos/src/errno.rs
index 9957fd1a..c00f39e3 100644
--- a/src/libos/src/errno.rs
+++ b/src/libos/src/errno.rs
@@ -22,6 +22,15 @@ impl convert::From<(Errno, &'static str)> for Error {
}
}
+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 error::Error for Error {
fn description(&self) -> &str {
self.desc
@@ -39,6 +48,7 @@ impl fmt::Display for Error {
}
#[derive(Clone, Copy, Debug, PartialEq)]
+#[repr(u8)]
pub enum Errno {
EUNDEF = 0,
EPERM = 1,
@@ -80,12 +90,112 @@ pub enum Errno {
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 {
diff --git a/src/libos/src/fs/access.rs b/src/libos/src/fs/access.rs
index e2910a73..201c6864 100644
--- a/src/libos/src/fs/access.rs
+++ b/src/libos/src/fs/access.rs
@@ -17,7 +17,6 @@ impl AccessModes {
}
}
-
bitflags! {
pub struct AccessFlags : u32 {
const AT_SYMLINK_NOFOLLOW = 0x100;
@@ -31,10 +30,18 @@ impl AccessFlags {
}
}
+pub const AT_FDCWD: i32 = -100;
-pub const AT_FDCWD : i32 = -100;
-
-pub fn do_faccessat(dirfd: Option, path: &str, mode: AccessModes, flags: AccessFlags) -> Result<(), Error> {
+pub fn do_faccessat(
+ dirfd: Option,
+ path: &str,
+ mode: AccessModes,
+ flags: AccessFlags,
+) -> Result<(), Error> {
+ info!(
+ "faccessat: dirfd: {:?}, path: {:?}, mode: {:?}, flags: {:?}",
+ dirfd, path, mode, flags
+ );
match dirfd {
// TODO: handle dirfd
Some(dirfd) => errno!(ENOSYS, "cannot accept dirfd"),
@@ -43,6 +50,7 @@ pub fn do_faccessat(dirfd: Option, path: &str, mode: AccessModes, flag
}
pub fn do_access(path: &str, mode: AccessModes) -> Result<(), Error> {
+ info!("access: path: {:?}, mode: {:?}", path, mode);
let current_ref = process::get_current();
let mut current = current_ref.lock().unwrap();
let inode = current.lookup_inode(path)?;
diff --git a/src/libos/src/fs/file.rs b/src/libos/src/fs/file.rs
index 79d0e415..a45a0e24 100644
--- a/src/libos/src/fs/file.rs
+++ b/src/libos/src/fs/file.rs
@@ -4,7 +4,7 @@ use std::borrow::BorrowMut;
use std::fmt;
use std::io::SeekFrom;
-pub trait File: Debug + Sync + Send {
+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;
@@ -17,6 +17,7 @@ pub trait File: Debug + Sync + Send {
fn sync_all(&self) -> Result<(), Error>;
fn sync_data(&self) -> Result<(), Error>;
fn read_entry(&self) -> Result;
+ fn as_any(&self) -> &Any;
}
pub type FileRef = Arc>;
@@ -35,7 +36,7 @@ impl SgxFile {
is_append: bool,
) -> Result {
if !is_readable && !is_writable {
- return Err(Error::new(Errno::EINVAL, "Invalid permissions"));
+ return errno!(EINVAL, "Invalid permissions");
}
Ok(SgxFile {
@@ -114,6 +115,10 @@ impl File for SgxFile {
fn read_entry(&self) -> Result {
unimplemented!()
}
+
+ fn as_any(&self) -> &Any {
+ self
+ }
}
#[derive(Clone)]
@@ -130,7 +135,7 @@ struct SgxFileInner {
impl SgxFileInner {
pub fn write(&mut self, buf: &[u8]) -> Result {
if !self.is_writable {
- return Err(Error::new(Errno::EINVAL, "File not writable"));
+ return errno!(EINVAL, "File not writable");
}
let mut file_guard = self.file.lock().unwrap();
@@ -158,7 +163,7 @@ impl SgxFileInner {
pub fn read(&mut self, buf: &mut [u8]) -> Result {
if !self.is_readable {
- return Err(Error::new(Errno::EINVAL, "File not readable"));
+ return errno!(EINVAL, "File not readable");
}
let mut file_guard = self.file.lock().unwrap();
@@ -191,7 +196,7 @@ impl SgxFileInner {
let backward_offset = (-relative_offset) as usize;
if self.pos < backward_offset {
// underflow
- return Err(Error::new(Errno::EINVAL, "Invalid seek position"));
+ return errno!(EINVAL, "Invalid seek position");
}
SeekFrom::Start((self.pos - backward_offset) as u64)
}
@@ -207,7 +212,7 @@ impl SgxFileInner {
pub fn writev(&mut self, bufs: &[&[u8]]) -> Result {
if !self.is_writable {
- return Err(Error::new(Errno::EINVAL, "File not writable"));
+ return errno!(EINVAL, "File not writable");
}
let mut file_guard = self.file.lock().unwrap();
@@ -233,7 +238,7 @@ impl SgxFileInner {
Err(e) => {
match total_bytes {
// a complete failure
- 0 => return Err(Error::new(Errno::EINVAL, "Failed to write")),
+ 0 => return errno!(EINVAL, "Failed to write"),
// a partially failure
_ => break,
}
@@ -247,7 +252,7 @@ impl SgxFileInner {
fn readv(&mut self, bufs: &mut [&mut [u8]]) -> Result {
if !self.is_readable {
- return Err(Error::new(Errno::EINVAL, "File not readable"));
+ return errno!(EINVAL, "File not readable");
}
let mut file_guard = self.file.lock().unwrap();
@@ -269,7 +274,7 @@ impl SgxFileInner {
Err(e) => {
match total_bytes {
// a complete failure
- 0 => return Err(Error::new(Errno::EINVAL, "Failed to write")),
+ 0 => return errno!(EINVAL, "Failed to write"),
// a partially failure
_ => break,
}
@@ -305,7 +310,7 @@ impl StdoutFile {
impl File for StdoutFile {
fn read(&self, buf: &mut [u8]) -> Result {
- Err(Error::new(Errno::EBADF, "Stdout does not support read"))
+ errno!(EBADF, "Stdout does not support read")
}
fn write(&self, buf: &[u8]) -> Result {
@@ -318,16 +323,16 @@ impl File for StdoutFile {
Ok(write_len)
}
- fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result {
- unimplemented!()
+ fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result {
+ self.read(buf)
}
- fn write_at(&self, offset: usize, buf: &[u8]) -> Result {
- unimplemented!()
+ fn write_at(&self, _offset: usize, buf: &[u8]) -> Result {
+ self.write(buf)
}
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result {
- Err(Error::new(Errno::EBADF, "Stdout does not support read"))
+ errno!(EBADF, "Stdout does not support read")
}
fn writev(&self, bufs: &[&[u8]]) -> Result {
@@ -344,7 +349,7 @@ impl File for StdoutFile {
Err(e) => {
match total_bytes {
// a complete failure
- 0 => return Err(Error::new(Errno::EINVAL, "Failed to write")),
+ 0 => return errno!(EINVAL, "Failed to write"),
// a partially failure
_ => break,
}
@@ -355,27 +360,46 @@ impl File for StdoutFile {
}
fn seek(&self, seek_pos: SeekFrom) -> Result {
- Err(Error::new(Errno::ESPIPE, "Stdout does not support seek"))
+ errno!(ESPIPE, "Stdout does not support seek")
}
fn metadata(&self) -> Result {
- unimplemented!()
+ Ok(Metadata {
+ dev: 0,
+ inode: 0,
+ size: 0,
+ blk_size: 0,
+ blocks: 0,
+ atime: Timespec { sec: 0, nsec: 0 },
+ mtime: Timespec { sec: 0, nsec: 0 },
+ ctime: Timespec { sec: 0, nsec: 0 },
+ type_: FileType::CharDevice,
+ mode: 0,
+ nlinks: 0,
+ uid: 0,
+ gid: 0,
+ })
}
- fn set_len(&self, len: u64) -> Result<(), Error> {
- unimplemented!()
+ fn set_len(&self, _len: u64) -> Result<(), Error> {
+ errno!(EINVAL, "Stdout does not support set_len")
}
fn sync_all(&self) -> Result<(), Error> {
- unimplemented!()
+ self.sync_data()
}
fn sync_data(&self) -> Result<(), Error> {
- unimplemented!()
+ self.inner.lock().flush()?;
+ Ok(())
}
fn read_entry(&self) -> Result {
- unimplemented!()
+ errno!(ENOTDIR, "Stdout does not support read_entry")
+ }
+
+ fn as_any(&self) -> &Any {
+ self
}
}
@@ -412,7 +436,7 @@ impl File for StdinFile {
}
fn write(&self, buf: &[u8]) -> Result {
- Err(Error::new(Errno::EBADF, "Stdin does not support write"))
+ errno!(EBADF, "Stdin does not support write")
}
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result {
@@ -437,7 +461,7 @@ impl File for StdinFile {
Err(e) => {
match total_bytes {
// a complete failure
- 0 => return Err(Error::new(Errno::EINVAL, "Failed to write")),
+ 0 => return errno!(EINVAL, "Failed to write"),
// a partially failure
_ => break,
}
@@ -448,31 +472,49 @@ impl File for StdinFile {
}
fn writev(&self, bufs: &[&[u8]]) -> Result {
- Err(Error::new(Errno::EBADF, "Stdin does not support write"))
+ errno!(EBADF, "Stdin does not support write")
}
fn seek(&self, pos: SeekFrom) -> Result {
- Err(Error::new(Errno::ESPIPE, "Stdin does not support seek"))
+ errno!(ESPIPE, "Stdin does not support seek")
}
fn metadata(&self) -> Result {
- unimplemented!()
+ Ok(Metadata {
+ dev: 0,
+ inode: 0,
+ size: 0,
+ blk_size: 0,
+ blocks: 0,
+ atime: Timespec { sec: 0, nsec: 0 },
+ mtime: Timespec { sec: 0, nsec: 0 },
+ ctime: Timespec { sec: 0, nsec: 0 },
+ type_: FileType::CharDevice,
+ mode: 0,
+ nlinks: 0,
+ uid: 0,
+ gid: 0,
+ })
}
- fn set_len(&self, len: u64) -> Result<(), Error> {
- unimplemented!()
+ fn set_len(&self, _len: u64) -> Result<(), Error> {
+ errno!(EINVAL, "Stdin does not support set_len")
}
fn sync_all(&self) -> Result<(), Error> {
- unimplemented!()
+ self.sync_data()
}
fn sync_data(&self) -> Result<(), Error> {
- unimplemented!()
+ Ok(())
}
fn read_entry(&self) -> Result {
- unimplemented!()
+ errno!(ENOTDIR, "Stdin does not support read_entry")
+ }
+
+ fn as_any(&self) -> &Any {
+ self
}
}
diff --git a/src/libos/src/fs/file_table.rs b/src/libos/src/fs/file_table.rs
index 0e60c108..be80ba4b 100644
--- a/src/libos/src/fs/file_table.rs
+++ b/src/libos/src/fs/file_table.rs
@@ -4,7 +4,7 @@ use std;
pub type FileDesc = u32;
-#[derive(Debug, Default)]
+#[derive(Debug, Default, Clone)]
#[repr(C)]
pub struct FileTable {
table: Vec