Reformat Rust code using cargo fmt

This commit is contained in:
Tate, Hongliang Tian 2019-02-17 22:41:51 +08:00
parent be64e45d15
commit 602fef10f8
30 changed files with 929 additions and 937 deletions

@ -1,61 +1,59 @@
use super::{*}; use super::*;
use util::mem_util::from_untrusted::*;
use std::ffi::{CStr, CString, OsString}; use std::ffi::{CStr, CString, OsString};
use std::path::{Path}; use std::path::Path;
use util::mem_util::from_untrusted::*;
#[no_mangle] #[no_mangle]
pub extern "C" fn libos_boot(path_buf: *const c_char, argv: *const *const c_char) -> i32 { pub extern "C" fn libos_boot(path_buf: *const c_char, argv: *const *const c_char) -> i32 {
let (path, args) = match parse_arguments(path_buf, argv) { let (path, args) = match parse_arguments(path_buf, argv) {
Ok(path_and_args) => { Ok(path_and_args) => path_and_args,
path_and_args
},
Err(_) => { Err(_) => {
return EXIT_STATUS_INTERNAL_ERROR; return EXIT_STATUS_INTERNAL_ERROR;
} }
}; };
let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short); let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short);
panic::catch_unwind(||{ panic::catch_unwind(|| {
backtrace::__rust_begin_short_backtrace(||{ backtrace::__rust_begin_short_backtrace(|| match do_boot(&path, &args) {
match do_boot(&path, &args) {
Ok(()) => 0, Ok(()) => 0,
Err(err) => EXIT_STATUS_INTERNAL_ERROR, Err(err) => EXIT_STATUS_INTERNAL_ERROR,
}
}) })
}).unwrap_or(EXIT_STATUS_INTERNAL_ERROR) })
.unwrap_or(EXIT_STATUS_INTERNAL_ERROR)
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn libos_run() -> i32 { pub extern "C" fn libos_run() -> i32 {
let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short); let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short);
panic::catch_unwind(||{ panic::catch_unwind(|| {
backtrace::__rust_begin_short_backtrace(||{ backtrace::__rust_begin_short_backtrace(|| match do_run() {
match do_run() {
Ok(exit_status) => exit_status, Ok(exit_status) => exit_status,
Err(err) => EXIT_STATUS_INTERNAL_ERROR, Err(err) => EXIT_STATUS_INTERNAL_ERROR,
}
}) })
}).unwrap_or(EXIT_STATUS_INTERNAL_ERROR) })
.unwrap_or(EXIT_STATUS_INTERNAL_ERROR)
} }
// Use 127 as a special value to indicate internal error from libos, not from // 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. // user programs, although it is completely ok for a user program to return 127.
const EXIT_STATUS_INTERNAL_ERROR : i32 = 127; const EXIT_STATUS_INTERNAL_ERROR: i32 = 127;
fn parse_arguments(path_buf: *const c_char, argv: *const *const c_char) fn parse_arguments(
-> Result<(String, Vec<CString>), Error> path_buf: *const c_char,
{ argv: *const *const c_char,
) -> Result<(String, Vec<CString>), Error> {
let path_string = { let path_string = {
let path_cstring = clone_cstring_safely(path_buf)?; let path_cstring = clone_cstring_safely(path_buf)?;
path_cstring.to_string_lossy().into_owned() path_cstring.to_string_lossy().into_owned()
}; };
let program_cstring = { let program_cstring = {
let program_osstr= Path::new(&path_string).file_name() let program_osstr = Path::new(&path_string)
.file_name()
.ok_or_else(|| Error::new(Errno::EINVAL, "Invalid path"))?; .ok_or_else(|| Error::new(Errno::EINVAL, "Invalid path"))?;
let program_str = program_osstr.to_str() let program_str = program_osstr
.to_str()
.ok_or_else(|| Error::new(Errno::EINVAL, "Invalid path"))?; .ok_or_else(|| Error::new(Errno::EINVAL, "Invalid path"))?;
CString::new(program_str) CString::new(program_str).or_else(|_| errno!(EINVAL, "Invalid path"))?
.or_else(|_| errno!(EINVAL, "Invalid path"))?
}; };
let mut args = clone_cstrings_safely(argv)?; let mut args = clone_cstrings_safely(argv)?;

@ -1,5 +1,5 @@
use prelude::*; use prelude::*;
use std::{fmt, error, convert,}; use std::{convert, error, fmt};
// TODO: remove errno.h // TODO: remove errno.h
@ -11,20 +11,14 @@ pub struct Error {
impl Error { impl Error {
pub fn new(errno: Errno, desc: &'static str) -> Error { pub fn new(errno: Errno, desc: &'static str) -> Error {
let ret = Error { let ret = Error { errno, desc };
errno,
desc,
};
ret ret
} }
} }
impl convert::From<(Errno, &'static str)> for Error { impl convert::From<(Errno, &'static str)> for Error {
fn from(info: (Errno, &'static str)) -> Error { fn from(info: (Errno, &'static str)) -> Error {
Error::new( Error::new(info.0, info.1)
info.0,
info.1,
)
} }
} }
@ -88,13 +82,15 @@ pub enum Errno {
impl Errno { impl Errno {
pub fn as_retval(&self) -> i32 { pub fn as_retval(&self) -> i32 {
- (*self as i32) -(*self as i32)
} }
} }
impl fmt::Display for Errno { impl fmt::Display for Errno {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "errno = {}, \"{}\"", write!(
f,
"errno = {}, \"{}\"",
*self as u32, *self as u32,
match *self { match *self {
Errno::EPERM => "Operation not permitted", Errno::EPERM => "Operation not permitted",
@ -139,5 +135,3 @@ impl fmt::Display for Errno {
) )
} }
} }

@ -1,10 +1,9 @@
use super::*; use super::*;
use {std}; use std;
use std::{fmt};
use std::borrow::BorrowMut; use std::borrow::BorrowMut;
use std::fmt;
pub trait File: Debug + Sync + Send {
pub trait File : Debug + Sync + Send {
fn read(&self, buf: &mut [u8]) -> Result<usize, Error>; fn read(&self, buf: &mut [u8]) -> Result<usize, Error>;
fn write(&self, buf: &[u8]) -> Result<usize, Error>; fn write(&self, buf: &[u8]) -> Result<usize, Error>;
fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result<usize, Error>; fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result<usize, Error>;
@ -21,10 +20,12 @@ pub struct SgxFile {
} }
impl SgxFile { impl SgxFile {
pub fn new(file: Arc<SgxMutex<fs_impl::SgxFile>>, pub fn new(
is_readable: bool, is_writable: bool, is_append: bool) file: Arc<SgxMutex<fs_impl::SgxFile>>,
-> Result<SgxFile, Error> is_readable: bool,
{ is_writable: bool,
is_append: bool,
) -> Result<SgxFile, Error> {
if !is_readable && !is_writable { if !is_readable && !is_writable {
return Err(Error::new(Errno::EINVAL, "Invalid permissions")); return Err(Error::new(Errno::EINVAL, "Invalid permissions"));
} }
@ -76,7 +77,7 @@ impl File for SgxFile {
#[derive(Clone)] #[derive(Clone)]
#[repr(C)] #[repr(C)]
struct SgxFileInner { struct SgxFileInner {
// perms: FilePerms, // perms: FilePerms,
pos: usize, pos: usize,
file: Arc<SgxMutex<fs_impl::SgxFile>>, file: Arc<SgxMutex<fs_impl::SgxFile>>,
is_readable: bool, is_readable: bool,
@ -99,12 +100,12 @@ impl SgxFileInner {
SeekFrom::End(0) SeekFrom::End(0)
}; };
// TODO: recover from error // TODO: recover from error
file.seek(seek_pos).map_err( file.seek(seek_pos)
|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?; .map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
let write_len = { let write_len = {
file.write(buf).map_err( file.write(buf)
|e| Error::new(Errno::EINVAL, "Failed to write"))? .map_err(|e| Error::new(Errno::EINVAL, "Failed to write"))?
}; };
if !self.is_append { if !self.is_append {
@ -122,12 +123,12 @@ impl SgxFileInner {
let file = file_guard.borrow_mut(); let file = file_guard.borrow_mut();
let seek_pos = SeekFrom::Start(self.pos as u64); let seek_pos = SeekFrom::Start(self.pos as u64);
file.seek(seek_pos).map_err( file.seek(seek_pos)
|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?; .map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
let read_len = { let read_len = {
file.read(buf).map_err( file.read(buf)
|e| Error::new(Errno::EINVAL, "Failed to write"))? .map_err(|e| Error::new(Errno::EINVAL, "Failed to write"))?
}; };
self.pos += read_len; self.pos += read_len;
@ -139,29 +140,26 @@ impl SgxFileInner {
let file = file_guard.borrow_mut(); let file = file_guard.borrow_mut();
let pos = match pos { let pos = match pos {
SeekFrom::Start(absolute_offset) => { SeekFrom::Start(absolute_offset) => pos,
pos SeekFrom::End(relative_offset) => pos,
}
SeekFrom::End(relative_offset) => {
pos
}
SeekFrom::Current(relative_offset) => { SeekFrom::Current(relative_offset) => {
if relative_offset >= 0 { if relative_offset >= 0 {
SeekFrom::Start((self.pos + relative_offset as usize) as u64) SeekFrom::Start((self.pos + relative_offset as usize) as u64)
} } else {
else {
let backward_offset = (-relative_offset) as usize; let backward_offset = (-relative_offset) as usize;
if self.pos < backward_offset { // underflow if self.pos < backward_offset {
return Err(Error::new(Errno::EINVAL, // underflow
"Invalid seek position")); return Err(Error::new(Errno::EINVAL, "Invalid seek position"));
} }
SeekFrom::Start((self.pos - backward_offset) as u64) SeekFrom::Start((self.pos - backward_offset) as u64)
} }
} }
}; };
self.pos = file.seek(pos).map_err( self.pos = file
|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))? as usize; .seek(pos)
.map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?
as usize;
Ok(self.pos as off_t) Ok(self.pos as off_t)
} }
@ -178,15 +176,17 @@ impl SgxFileInner {
} else { } else {
SeekFrom::End(0) SeekFrom::End(0)
}; };
file.seek(seek_pos).map_err( file.seek(seek_pos)
|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?; .map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
let mut total_bytes = 0; let mut total_bytes = 0;
for buf in bufs { for buf in bufs {
match file.write(buf) { match file.write(buf) {
Ok(this_bytes) => { Ok(this_bytes) => {
total_bytes += this_bytes; total_bytes += this_bytes;
if this_bytes < buf.len() { break; } if this_bytes < buf.len() {
break;
}
} }
Err(e) => { Err(e) => {
match total_bytes { match total_bytes {
@ -212,15 +212,17 @@ impl SgxFileInner {
let file = file_guard.borrow_mut(); let file = file_guard.borrow_mut();
let seek_pos = SeekFrom::Start(self.pos as u64); let seek_pos = SeekFrom::Start(self.pos as u64);
file.seek(seek_pos).map_err( file.seek(seek_pos)
|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?; .map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
let mut total_bytes = 0; let mut total_bytes = 0;
for buf in bufs { for buf in bufs {
match file.read(buf) { match file.read(buf) {
Ok(this_bytes) => { Ok(this_bytes) => {
total_bytes += this_bytes; total_bytes += this_bytes;
if this_bytes < buf.len() { break; } if this_bytes < buf.len() {
break;
}
} }
Err(e) => { Err(e) => {
match total_bytes { match total_bytes {
@ -262,8 +264,10 @@ impl StdoutFile {
impl File for StdoutFile { impl File for StdoutFile {
fn write(&self, buf: &[u8]) -> Result<usize, Error> { fn write(&self, buf: &[u8]) -> Result<usize, Error> {
let write_len = { let write_len = {
self.inner.lock().write(buf).map_err(|e| (Errno::EINVAL, self.inner
"Failed to write"))? .lock()
.write(buf)
.map_err(|e| (Errno::EINVAL, "Failed to write"))?
}; };
Ok(write_len) Ok(write_len)
} }
@ -279,7 +283,9 @@ impl File for StdoutFile {
match guard.write(buf) { match guard.write(buf) {
Ok(this_len) => { Ok(this_len) => {
total_bytes += this_len; total_bytes += this_len;
if this_len < buf.len() { break; } if this_len < buf.len() {
break;
}
} }
Err(e) => { Err(e) => {
match total_bytes { match total_bytes {
@ -327,8 +333,10 @@ impl StdinFile {
impl File for StdinFile { impl File for StdinFile {
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> { fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
let read_len = { let read_len = {
self.inner.lock().read(buf).map_err(|e| (Errno::EINVAL, self.inner
"Failed to read"))? .lock()
.read(buf)
.map_err(|e| (Errno::EINVAL, "Failed to read"))?
}; };
Ok(read_len) Ok(read_len)
} }
@ -348,7 +356,9 @@ impl File for StdinFile {
match guard.read(buf) { match guard.read(buf) {
Ok(this_len) => { Ok(this_len) => {
total_bytes += this_len; total_bytes += this_len;
if this_len < buf.len() { break; } if this_len < buf.len() {
break;
}
} }
Err(e) => { Err(e) => {
match total_bytes { match total_bytes {

@ -1,6 +1,6 @@
use super::*;
use super::file::{File, FileRef}; use super::file::{File, FileRef};
use {std}; use super::*;
use std;
pub type FileDesc = u32; pub type FileDesc = u32;
@ -17,7 +17,6 @@ struct FileTableEntry {
close_on_spawn: bool, close_on_spawn: bool,
} }
impl FileTable { impl FileTable {
pub fn new() -> FileTable { pub fn new() -> FileTable {
FileTable { FileTable {
@ -30,15 +29,18 @@ impl FileTable {
let mut table = &mut self.table; let mut table = &mut self.table;
let min_free_fd = if self.num_fds < table.len() { let min_free_fd = if self.num_fds < table.len() {
table.iter().enumerate().find(|&(idx, opt)| opt.is_none()) table
.unwrap().0 .iter()
.enumerate()
.find(|&(idx, opt)| opt.is_none())
.unwrap()
.0
} else { } else {
table.push(None); table.push(None);
table.len() - 1 table.len() - 1
}; };
table[min_free_fd as usize] = Some(FileTableEntry::new(file, table[min_free_fd as usize] = Some(FileTableEntry::new(file, close_on_spawn));
close_on_spawn));
self.num_fds += 1; self.num_fds += 1;
min_free_fd as FileDesc min_free_fd as FileDesc
@ -80,7 +82,7 @@ impl FileTable {
Some(del_table_entry) => { Some(del_table_entry) => {
self.num_fds -= 1; self.num_fds -= 1;
Ok(del_table_entry.file) Ok(del_table_entry.file)
}, }
None => errno!(EBADF, "Invalid file descriptor"), None => errno!(EBADF, "Invalid file descriptor"),
} }
} }
@ -90,20 +92,20 @@ impl Clone for FileTable {
fn clone(&self) -> FileTable { fn clone(&self) -> FileTable {
// Only clone file descriptors that are not close-on-spawn // Only clone file descriptors that are not close-on-spawn
let mut num_cloned_fds = 0; let mut num_cloned_fds = 0;
let cloned_table = self.table.iter().map(|entry| { let cloned_table = self
match entry { .table
Some(file_table_entry) => { .iter()
match file_table_entry.close_on_spawn { .map(|entry| match entry {
Some(file_table_entry) => match file_table_entry.close_on_spawn {
false => { false => {
num_cloned_fds += 1; num_cloned_fds += 1;
Some(file_table_entry.clone()) Some(file_table_entry.clone())
} }
true => None true => None,
}
}, },
None => None None => None,
} })
}).collect(); .collect();
FileTable { FileTable {
table: cloned_table, table: cloned_table,
@ -112,7 +114,6 @@ impl Clone for FileTable {
} }
} }
impl FileTableEntry { impl FileTableEntry {
fn new(file: FileRef, close_on_spawn: bool) -> FileTableEntry { fn new(file: FileRef, close_on_spawn: bool) -> FileTableEntry {
FileTableEntry { FileTableEntry {

@ -1,7 +1,7 @@
use super::*; use super::*;
use prelude::*; use prelude::*;
use {std, process};
use std::sgxfs as fs_impl; use std::sgxfs as fs_impl;
use {process, std};
mod file; mod file;
mod file_table; mod file_table;
@ -9,14 +9,14 @@ mod pipe;
pub use self::file::{File, FileRef, SgxFile, StdinFile, StdoutFile}; pub use self::file::{File, FileRef, SgxFile, StdinFile, StdoutFile};
pub use self::file_table::{FileDesc, FileTable}; pub use self::file_table::{FileDesc, FileTable};
pub use self::pipe::{Pipe}; pub use self::pipe::Pipe;
pub const O_RDONLY : u32 = 0x00000000; pub const O_RDONLY: u32 = 0x00000000;
pub const O_WRONLY : u32 = 0x00000001; pub const O_WRONLY: u32 = 0x00000001;
pub const O_RDWR : u32 = 0x00000002; pub const O_RDWR: u32 = 0x00000002;
pub const O_CREAT : u32 = 0x00000040; pub const O_CREAT: u32 = 0x00000040;
pub const O_TRUNC : u32 = 0x00000200; pub const O_TRUNC: u32 = 0x00000200;
pub const O_APPEND : u32 = 0x00000400; pub const O_APPEND: u32 = 0x00000400;
pub const O_CLOEXEC: u32 = 0x00080000; pub const O_CLOEXEC: u32 = 0x00080000;
// TODO: use the type defined in Rust libc. // TODO: use the type defined in Rust libc.
@ -32,8 +32,7 @@ pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
if ((flags & O_TRUNC) != 0 || (flags & O_CREAT) != 0) { if ((flags & O_TRUNC) != 0 || (flags & O_CREAT) != 0) {
open_options.write(true); open_options.write(true);
} } else {
else {
open_options.read(true); open_options.read(true);
} }
open_options.update(true).binary(true); open_options.update(true).binary(true);
@ -42,18 +41,23 @@ pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
}; };
let mut sgx_file = { let mut sgx_file = {
let key : sgx_key_128bit_t = [0 as uint8_t; 16]; let key: sgx_key_128bit_t = [0 as uint8_t; 16];
// TODO: what if two processes open the same underlying SGX file? // TODO: what if two processes open the same underlying SGX file?
let sgx_file = open_options.open_ex(path, &key) let sgx_file = open_options
.map_err(|e| (Errno::ENOENT, "Failed to open the SGX-protected file") )?; .open_ex(path, &key)
.map_err(|e| (Errno::ENOENT, "Failed to open the SGX-protected file"))?;
Arc::new(SgxMutex::new(sgx_file)) Arc::new(SgxMutex::new(sgx_file))
}; };
let is_readable = (flags & O_WRONLY) == 0; let is_readable = (flags & O_WRONLY) == 0;
let is_writable = (flags & O_WRONLY != 0) || (flags & O_RDWR != 0); let is_writable = (flags & O_WRONLY != 0) || (flags & O_RDWR != 0);
let is_append = (flags & O_APPEND != 0); let is_append = (flags & O_APPEND != 0);
let file_ref : Arc<Box<File>> = Arc::new(Box::new( let file_ref: Arc<Box<File>> = Arc::new(Box::new(SgxFile::new(
SgxFile::new(sgx_file, is_readable, is_writable, is_append)?)); sgx_file,
is_readable,
is_writable,
is_append,
)?));
let fd = { let fd = {
let current_ref = process::get_current(); let current_ref = process::get_current();
@ -114,10 +118,8 @@ pub fn do_pipe2(flags: u32) -> Result<[FileDesc; 2], Error> {
let mut file_table = current.get_files_mut(); let mut file_table = current.get_files_mut();
let close_on_spawn = flags & O_CLOEXEC != 0; let close_on_spawn = flags & O_CLOEXEC != 0;
let reader_fd = file_table.put(Arc::new(Box::new(pipe.reader)), let reader_fd = file_table.put(Arc::new(Box::new(pipe.reader)), close_on_spawn);
close_on_spawn); let writer_fd = file_table.put(Arc::new(Box::new(pipe.writer)), close_on_spawn);
let writer_fd = file_table.put(Arc::new(Box::new(pipe.writer)),
close_on_spawn);
Ok([reader_fd, writer_fd]) Ok([reader_fd, writer_fd])
} }
@ -155,10 +157,12 @@ pub fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result<FileDes
} }
pub fn do_sync() -> Result<(), Error> { pub fn do_sync() -> Result<(), Error> {
unsafe { ocall_sync(); } unsafe {
ocall_sync();
}
Ok(()) Ok(())
} }
extern { extern "C" {
fn ocall_sync() -> sgx_status_t; fn ocall_sync() -> sgx_status_t;
} }

@ -1,9 +1,9 @@
use super::*; use super::*;
use util::ring_buf::{*}; use util::ring_buf::*;
// TODO: Use Waiter and WaitQueue infrastructure to sleep when blocking // TODO: Use Waiter and WaitQueue infrastructure to sleep when blocking
pub const PIPE_BUF_SIZE : usize = 2 * 1024 * 1024; pub const PIPE_BUF_SIZE: usize = 2 * 1024 * 1024;
#[derive(Debug)] #[derive(Debug)]
pub struct Pipe { pub struct Pipe {
@ -20,12 +20,11 @@ impl Pipe {
}, },
writer: PipeWriter { writer: PipeWriter {
inner: SgxMutex::new(ring_buf.writer), inner: SgxMutex::new(ring_buf.writer),
} },
}) })
} }
} }
#[derive(Debug)] #[derive(Debug)]
pub struct PipeReader { pub struct PipeReader {
inner: SgxMutex<RingBufReader>, inner: SgxMutex<RingBufReader>,
@ -44,7 +43,9 @@ impl File for PipeReader {
match ringbuf.read(buf) { match ringbuf.read(buf) {
Ok(this_len) => { Ok(this_len) => {
total_bytes += this_len; total_bytes += this_len;
if this_len < buf.len() { break; } if this_len < buf.len() {
break;
}
} }
Err(e) => { Err(e) => {
match total_bytes { match total_bytes {
@ -60,11 +61,17 @@ impl File for PipeReader {
} }
fn write(&self, buf: &[u8]) -> Result<usize, Error> { fn write(&self, buf: &[u8]) -> Result<usize, Error> {
Err(Error::new(Errno::EBADF, "PipeReader does not support write")) Err(Error::new(
Errno::EBADF,
"PipeReader does not support write",
))
} }
fn writev<'a, 'b>(&self, bufs: &'a [&'b [u8]]) -> Result<usize, Error> { fn writev<'a, 'b>(&self, bufs: &'a [&'b [u8]]) -> Result<usize, Error> {
Err(Error::new(Errno::EBADF, "PipeReader does not support write")) Err(Error::new(
Errno::EBADF,
"PipeReader does not support write",
))
} }
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> { fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
@ -75,7 +82,6 @@ impl File for PipeReader {
unsafe impl Send for PipeReader {} unsafe impl Send for PipeReader {}
unsafe impl Sync for PipeReader {} unsafe impl Sync for PipeReader {}
#[derive(Debug)] #[derive(Debug)]
pub struct PipeWriter { pub struct PipeWriter {
inner: SgxMutex<RingBufWriter>, inner: SgxMutex<RingBufWriter>,
@ -94,7 +100,9 @@ impl File for PipeWriter {
match ringbuf.write(buf) { match ringbuf.write(buf) {
Ok(this_len) => { Ok(this_len) => {
total_bytes += this_len; total_bytes += this_len;
if this_len < buf.len() { break; } if this_len < buf.len() {
break;
}
} }
Err(e) => { Err(e) => {
match total_bytes { match total_bytes {

@ -1,8 +1,6 @@
#![allow(unused)] #![allow(unused)]
#![crate_name = "occlum_rs"] #![crate_name = "occlum_rs"]
#![crate_type = "staticlib"] #![crate_type = "staticlib"]
#![cfg_attr(not(target_env = "sgx"), no_std)] #![cfg_attr(not(target_env = "sgx"), no_std)]
#![cfg_attr(target_env = "sgx", feature(rustc_private))] #![cfg_attr(target_env = "sgx", feature(rustc_private))]
#![feature(allocator_api)] #![feature(allocator_api)]
@ -18,11 +16,11 @@ extern crate xmas_elf;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
use std::ffi::CStr; // a borrowed C string
use std::backtrace::{self, PrintFormat};
use std::panic;
use sgx_types::*;
use sgx_trts::libc; use sgx_trts::libc;
use sgx_types::*;
use std::backtrace::{self, PrintFormat};
use std::ffi::CStr; // a borrowed C string
use std::panic;
#[macro_use] #[macro_use]
mod prelude; mod prelude;
@ -31,9 +29,9 @@ mod errno;
mod fs; mod fs;
mod process; mod process;
mod syscall; mod syscall;
mod vm;
mod util;
mod time; mod time;
mod util;
mod vm;
use prelude::*; use prelude::*;

@ -1,29 +1,30 @@
use std;
pub use sgx_types::*;
pub use sgx_trts::libc; pub use sgx_trts::libc;
pub use sgx_types::*;
use std;
//pub use {elf_helper, errno, file, file_table, fs, mm, process, syscall, vma, }; //pub use {elf_helper, errno, file, file_table, fs, mm, process, syscall, vma, };
pub use std::marker::{Sync, Send};
pub use std::sync::{Arc, SgxMutex, SgxMutexGuard, SgxRwLock,
SgxRwLockReadGuard, SgxRwLockWriteGuard};
pub use std::cell::{Cell, RefCell}; pub use std::cell::{Cell, RefCell};
pub use std::marker::{Send, Sync};
pub use std::result::Result; pub use std::result::Result;
pub use std::sync::{
Arc, SgxMutex, SgxMutexGuard, SgxRwLock, SgxRwLockReadGuard, SgxRwLockWriteGuard,
};
//pub use std::borrow::BorrowMut; //pub use std::borrow::BorrowMut;
pub use std::borrow::ToOwned;
pub use std::boxed::Box; pub use std::boxed::Box;
pub use std::vec::Vec; pub use std::cmp::{Ordering, PartialOrd};
pub use std::string::{String};
pub use std::collections::{HashMap, VecDeque}; pub use std::collections::{HashMap, VecDeque};
pub use std::fmt::{Debug, Display}; pub use std::fmt::{Debug, Display};
pub use std::io::{Read, Write, Seek, SeekFrom}; pub use std::io::{Read, Seek, SeekFrom, Write};
pub use std::rc::{Rc}; pub use std::iter::Iterator;
pub use std::iter::{Iterator}; pub use std::rc::Rc;
pub use std::cmp::{Ordering, PartialOrd}; pub use std::string::String;
pub use std::borrow::{ToOwned}; pub use std::vec::Vec;
pub use errno::Error as Error;
pub use errno::Errno; pub use errno::Errno;
pub use errno::Errno::{*}; pub use errno::Errno::*;
pub use errno::Error;
pub use fs::off_t; pub use fs::off_t;
@ -34,12 +35,16 @@ macro_rules! debug_trace {
} }
macro_rules! errno { macro_rules! errno {
($errno: ident, $msg: expr) => { ($errno: ident, $msg: expr) => {{
{ println!(
println!("ERROR: {} ({}, line {} in file {})", $errno, $msg, line!(), file!()); "ERROR: {} ({}, line {} in file {})",
$errno,
$msg,
line!(),
file!()
);
Err(Error::new($errno, $msg)) Err(Error::new($errno, $msg))
} }};
}
} }
pub fn align_up(addr: usize, align: usize) -> usize { pub fn align_up(addr: usize, align: usize) -> usize {

@ -1,4 +1,4 @@
use super::{*}; use super::*;
// TODO: make sure Processes are released eventually // TODO: make sure Processes are released eventually
@ -11,7 +11,6 @@ pub enum ChildProcessFilter {
unsafe impl Send for ChildProcessFilter {} unsafe impl Send for ChildProcessFilter {}
pub fn do_exit(exit_status: i32) { pub fn do_exit(exit_status: i32) {
let current_ref = get_current(); let current_ref = get_current();
let mut current = current_ref.lock().unwrap(); let mut current = current_ref.lock().unwrap();
@ -35,30 +34,29 @@ pub fn do_exit(exit_status: i32) {
lock_two_in_order(&parent_ref, &current_ref) lock_two_in_order(&parent_ref, &current_ref)
}; };
// Wake up the parent if it is waiting on this child // Wake up the parent if it is waiting on this child
if parent.waiting_children.is_none() { return; } if parent.waiting_children.is_none() {
return;
}
let mut wait_queue = parent.waiting_children.as_mut().unwrap(); let mut wait_queue = parent.waiting_children.as_mut().unwrap();
wait_queue.del_and_wake_one_waiter(|waiter_data| -> Option<pid_t> { wait_queue.del_and_wake_one_waiter(|waiter_data| -> Option<pid_t> {
match waiter_data { match waiter_data {
ChildProcessFilter::WithAnyPID => { ChildProcessFilter::WithAnyPID => {}
},
ChildProcessFilter::WithPID(required_pid) => { ChildProcessFilter::WithPID(required_pid) => {
if current.get_pid() != *required_pid { if current.get_pid() != *required_pid {
return None; return None;
} }
}, }
ChildProcessFilter::WithPGID(required_pgid) => { ChildProcessFilter::WithPGID(required_pgid) => {
if current.get_pgid() != *required_pgid { if current.get_pgid() != *required_pgid {
return None; return None;
} }
}, }
} }
Some(current.get_pid()) Some(current.get_pid())
}); });
} }
pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32) pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32) -> Result<pid_t, Error> {
-> Result<pid_t, Error>
{
let current_ref = get_current(); let current_ref = get_current();
let waiter = { let waiter = {
let mut current = current_ref.lock().unwrap(); let mut current = current_ref.lock().unwrap();
@ -69,17 +67,13 @@ pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32)
let child = child_ref.lock().unwrap(); let child = child_ref.lock().unwrap();
let may_wait_for = match child_filter { let may_wait_for = match child_filter {
ChildProcessFilter::WithAnyPID => { ChildProcessFilter::WithAnyPID => true,
true ChildProcessFilter::WithPID(required_pid) => child.get_pid() == *required_pid,
}, ChildProcessFilter::WithPGID(required_pgid) => child.get_pgid() == *required_pgid,
ChildProcessFilter::WithPID(required_pid) => {
child.get_pid() == *required_pid
},
ChildProcessFilter::WithPGID(required_pgid) => {
child.get_pgid() == *required_pgid
}
}; };
if !may_wait_for { continue; } if !may_wait_for {
continue;
}
// Return immediately as a child that we wait for has alreay exited // Return immediately as a child that we wait for has alreay exited
if child.status == Status::ZOMBIE { if child.status == Status::ZOMBIE {
@ -88,7 +82,9 @@ pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32)
any_child_to_wait_for = true; any_child_to_wait_for = true;
} }
if !any_child_to_wait_for { return errno!(ECHILD, "No such child"); } if !any_child_to_wait_for {
return errno!(ECHILD, "No such child");
}
let waiter = Waiter::new(child_filter); let waiter = Waiter::new(child_filter);
let mut wait_queue = WaitQueue::new(); let mut wait_queue = WaitQueue::new();
@ -107,7 +103,9 @@ pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32)
for (child_i, child_weak) in current.children.iter().enumerate() { for (child_i, child_weak) in current.children.iter().enumerate() {
let child_ref = child_weak.upgrade().unwrap(); let child_ref = child_weak.upgrade().unwrap();
let child = child_ref.lock().unwrap(); let child = child_ref.lock().unwrap();
if child.get_pid() != child_pid { continue; } if child.get_pid() != child_pid {
continue;
}
if child.get_status() != Status::ZOMBIE { if child.get_status() != Status::ZOMBIE {
panic!("THIS SHOULD NEVER HAPPEN!"); panic!("THIS SHOULD NEVER HAPPEN!");
@ -126,9 +124,9 @@ pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32)
Ok(child_pid) Ok(child_pid)
} }
fn lock_two_in_order<'a>(first_ref: &'a ProcessRef, second_ref: &'a ProcessRef) -> fn lock_two_in_order<'a>(
(SgxMutexGuard<'a, Process>, SgxMutexGuard<'a, Process>) first_ref: &'a ProcessRef,
{ second_ref: &'a ProcessRef,
) -> (SgxMutexGuard<'a, Process>, SgxMutexGuard<'a, Process>) {
(first_ref.lock().unwrap(), second_ref.lock().unwrap()) (first_ref.lock().unwrap(), second_ref.lock().unwrap())
} }

@ -1,11 +1,11 @@
pub use self::process::{Status, IDLE_PROCESS}; pub use self::process::{Status, IDLE_PROCESS};
pub use self::task::{get_current, run_task}; pub use self::task::{get_current, run_task};
pub mod table { pub mod table {
pub use super::process_table::{get}; pub use super::process_table::get;
} }
pub use self::spawn::{do_spawn, FileAction};
pub use self::exit::{do_exit, do_wait4, ChildProcessFilter}; pub use self::exit::{do_exit, do_wait4, ChildProcessFilter};
pub use self::wait::{Waiter, WaitQueue}; pub use self::spawn::{do_spawn, FileAction};
pub use self::wait::{WaitQueue, Waiter};
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub type pid_t = u32; pub type pid_t = u32;
@ -51,14 +51,14 @@ pub fn do_getppid() -> pid_t {
parent.get_pid() parent.get_pid()
} }
mod task; mod exit;
mod process; mod process;
mod process_table; mod process_table;
mod spawn; mod spawn;
mod task;
mod wait; mod wait;
mod exit;
use super::{*}; use self::task::Task;
use super::*;
use fs::{File, FileRef, FileTable};
use vm::{ProcessVM, VMRangeTrait}; use vm::{ProcessVM, VMRangeTrait};
use fs::{FileTable, File, FileRef};
use self::task::{Task};

@ -1,7 +1,7 @@
use super::task::Task;
use super::*; use super::*;
use super::task::{Task}; use fs::{File, FileRef, FileTable};
use vm::{ProcessVM, VMRangeTrait}; use vm::{ProcessVM, VMRangeTrait};
use fs::{FileTable, File, FileRef};
lazy_static! { lazy_static! {
// Dummy object to make all processes having a parent // Dummy object to make all processes having a parent
@ -24,9 +24,12 @@ lazy_static! {
} }
impl Process { impl Process {
pub fn new(exec_path: &str, task: Task, vm: ProcessVM, file_table: FileTable) pub fn new(
-> Result<(pid_t, ProcessRef), Error> exec_path: &str,
{ task: Task,
vm: ProcessVM,
file_table: FileTable,
) -> Result<(pid_t, ProcessRef), Error> {
let new_pid = process_table::alloc_pid(); let new_pid = process_table::alloc_pid();
let new_process_ref = Arc::new(SgxMutex::new(Process { let new_process_ref = Arc::new(SgxMutex::new(Process {
task: task, task: task,
@ -45,20 +48,48 @@ impl Process {
Ok((new_pid, new_process_ref)) Ok((new_pid, new_process_ref))
} }
pub fn get_task(&self) -> &Task { &self.task } pub fn get_task(&self) -> &Task {
pub fn get_task_mut(&mut self) -> &mut Task { &mut self.task } &self.task
pub fn get_pid(&self) -> pid_t { self.pid } }
pub fn get_pgid(&self) -> pid_t { self.pgid } pub fn get_task_mut(&mut self) -> &mut Task {
pub fn get_tgid(&self) -> pid_t { self.tgid } &mut self.task
pub fn get_status(&self) -> Status { self.status } }
pub fn get_exit_status(&self) -> i32 { self.exit_status } pub fn get_pid(&self) -> pid_t {
pub fn get_exec_path(&self) -> &str { &self.exec_path } self.pid
pub fn get_vm(&self) -> &ProcessVM { &self.vm } }
pub fn get_vm_mut(&mut self) -> &mut ProcessVM { &mut self.vm } pub fn get_pgid(&self) -> pid_t {
pub fn get_files(&self) -> &FileTable { &self.file_table } self.pgid
pub fn get_files_mut(&mut self) -> &mut FileTable { &mut self.file_table } }
pub fn get_parent(&self) -> &ProcessRef { self.parent.as_ref().unwrap() } pub fn get_tgid(&self) -> pid_t {
pub fn get_children(&self) -> &[ProcessWeakRef] { &self.children } self.tgid
}
pub fn get_status(&self) -> Status {
self.status
}
pub fn get_exit_status(&self) -> i32 {
self.exit_status
}
pub fn get_exec_path(&self) -> &str {
&self.exec_path
}
pub fn get_vm(&self) -> &ProcessVM {
&self.vm
}
pub fn get_vm_mut(&mut self) -> &mut ProcessVM {
&mut self.vm
}
pub fn get_files(&self) -> &FileTable {
&self.file_table
}
pub fn get_files_mut(&mut self) -> &mut FileTable {
&mut self.file_table
}
pub fn get_parent(&self) -> &ProcessRef {
self.parent.as_ref().unwrap()
}
pub fn get_children(&self) -> &[ProcessWeakRef] {
&self.children
}
} }
impl Drop for Process { impl Drop for Process {
@ -67,7 +98,6 @@ impl Drop for Process {
} }
} }
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub enum Status { pub enum Status {
RUNNING, RUNNING,

@ -2,9 +2,8 @@ use super::*;
use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::atomic::{AtomicU32, Ordering};
lazy_static! { lazy_static! {
static ref PROCESS_TABLE: SgxMutex<HashMap<pid_t, ProcessRef>> = { static ref PROCESS_TABLE: SgxMutex<HashMap<pid_t, ProcessRef>> =
SgxMutex::new(HashMap::new()) { SgxMutex::new(HashMap::new()) };
};
} }
pub fn put(pid: pid_t, process: ProcessRef) { pub fn put(pid: pid_t, process: ProcessRef) {
@ -19,8 +18,7 @@ pub fn get(pid: pid_t) -> Option<ProcessRef> {
PROCESS_TABLE.lock().unwrap().get(&pid).map(|pr| pr.clone()) PROCESS_TABLE.lock().unwrap().get(&pid).map(|pr| pr.clone())
} }
static NEXT_PID: AtomicU32 = AtomicU32::new(1);
static NEXT_PID : AtomicU32 = AtomicU32::new(1);
pub fn alloc_pid() -> u32 { pub fn alloc_pid() -> u32 {
NEXT_PID.fetch_add(1, Ordering::SeqCst) NEXT_PID.fetch_add(1, Ordering::SeqCst)
@ -28,7 +26,8 @@ pub fn alloc_pid() -> u32 {
pub fn free_pid(pid: u32) { pub fn free_pid(pid: u32) {
// PID 0 is reserved for idle thread, thus no need to free // PID 0 is reserved for idle thread, thus no need to free
if pid == 0 { return; } if pid == 0 {
return;
}
// TODO: // TODO:
} }

@ -1,18 +1,17 @@
use super::*; use super::*;
use xmas_elf::{sections, ElfFile, program, P64}; use xmas_elf::program::ProgramHeader;
use xmas_elf::symbol_table::{Entry64, DynEntry64}; use xmas_elf::sections::Rela;
use xmas_elf::program::{ProgramHeader};
use xmas_elf::sections::{Rela};
use xmas_elf::symbol_table::Entry; use xmas_elf::symbol_table::Entry;
use xmas_elf::symbol_table::{DynEntry64, Entry64};
use xmas_elf::{program, sections, ElfFile, P64};
pub fn print_program_headers(elf_file: &ElfFile) -> Result<(), Error> { pub fn print_program_headers(elf_file: &ElfFile) -> Result<(), Error> {
println!("Program headers:"); println!("Program headers:");
let ph_iter = elf_file.program_iter(); let ph_iter = elf_file.program_iter();
for sect in ph_iter { for sect in ph_iter {
program::sanity_check(sect, &elf_file) program::sanity_check(sect, &elf_file)
.map_err(|e| (Errno::ENOEXEC, .map_err(|e| (Errno::ENOEXEC, "Sanity check for program header failed"))?;
"Sanity check for program header failed"))?;
println!("\t{:?}", sect.get_type()); println!("\t{:?}", sect.get_type());
} }
Ok(()) Ok(())
@ -24,11 +23,10 @@ pub fn print_sections(elf_file: &ElfFile) -> Result<(), Error> {
sect_iter.next(); // Skip the first, dummy section sect_iter.next(); // Skip the first, dummy section
for sect in sect_iter { for sect in sect_iter {
sections::sanity_check(sect, &elf_file) sections::sanity_check(sect, &elf_file)
.map_err(|e| (Errno::ENOEXEC, .map_err(|e| (Errno::ENOEXEC, "Sanity check for program header failed"))?;
"Sanity check for program header failed"))?; let sec_name = sect
let sec_name = sect.get_name(&elf_file) .get_name(&elf_file)
.map_err(|e| (Errno::ENOEXEC, .map_err(|e| (Errno::ENOEXEC, "Failed to get section name"))?;
"Failed to get section name"))?;
println!("\t{}\n{:?}", sec_name, sect); println!("\t{}\n{:?}", sec_name, sect);
} }
Ok(()) Ok(())
@ -36,107 +34,107 @@ pub fn print_sections(elf_file: &ElfFile) -> Result<(), Error> {
pub fn print_rela_plt_section(elf_file: &ElfFile) -> Result<(), Error> { pub fn print_rela_plt_section(elf_file: &ElfFile) -> Result<(), Error> {
let rela_entries = get_rela_entries(elf_file, ".rela.plt") let rela_entries = get_rela_entries(elf_file, ".rela.plt")
.map_err(|e| (Errno::ENOEXEC, .map_err(|e| (Errno::ENOEXEC, "Failed to get .pltrel entries"))?;
"Failed to get .pltrel entries"))?;
let dynsym_entries = get_dynsym_entries(elf_file) let dynsym_entries = get_dynsym_entries(elf_file)
.map_err(|e| (Errno::ENOEXEC, .map_err(|e| (Errno::ENOEXEC, "Failed to get .dynsym entries"))?;
"Failed to get .dynsym entries"))?;
println!(".rela.plt section:"); println!(".rela.plt section:");
for entry in rela_entries { for entry in rela_entries {
println!("\toffset: {}, symbol index: {}, type: {}, addend: {}", println!(
"\toffset: {}, symbol index: {}, type: {}, addend: {}",
entry.get_offset(), entry.get_offset(),
entry.get_symbol_table_index(), entry.get_symbol_table_index(),
entry.get_type(), entry.get_type(),
entry.get_addend()); entry.get_addend()
);
let symidx = entry.get_symbol_table_index() as usize; let symidx = entry.get_symbol_table_index() as usize;
let dynsym_entry = &dynsym_entries[symidx]; let dynsym_entry = &dynsym_entries[symidx];
let dynsym_name = dynsym_entry.get_name(&elf_file) let dynsym_name = dynsym_entry
.map_err(|e| (Errno::ENOEXEC, .get_name(&elf_file)
"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); println!("\t\t{} = {:?}", dynsym_name, dynsym_entry);
} }
Ok(()) Ok(())
} }
pub fn get_data_program_header<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) pub fn get_data_program_header<'b, 'a: 'b>(
-> Result<ProgramHeader<'a>, Error> elf_file: &'b ElfFile<'a>,
{ ) -> Result<ProgramHeader<'a>, Error> {
let mut ph_iter = elf_file.program_iter(); let mut ph_iter = elf_file.program_iter();
ph_iter.find(|&ph| ph.get_type() == Ok(program::Type::Load) && ph_iter
!ph.flags().is_execute() && .find(|&ph| {
ph.flags().is_write() && ph.get_type() == Ok(program::Type::Load)
ph.flags().is_read()) && !ph.flags().is_execute()
&& 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").into())
} }
pub fn get_code_program_header<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) pub fn get_code_program_header<'b, 'a: 'b>(
-> Result<ProgramHeader<'a>, Error> elf_file: &'b ElfFile<'a>,
{ ) -> Result<ProgramHeader<'a>, Error> {
let mut ph_iter = elf_file.program_iter(); let mut ph_iter = elf_file.program_iter();
ph_iter.find(|&ph| ph.get_type() == Ok(program::Type::Load) && ph_iter
ph.flags().is_execute() && .find(|&ph| {
!ph.flags().is_write() && ph.get_type() == Ok(program::Type::Load)
ph.flags().is_read()) && ph.flags().is_execute()
&& !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").into())
} }
pub fn get_start_address<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) pub fn get_start_address<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<usize, Error> {
-> Result<usize, Error>
{
let sym_entries = get_sym_entries(elf_file)?; let sym_entries = get_sym_entries(elf_file)?;
for sym_entry in sym_entries { for sym_entry in sym_entries {
let sym_str = sym_entry.get_name(elf_file) let sym_str = sym_entry
.map_err(|e| Error::new(Errno::ENOEXEC, .get_name(elf_file)
"Failed to get the name of a symbol"))?; .map_err(|e| Error::new(Errno::ENOEXEC, "Failed to get the name of a symbol"))?;
if sym_str == "_start" { if sym_str == "_start" {
return Ok(sym_entry.value() as usize) return Ok(sym_entry.value() as usize);
} }
} }
Err((Errno::ENOEXEC, "Failed to get the _start symbol").into()) Err((Errno::ENOEXEC, "Failed to get the _start symbol").into())
} }
pub fn get_sym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) pub fn get_sym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<&'a [Entry64], Error> {
-> Result<&'a [Entry64], Error> elf_file
{ .find_section_by_name(".symtab")
elf_file.find_section_by_name(".symtab") .and_then(|symtab_section| symtab_section.get_data(&elf_file).ok())
.and_then(|symtab_section| { .and_then(|symbol_table| match symbol_table {
symtab_section.get_data(&elf_file).ok()
}).and_then(|symbol_table| {
match symbol_table {
sections::SectionData::SymbolTable64(entries) => Some(entries), sections::SectionData::SymbolTable64(entries) => Some(entries),
_ => None, _ => None,
} })
}).ok_or_else(|| (Errno::ENOEXEC, "Failed get the symbol entries").into()) .ok_or_else(|| (Errno::ENOEXEC, "Failed get the symbol entries").into())
} }
pub fn get_rela_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>, sec_name: &'b str) pub fn get_rela_entries<'b, 'a: 'b>(
-> Result<&'a [Rela<P64>], Error> elf_file: &'b ElfFile<'a>,
{ sec_name: &'b str,
elf_file.find_section_by_name(sec_name) ) -> Result<&'a [Rela<P64>], Error> {
.and_then(|plt_rela_section| { elf_file
plt_rela_section.get_data(&elf_file).ok() .find_section_by_name(sec_name)
}).and_then(|rela_table| { .and_then(|plt_rela_section| plt_rela_section.get_data(&elf_file).ok())
match rela_table { .and_then(|rela_table| match rela_table {
sections::SectionData::Rela64(entries) => Some(entries), sections::SectionData::Rela64(entries) => Some(entries),
_ => None, _ => None,
} })
}).ok_or_else(|| (Errno::ENOEXEC, "Failed to get .rela.plt entries").into()) .ok_or_else(|| (Errno::ENOEXEC, "Failed to get .rela.plt entries").into())
} }
pub fn get_dynsym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) pub fn get_dynsym_entries<'b, 'a: 'b>(
-> Result<&'a [DynEntry64], Error> elf_file: &'b ElfFile<'a>,
{ ) -> Result<&'a [DynEntry64], Error> {
elf_file.find_section_by_name(".dynsym") elf_file
.and_then(|dynamic_section| { .find_section_by_name(".dynsym")
dynamic_section.get_data(&elf_file).ok() .and_then(|dynamic_section| dynamic_section.get_data(&elf_file).ok())
}).and_then(|dynamic_table| { .and_then(|dynamic_table| match dynamic_table {
match dynamic_table {
sections::SectionData::DynSymbolTable64(entries) => Some(entries), sections::SectionData::DynSymbolTable64(entries) => Some(entries),
_ => None, _ => None,
} })
}).ok_or_else(|| (Errno::ENOEXEC, "Failed to get .dynsym entries").into()) .ok_or_else(|| (Errno::ENOEXEC, "Failed to get .dynsym entries").into())
} }

@ -1,8 +1,8 @@
use super::*; use super::*;
use {std, std::mem, std::ptr};
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::os::raw::c_char; use std::os::raw::c_char;
use {std, std::mem, std::ptr};
/* /*
* The initial stack of a process looks like below: * The initial stack of a process looks like below:
@ -47,10 +47,13 @@ use std::os::raw::c_char;
* *
*/ */
pub fn do_init(stack_top: usize, init_area_size: usize, pub fn do_init(
argv: &[CString], envp: &[CString], auxtbl: &AuxTable) stack_top: usize,
-> Result<usize, Error> init_area_size: usize,
{ argv: &[CString],
envp: &[CString],
auxtbl: &AuxTable,
) -> Result<usize, Error> {
let stack_buf = unsafe { StackBuf::new(stack_top, init_area_size)? }; let stack_buf = unsafe { StackBuf::new(stack_top, init_area_size)? };
let envp_cloned = clone_cstrings_on_stack(&stack_buf, envp)?; let envp_cloned = clone_cstrings_on_stack(&stack_buf, envp)?;
let argv_cloned = clone_cstrings_on_stack(&stack_buf, argv)?; let argv_cloned = clone_cstrings_on_stack(&stack_buf, argv)?;
@ -73,7 +76,7 @@ pub struct StackBuf {
} }
impl StackBuf { impl StackBuf {
pub unsafe fn new(stack_top: usize, stack_size: usize) -> Result<StackBuf, Error>{ pub unsafe fn new(stack_top: usize, stack_size: usize) -> Result<StackBuf, Error> {
if stack_top % 16 != 0 || stack_size == 0 || stack_top < stack_size { if stack_top % 16 != 0 || stack_size == 0 || stack_top < stack_size {
return errno!(EINVAL, "Invalid stack range"); return errno!(EINVAL, "Invalid stack range");
}; };
@ -85,30 +88,38 @@ impl StackBuf {
} }
pub fn put<T>(&self, val: T) -> Result<*const T, Error> pub fn put<T>(&self, val: T) -> Result<*const T, Error>
where T : Copy where
T: Copy,
{ {
let val_size = mem::size_of::<T>(); let val_size = mem::size_of::<T>();
let val_align = mem::align_of::<T>(); let val_align = mem::align_of::<T>();
let val_ptr = self.alloc(val_size, val_align)? as *mut T; let val_ptr = self.alloc(val_size, val_align)? as *mut T;
unsafe { ptr::write(val_ptr, val); } unsafe {
ptr::write(val_ptr, val);
}
Ok(val_ptr as *const T) Ok(val_ptr as *const T)
} }
pub fn put_slice<T>(&self, vals: &[T]) -> Result<*const T, Error> pub fn put_slice<T>(&self, vals: &[T]) -> Result<*const T, Error>
where T: Copy where
T: Copy,
{ {
let val_size = mem::size_of::<T>(); let val_size = mem::size_of::<T>();
let val_align = mem::align_of::<T>(); let val_align = mem::align_of::<T>();
let total_size = { let total_size = {
let num_vals = vals.len(); let num_vals = vals.len();
if num_vals == 0 { return Ok(self.get_pos() as *const T); } if num_vals == 0 {
return Ok(self.get_pos() as *const T);
}
val_size * num_vals val_size * num_vals
}; };
let base_ptr = self.alloc(total_size, val_align)? as *mut T; let base_ptr = self.alloc(total_size, val_align)? as *mut T;
let mut val_ptr = base_ptr; let mut val_ptr = base_ptr;
for v in vals { for v in vals {
unsafe { ptr::write(val_ptr, *v); } unsafe {
ptr::write(val_ptr, *v);
}
val_ptr = unsafe { val_ptr.offset(1) }; val_ptr = unsafe { val_ptr.offset(1) };
} }
@ -139,26 +150,21 @@ impl StackBuf {
} }
} }
fn clone_cstrings_on_stack<'a, 'b>(
fn clone_cstrings_on_stack<'a, 'b>(stack: &'a StackBuf, stack: &'a StackBuf,
cstrings: &'b [CString]) cstrings: &'b [CString],
-> Result<Vec<&'a CStr>, Error> ) -> Result<Vec<&'a CStr>, Error> {
{
let mut cstrs_cloned = Vec::new(); let mut cstrs_cloned = Vec::new();
for cs in cstrings.iter().rev() { for cs in cstrings.iter().rev() {
let cstrp_cloned = stack.put_cstr(cs)?; let cstrp_cloned = stack.put_cstr(cs)?;
let cstr_cloned = unsafe { let cstr_cloned = unsafe { CStr::from_ptr::<'a>(cstrp_cloned as *const c_char) };
CStr::from_ptr::<'a>(cstrp_cloned as *const c_char)
};
cstrs_cloned.push(cstr_cloned); cstrs_cloned.push(cstr_cloned);
} }
cstrs_cloned.reverse(); cstrs_cloned.reverse();
Ok(cstrs_cloned) Ok(cstrs_cloned)
} }
fn dump_auxtbl_on_stack<'a, 'b>(stack: &'a StackBuf, auxtbl: &'b AuxTable) fn dump_auxtbl_on_stack<'a, 'b>(stack: &'a StackBuf, auxtbl: &'b AuxTable) -> Result<(), Error> {
-> Result<(), Error>
{
// For every key-value pari, dump the value first, then the key // For every key-value pari, dump the value first, then the key
stack.put(AuxKey::AT_NULL as u64); stack.put(AuxKey::AT_NULL as u64);
stack.put(AuxKey::AT_NULL as u64); stack.put(AuxKey::AT_NULL as u64);
@ -169,9 +175,10 @@ fn dump_auxtbl_on_stack<'a, 'b>(stack: &'a StackBuf, auxtbl: &'b AuxTable)
Ok(()) Ok(())
} }
fn dump_cstrptrs_on_stack<'a, 'b>(stack: &'a StackBuf, strptrs: &'b [&'a CStr]) fn dump_cstrptrs_on_stack<'a, 'b>(
-> Result<(), Error> stack: &'a StackBuf,
{ strptrs: &'b [&'a CStr],
) -> Result<(), Error> {
stack.put(0 as u64); // End with a NULL pointer stack.put(0 as u64); // End with a NULL pointer
for sp in strptrs.iter().rev() { for sp in strptrs.iter().rev() {
stack.put(sp.as_ptr() as u64); stack.put(sp.as_ptr() as u64);
@ -179,9 +186,8 @@ fn dump_cstrptrs_on_stack<'a, 'b>(stack: &'a StackBuf, strptrs: &'b [&'a CStr])
Ok(()) Ok(())
} }
/* Symbolic values for the entries in the auxiliary table /* Symbolic values for the entries in the auxiliary table
put on the initial stack */ put on the initial stack */
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub enum AuxKey { pub enum AuxKey {
@ -205,7 +211,6 @@ pub enum AuxKey {
AT_CLKTCK = 17, /* frequency at which times() increments */ AT_CLKTCK = 17, /* frequency at which times() increments */
/* 18...22 not used */ /* 18...22 not used */
AT_SECURE = 23, /* secure mode boolean */ AT_SECURE = 23, /* secure mode boolean */
AT_BASE_PLATFORM = 24, /* string identifying real platform, may AT_BASE_PLATFORM = 24, /* string identifying real platform, may
* differ from AT_PLATFORM. */ * differ from AT_PLATFORM. */
@ -213,11 +218,9 @@ pub enum AuxKey {
AT_HWCAP2 = 26, /* extension of AT_HWCAP */ AT_HWCAP2 = 26, /* extension of AT_HWCAP */
/* 28...30 not used */ /* 28...30 not used */
AT_EXECFN = 31, /* filename of program */ AT_EXECFN = 31, /* filename of program */
} }
static AUX_KEYS: &'static [AuxKey] = &[ static AUX_KEYS: &'static [AuxKey] = &[
AuxKey::AT_NULL, AuxKey::AT_NULL,
AuxKey::AT_IGNORE, AuxKey::AT_IGNORE,
@ -252,14 +255,12 @@ impl AuxKey {
let next_idx = self_idx + 1; let next_idx = self_idx + 1;
if next_idx < AUX_KEYS.len() { if next_idx < AUX_KEYS.len() {
Some(AUX_KEYS[next_idx]) Some(AUX_KEYS[next_idx])
} } else {
else {
None None
} }
} }
} }
#[derive(Clone, Default, Copy, Debug)] #[derive(Clone, Default, Copy, Debug)]
pub struct AuxTable { pub struct AuxTable {
values: [Option<u64>; AuxKey::MAX], values: [Option<u64>; AuxKey::MAX],
@ -268,11 +269,11 @@ pub struct AuxTable {
impl AuxTable { impl AuxTable {
pub fn new() -> AuxTable { pub fn new() -> AuxTable {
AuxTable { AuxTable {
values: [None; AuxKey::MAX] values: [None; AuxKey::MAX],
} }
} }
pub fn set_val(&mut self, key: AuxKey, val: u64) -> Result<(), Error>{ pub fn set_val(&mut self, key: AuxKey, val: u64) -> Result<(), Error> {
if key == AuxKey::AT_NULL || key == AuxKey::AT_IGNORE { if key == AuxKey::AT_NULL || key == AuxKey::AT_IGNORE {
return Err(Error::new(Errno::EINVAL, "Illegal key")); return Err(Error::new(Errno::EINVAL, "Illegal key"));
} }
@ -315,10 +316,12 @@ impl<'a> Iterator for AuxTableIter<'a> {
fn next(&mut self) -> Option<(AuxKey, u64)> { fn next(&mut self) -> Option<(AuxKey, u64)> {
loop { loop {
if self.key == None { return None; } if self.key == None {
return None;
}
let key = self.key.unwrap(); let key = self.key.unwrap();
let item = self.tbl.get_val(key).map(|val| (key, val) ); let item = self.tbl.get_val(key).map(|val| (key, val));
self.key = key.next(); self.key = key.next();
if item != None { if item != None {

@ -1,11 +1,11 @@
use self::segment::*;
use super::*; use super::*;
use std::{ptr}; use std::ptr;
use xmas_elf::{ElfFile, header, program, sections}; use xmas_elf::{header, program, sections, ElfFile};
use self::segment::{*};
pub const DEFAULT_STACK_SIZE : usize = 1 * 1024 * 1024; pub const DEFAULT_STACK_SIZE: usize = 1 * 1024 * 1024;
pub const DEFAULT_HEAP_SIZE : usize = 2 * 1024 * 1024; pub const DEFAULT_HEAP_SIZE: usize = 2 * 1024 * 1024;
pub const DEFAULT_MMAP_SIZE : usize = 2 * 1024 * 1024; pub const DEFAULT_MMAP_SIZE: usize = 2 * 1024 * 1024;
pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result<ProcessVM, Error> { pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result<ProcessVM, Error> {
let mut code_seg = get_code_segment(elf_file)?; let mut code_seg = get_code_segment(elf_file)?;
@ -21,8 +21,7 @@ pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result<ProcessVM, Error> {
let stack_size = DEFAULT_STACK_SIZE; let stack_size = DEFAULT_STACK_SIZE;
let heap_size = DEFAULT_HEAP_SIZE; let heap_size = DEFAULT_HEAP_SIZE;
let mmap_size = DEFAULT_MMAP_SIZE; let mmap_size = DEFAULT_MMAP_SIZE;
let mut process_vm = ProcessVM::new(code_size, data_size, heap_size, let mut process_vm = ProcessVM::new(code_size, data_size, heap_size, stack_size, mmap_size)?;
stack_size, mmap_size)?;
// Calculate the "real" addresses // Calculate the "real" addresses
let process_base_addr = process_vm.get_base_addr(); let process_base_addr = process_vm.get_base_addr();
@ -44,9 +43,7 @@ pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result<ProcessVM, Error> {
Ok(process_vm) Ok(process_vm)
} }
fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile) fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile) -> Result<(), Error> {
-> Result<(), Error>
{
let rela_entries = elf_helper::get_rela_entries(elf_file, ".rela.dyn")?; let rela_entries = elf_helper::get_rela_entries(elf_file, ".rela.dyn")?;
for rela_entry in rela_entries { for rela_entry in rela_entries {
/* /*
@ -67,15 +64,13 @@ fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile)
} }
} }
// TODO: need to handle other relocation types // TODO: need to handle other relocation types
_ => { } _ => {}
} }
} }
Ok(()) Ok(())
} }
fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile) fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile) -> Result<(), Error> {
-> Result<(), Error>
{
let syscall_addr = __occlum_syscall as *const () as usize; let syscall_addr = __occlum_syscall as *const () as usize;
let rela_entries = elf_helper::get_rela_entries(elf_file, ".rela.plt")?; let rela_entries = elf_helper::get_rela_entries(elf_file, ".rela.plt")?;
@ -83,9 +78,9 @@ fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile)
for rela_entry in rela_entries { for rela_entry in rela_entries {
let dynsym_idx = rela_entry.get_symbol_table_index() as usize; let dynsym_idx = rela_entry.get_symbol_table_index() as usize;
let dynsym_entry = &dynsym_entries[dynsym_idx]; let dynsym_entry = &dynsym_entries[dynsym_idx];
let dynsym_str = dynsym_entry.get_name(elf_file) let dynsym_str = dynsym_entry
.map_err(|e| Error::new(Errno::ENOEXEC, .get_name(elf_file)
"Failed to get the name of dynamic symbol"))?; .map_err(|e| Error::new(Errno::ENOEXEC, "Failed to get the name of dynamic symbol"))?;
if dynsym_str == "__occlum_syscall" { if dynsym_str == "__occlum_syscall" {
let rela_addr = process_base_addr + rela_entry.get_offset() as usize; let rela_addr = process_base_addr + rela_entry.get_offset() as usize;
@ -98,6 +93,6 @@ fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile)
Ok(()) Ok(())
} }
extern { extern "C" {
fn __occlum_syscall(num: i32, arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64) -> i64; fn __occlum_syscall(num: i32, arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64) -> i64;
} }

@ -1,17 +1,17 @@
use super::*;
use fs::{File, FileDesc, StdinFile, StdoutFile/*, StderrFile*/, FileTable};
use std::path::Path;
use std::ffi::{CStr, CString};
use std::sgxfs::SgxFile;
use xmas_elf::{ElfFile, header, program, sections};
use xmas_elf::symbol_table::Entry;
use self::init_stack::{AuxKey, AuxTable}; use self::init_stack::{AuxKey, AuxTable};
use super::task::{Task}; use super::task::Task;
use super::*;
use fs::{File, FileDesc, FileTable, StdinFile, StdoutFile /*, StderrFile*/};
use std::ffi::{CStr, CString};
use std::path::Path;
use std::sgxfs::SgxFile;
use vm::{ProcessVM, VMRangeTrait}; use vm::{ProcessVM, VMRangeTrait};
use xmas_elf::symbol_table::Entry;
use xmas_elf::{header, program, sections, ElfFile};
mod elf_helper;
mod init_stack; mod init_stack;
mod init_vm; mod init_vm;
mod elf_helper;
mod segment; mod segment;
#[derive(Debug)] #[derive(Debug)]
@ -22,12 +22,15 @@ pub enum FileAction {
Close(FileDesc), Close(FileDesc),
} }
pub fn do_spawn<P: AsRef<Path>>(elf_path: &P, argv: &[CString], envp: &[CString], pub fn do_spawn<P: AsRef<Path>>(
file_actions: &[FileAction], parent_ref: &ProcessRef) elf_path: &P,
-> Result<u32, Error> argv: &[CString],
{ envp: &[CString],
file_actions: &[FileAction],
parent_ref: &ProcessRef,
) -> Result<u32, Error> {
let mut elf_buf = { let mut elf_buf = {
let key : sgx_key_128bit_t = [0 as uint8_t; 16]; let key: sgx_key_128bit_t = [0 as uint8_t; 16];
let mut sgx_file = SgxFile::open_ex(elf_path, &key) let mut sgx_file = SgxFile::open_ex(elf_path, &key)
.map_err(|e| (Errno::ENOENT, "Failed to open the SGX-protected file"))?; .map_err(|e| (Errno::ENOENT, "Failed to open the SGX-protected file"))?;
@ -37,8 +40,8 @@ pub fn do_spawn<P: AsRef<Path>>(elf_path: &P, argv: &[CString], envp: &[CString]
}; };
let elf_file = { let elf_file = {
let elf_file = ElfFile::new(&elf_buf) let elf_file =
.map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?; ElfFile::new(&elf_buf).map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?;
header::sanity_check(&elf_file) 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 ELF file"))?;
/* /*
@ -53,8 +56,7 @@ pub fn do_spawn<P: AsRef<Path>>(elf_path: &P, argv: &[CString], envp: &[CString]
let vm = init_vm::do_init(&elf_file, &elf_buf[..])?; let vm = init_vm::do_init(&elf_file, &elf_buf[..])?;
let task = { let task = {
let program_entry = { let program_entry = {
let program_entry = vm.get_base_addr() + let program_entry = vm.get_base_addr() + elf_helper::get_start_address(&elf_file)?;
elf_helper::get_start_address(&elf_file)?;
if !vm.get_code_vma().contains_obj(program_entry, 16) { if !vm.get_code_vma().contains_obj(program_entry, 16) {
return Err(Error::new(Errno::EINVAL, "Invalid program entry")); return Err(Error::new(Errno::EINVAL, "Invalid program entry"));
} }
@ -73,9 +75,7 @@ pub fn do_spawn<P: AsRef<Path>>(elf_path: &P, argv: &[CString], envp: &[CString]
Ok(new_pid) Ok(new_pid)
} }
fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction]) fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction]) -> Result<FileTable, Error> {
-> Result<FileTable, Error>
{
// Usually, we just inherit the file table from the parent // Usually, we just inherit the file table from the parent
let parent = parent_ref.lock().unwrap(); let parent = parent_ref.lock().unwrap();
let should_inherit_file_table = parent.get_pid() > 0; let should_inherit_file_table = parent.get_pid() > 0;
@ -89,7 +89,7 @@ fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction])
if old_fd != new_fd { if old_fd != new_fd {
cloned_file_table.put_at(*new_fd, file, false); cloned_file_table.put_at(*new_fd, file, false);
} }
}, }
FileAction::Close(fd) => { FileAction::Close(fd) => {
cloned_file_table.del(*fd)?; cloned_file_table.del(*fd)?;
} }
@ -101,8 +101,8 @@ fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction])
// But, for init process, we initialize file table for it // But, for init process, we initialize file table for it
let mut file_table = FileTable::new(); let mut file_table = FileTable::new();
let stdin : Arc<Box<File>> = Arc::new(Box::new(StdinFile::new())); let stdin: Arc<Box<File>> = Arc::new(Box::new(StdinFile::new()));
let stdout : Arc<Box<File>> = Arc::new(Box::new(StdoutFile::new())); let stdout: Arc<Box<File>> = Arc::new(Box::new(StdoutFile::new()));
// TODO: implement and use a real stderr // TODO: implement and use a real stderr
let stderr = stdout.clone(); let stderr = stdout.clone();
file_table.put(stdin, false); file_table.put(stdin, false);
@ -111,21 +111,21 @@ fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction])
Ok(file_table) Ok(file_table)
} }
fn init_task(user_entry: usize, stack_top: usize, fn init_task(
argv: &[CString], envp: &[CString]) user_entry: usize,
-> Result<Task, Error> stack_top: usize,
{ argv: &[CString],
envp: &[CString],
) -> Result<Task, Error> {
let user_stack = init_stack(stack_top, argv, envp)?; let user_stack = init_stack(stack_top, argv, envp)?;
Ok(Task { Ok(Task {
user_stack_addr: user_stack, user_stack_addr: user_stack,
user_entry_addr: user_entry, user_entry_addr: user_entry,
.. Default::default() ..Default::default()
}) })
} }
fn init_stack(stack_top: usize, argv: &[CString], envp: &[CString]) fn init_stack(stack_top: usize, argv: &[CString], envp: &[CString]) -> Result<usize, Error> {
-> Result<usize, Error>
{
let mut auxtbl = AuxTable::new(); let mut auxtbl = AuxTable::new();
auxtbl.set_val(AuxKey::AT_PAGESZ, 4096)?; auxtbl.set_val(AuxKey::AT_PAGESZ, 4096)?;
auxtbl.set_val(AuxKey::AT_UID, 0)?; auxtbl.set_val(AuxKey::AT_UID, 0)?;
@ -137,8 +137,7 @@ fn init_stack(stack_top: usize, argv: &[CString], envp: &[CString])
init_stack::do_init(stack_top, 4096, argv, envp, &auxtbl) init_stack::do_init(stack_top, 4096, argv, envp, &auxtbl)
} }
fn parent_adopts_new_child(parent_ref: &ProcessRef, child_ref: &ProcessRef) fn parent_adopts_new_child(parent_ref: &ProcessRef, child_ref: &ProcessRef) {
{
let mut parent = parent_ref.lock().unwrap(); let mut parent = parent_ref.lock().unwrap();
let mut child = child_ref.lock().unwrap(); let mut child = child_ref.lock().unwrap();
parent.children.push(Arc::downgrade(child_ref)); parent.children.push(Arc::downgrade(child_ref));

@ -1,7 +1,6 @@
use super::*; use super::*;
use std::{slice}; use std::slice;
use xmas_elf::program::{ProgramHeader}; use xmas_elf::program::ProgramHeader;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct Segment { pub struct Segment {
@ -22,31 +21,35 @@ pub const PERM_W: u32 = 0x2;
pub const PERM_X: u32 = 0x4; pub const PERM_X: u32 = 0x4;
impl Segment { impl Segment {
pub fn get_mem_addr(&self) -> usize { self.mem_addr } pub fn get_mem_addr(&self) -> usize {
pub fn get_mem_align(&self) -> usize { self.mem_align } self.mem_addr
pub fn get_mem_size(&self) -> usize { self.mem_size } }
pub fn get_mem_align(&self) -> usize {
self.mem_align
}
pub fn get_mem_size(&self) -> usize {
self.mem_size
}
pub fn from_program_header(ph: &ProgramHeader) -> Result<Segment, Error> { pub fn from_program_header(ph: &ProgramHeader) -> Result<Segment, Error> {
let ph64 = match ph { let ph64 = match ph {
ProgramHeader::Ph32(ph) => { ProgramHeader::Ph32(ph) => {
return Err((Errno::ENOEXEC, "Not support 32-bit ELF").into()) return Err((Errno::ENOEXEC, "Not support 32-bit ELF").into());
}
ProgramHeader::Ph64(ph64) => {
ph64
} }
ProgramHeader::Ph64(ph64) => ph64,
}; };
if ph64.align > 1 && ((ph64.offset % ph64.align) != if ph64.align > 1 && ((ph64.offset % ph64.align) != (ph64.virtual_addr % ph64.align)) {
(ph64.virtual_addr % ph64.align)) { return Err((
return Err((Errno::EINVAL, Errno::EINVAL,
"Memory address and file offset is not equal, per modulo").into()); "Memory address and file offset is not equal, per modulo",
)
.into());
} }
if ph64.mem_size < ph64.file_size { if ph64.mem_size < ph64.file_size {
return Err((Errno::EINVAL, return Err((Errno::EINVAL, "Memory size must be greater than file size").into());
"Memory size must be greater than file size").into());
} }
if !ph64.align.is_power_of_two() { if !ph64.align.is_power_of_two() {
return Err((Errno::EINVAL, return Err((Errno::EINVAL, "Memory alignment must be a power of two").into());
"Memory alignment must be a power of two").into());
} }
Ok(Segment { Ok(Segment {
@ -61,16 +64,20 @@ impl Segment {
pub fn load_from_file(&self, elf_buf: &[u8]) { pub fn load_from_file(&self, elf_buf: &[u8]) {
let mut target_buf = unsafe { let mut target_buf = unsafe {
slice::from_raw_parts_mut((self.process_base_addr + self.mem_addr) slice::from_raw_parts_mut(
as *mut u8, (self.process_base_addr + self.mem_addr) as *mut u8,
self.file_size) self.file_size,
)
}; };
target_buf.copy_from_slice(&elf_buf[self.file_offset.. target_buf.copy_from_slice(&elf_buf[self.file_offset..(self.file_offset + self.file_size)]);
(self.file_offset + self.file_size)]);
} }
pub fn set_runtime_info(&mut self, process_base_addr: usize, pub fn set_runtime_info(
start_addr: usize, end_addr: usize) { &mut self,
process_base_addr: usize,
start_addr: usize,
end_addr: usize,
) {
self.process_base_addr = process_base_addr; self.process_base_addr = process_base_addr;
self.start_addr = start_addr; self.start_addr = start_addr;
self.end_addr = end_addr; self.end_addr = end_addr;
@ -100,7 +107,7 @@ pub fn get_data_segment(elf_file: &ElfFile) -> Result<Segment, Error> {
} }
#[link(name = "sgx_trts")] #[link(name = "sgx_trts")]
extern { extern "C" {
// XXX: trts_mprotect is a private SGX function that is not supposed to be // XXX: trts_mprotect is a private SGX function that is not supposed to be
// used by external users. At least, this is the case for SGX v2.2. To use // used by external users. At least, this is the case for SGX v2.2. To use
// this function, we need to modify Intel SGX SDK slightly. I suppose // this function, we need to modify Intel SGX SDK slightly. I suppose

@ -1,5 +1,5 @@
use super::*; use super::*;
use std::{mem}; use std::mem;
/// Note: this definition must be in sync with task.h /// Note: this definition must be in sync with task.h
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
@ -13,11 +13,9 @@ pub struct Task {
pub saved_state: usize, // struct jmpbuf* pub saved_state: usize, // struct jmpbuf*
} }
lazy_static! { lazy_static! {
static ref new_process_queue: SgxMutex<VecDeque<ProcessRef>> = { static ref new_process_queue: SgxMutex<VecDeque<ProcessRef>> =
SgxMutex::new(VecDeque::new()) { SgxMutex::new(VecDeque::new()) };
};
} }
pub fn enqueue_task(new_process: ProcessRef) { pub fn enqueue_task(new_process: ProcessRef) {
@ -34,10 +32,9 @@ fn dequeue_task() -> Option<ProcessRef> {
new_process_queue.lock().unwrap().pop_front() new_process_queue.lock().unwrap().pop_front()
} }
pub fn run_task() -> Result<i32, Error> { pub fn run_task() -> Result<i32, Error> {
let new_process : ProcessRef = dequeue_task() let new_process: ProcessRef =
.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); set_current(&new_process);
let (pid, task) = { let (pid, task) = {
@ -105,10 +102,12 @@ fn reset_current() {
}); });
// Prevent memory leakage // Prevent memory leakage
unsafe { drop(Arc::from_raw(process_ptr)); } unsafe {
drop(Arc::from_raw(process_ptr));
}
} }
extern { extern "C" {
fn ocall_run_new_task(ret: *mut i32) -> sgx_status_t; fn ocall_run_new_task(ret: *mut i32) -> sgx_status_t;
fn do_run_task(task: *mut Task) -> i32; fn do_run_task(task: *mut Task) -> i32;
} }

@ -1,18 +1,27 @@
use super::{*}; use super::*;
#[derive(Debug)] #[derive(Debug)]
pub struct Waiter<D, R> pub struct Waiter<D, R>
where D: Sized + Copy, R: Sized + Copy where
D: Sized + Copy,
R: Sized + Copy,
{ {
inner: Arc<SgxMutex<WaiterInner<D, R>>>, inner: Arc<SgxMutex<WaiterInner<D, R>>>,
thread: *const c_void, thread: *const c_void,
} }
unsafe impl<D, R> Send for Waiter<D, R> where D: Sized + Copy, R: Sized + Copy {} unsafe impl<D, R> Send for Waiter<D, R>
where
D: Sized + Copy,
R: Sized + Copy,
{
}
#[derive(Debug)] #[derive(Debug)]
struct WaiterInner<D, R> struct WaiterInner<D, R>
where D: Sized + Copy, R: Sized + Copy where
D: Sized + Copy,
R: Sized + Copy,
{ {
is_woken: bool, is_woken: bool,
data: D, data: D,
@ -20,7 +29,9 @@ struct WaiterInner<D, R>
} }
impl<D, R> Waiter<D, R> impl<D, R> Waiter<D, R>
where D: Sized + Copy, R: Sized + Copy where
D: Sized + Copy,
R: Sized + Copy,
{ {
pub fn new(data: &D) -> Waiter<D, R> { pub fn new(data: &D) -> Waiter<D, R> {
Waiter { Waiter {
@ -50,17 +61,19 @@ impl<D, R> Waiter<D, R>
#[derive(Debug)] #[derive(Debug)]
pub struct WaitQueue<D, R> pub struct WaitQueue<D, R>
where D: Sized + Copy, R: Sized + Copy where
D: Sized + Copy,
R: Sized + Copy,
{ {
waiters: Vec<Waiter<D, R>>, waiters: Vec<Waiter<D, R>>,
} }
impl<D, R> WaitQueue<D, R> impl<D, R> WaitQueue<D, R>
where D: Sized + Copy, R: Sized + Copy where
D: Sized + Copy,
R: Sized + Copy,
{ {
pub fn new() -> WaitQueue<D, R> pub fn new() -> WaitQueue<D, R> {
{
WaitQueue { WaitQueue {
waiters: Vec::new(), waiters: Vec::new(),
} }
@ -74,7 +87,8 @@ impl<D, R> WaitQueue<D, R>
} }
pub fn del_and_wake_one_waiter<F>(&mut self, cond: F) -> usize pub fn del_and_wake_one_waiter<F>(&mut self, cond: F) -> usize
where F: Fn(&D) -> Option<R> where
F: Fn(&D) -> Option<R>,
{ {
let mut waiters = &mut self.waiters; let mut waiters = &mut self.waiters;
let del_waiter_i = { let del_waiter_i = {
@ -84,12 +98,13 @@ impl<D, R> WaitQueue<D, R>
waiter_inner.is_woken = true; waiter_inner.is_woken = true;
waiter_inner.result = Some(waiter_result); waiter_inner.result = Some(waiter_result);
true true
} } else {
else {
false false
} }
}); });
if waiter_i.is_none() { return 0; } if waiter_i.is_none() {
return 0;
}
waiter_i.unwrap() waiter_i.unwrap()
}; };
let del_waiter = waiters.swap_remove(del_waiter_i); let del_waiter = waiters.swap_remove(del_waiter_i);
@ -99,8 +114,8 @@ impl<D, R> WaitQueue<D, R>
} }
fn wait_event(thread: *const c_void) { fn wait_event(thread: *const c_void) {
let mut ret : c_int = 0; let mut ret: c_int = 0;
let mut sgx_ret : c_int = 0; let mut sgx_ret: c_int = 0;
unsafe { unsafe {
sgx_ret = sgx_thread_wait_untrusted_event_ocall(&mut ret as *mut c_int, thread); sgx_ret = sgx_thread_wait_untrusted_event_ocall(&mut ret as *mut c_int, thread);
} }
@ -110,8 +125,8 @@ fn wait_event(thread: *const c_void) {
} }
fn set_event(thread: *const c_void) { fn set_event(thread: *const c_void) {
let mut ret : c_int = 0; let mut ret: c_int = 0;
let mut sgx_ret : c_int = 0; let mut sgx_ret: c_int = 0;
unsafe { unsafe {
sgx_ret = sgx_thread_set_untrusted_event_ocall(&mut ret as *mut c_int, thread); sgx_ret = sgx_thread_set_untrusted_event_ocall(&mut ret as *mut c_int, thread);
} }
@ -120,20 +135,27 @@ fn set_event(thread: *const c_void) {
} }
} }
extern { extern "C" {
fn sgx_thread_get_self() -> *const c_void; fn sgx_thread_get_self() -> *const c_void;
/* Go outside and wait on my untrusted event */ /* Go outside and wait on my untrusted event */
fn sgx_thread_wait_untrusted_event_ocall(ret: *mut c_int, self_thread: *const c_void) -> c_int; fn sgx_thread_wait_untrusted_event_ocall(ret: *mut c_int, self_thread: *const c_void) -> c_int;
/* Wake a thread waiting on its untrusted event */ /* Wake a thread waiting on its untrusted event */
fn sgx_thread_set_untrusted_event_ocall(ret: *mut c_int, waiter_thread: *const c_void) -> c_int; fn sgx_thread_set_untrusted_event_ocall(ret: *mut c_int, waiter_thread: *const c_void)
-> c_int;
/* Wake a thread waiting on its untrusted event, and wait on my untrusted event */ /* Wake a thread waiting on its untrusted event, and wait on my untrusted event */
fn sgx_thread_setwait_untrusted_events_ocall(ret: *mut c_int, fn sgx_thread_setwait_untrusted_events_ocall(
waiter_thread: *const c_void, self_thread: *const c_void) -> c_int; ret: *mut c_int,
waiter_thread: *const c_void,
self_thread: *const c_void,
) -> c_int;
/* Wake multiple threads waiting on their untrusted events */ /* Wake multiple threads waiting on their untrusted events */
fn sgx_thread_set_multiple_untrusted_events_ocall(ret: *mut c_int, fn sgx_thread_set_multiple_untrusted_events_ocall(
waiter_threads: *const *const c_void, total: size_t ) -> c_int; ret: *mut c_int,
waiter_threads: *const *const c_void,
total: size_t,
) -> c_int;
} }

@ -1,13 +1,13 @@
use super::*; use super::*;
use prelude::*;
use {std, fs, process, vm};
use std::{ptr};
use std::ffi::{CStr, CString};
use fs::{off_t, FileDesc}; use fs::{off_t, FileDesc};
use vm::{VMAreaFlags, VMResizeOptions}; use prelude::*;
use process::{pid_t, ChildProcessFilter, FileAction}; use process::{pid_t, ChildProcessFilter, FileAction};
use time::{timeval_t}; use std::ffi::{CStr, CString};
use util::mem_util::from_user::{*}; use std::ptr;
use time::timeval_t;
use util::mem_util::from_user::*;
use vm::{VMAreaFlags, VMResizeOptions};
use {fs, process, std, vm};
// Use the internal syscall wrappers from sgx_tstd // Use the internal syscall wrappers from sgx_tstd
//use std::libc_fs as fs; //use std::libc_fs as fs;
//use std::libc_io as io; //use std::libc_io as io;
@ -18,14 +18,13 @@ pub struct iovec_t {
len: size_t, len: size_t,
} }
/* /*
* This Rust-version of fdop correspond to the C-version one in Occlum. * This Rust-version of fdop correspond to the C-version one in Occlum.
* See <path_to_musl_libc>/src/process/fdop.h. * See <path_to_musl_libc>/src/process/fdop.h.
*/ */
const FDOP_CLOSE : u32 = 1; const FDOP_CLOSE: u32 = 1;
const FDOP_DUP2 : u32 = 2; const FDOP_DUP2: u32 = 2;
const FDOP_OPEN : u32 = 3; const FDOP_OPEN: u32 = 3;
#[repr(C)] #[repr(C)]
#[derive(Debug)] #[derive(Debug)]
@ -41,9 +40,7 @@ pub struct FdOp {
path: *const u8, path: *const u8,
} }
fn clone_file_actions_safely(fdop_ptr: *const FdOp) fn clone_file_actions_safely(fdop_ptr: *const FdOp) -> Result<Vec<FileAction>, Error> {
-> Result<Vec<FileAction>, Error>
{
let mut file_actions = Vec::new(); let mut file_actions = Vec::new();
let mut fdop_ptr = fdop_ptr; let mut fdop_ptr = fdop_ptr;
@ -52,18 +49,14 @@ fn clone_file_actions_safely(fdop_ptr: *const FdOp)
let fdop = unsafe { &*fdop_ptr }; let fdop = unsafe { &*fdop_ptr };
let file_action = match fdop.cmd { let file_action = match fdop.cmd {
FDOP_CLOSE => { FDOP_CLOSE => FileAction::Close(fdop.fd),
FileAction::Close(fdop.fd) FDOP_DUP2 => FileAction::Dup2(fdop.srcfd, fdop.fd),
},
FDOP_DUP2 => {
FileAction::Dup2(fdop.srcfd, fdop.fd)
},
FDOP_OPEN => { FDOP_OPEN => {
return errno!(EINVAL, "Not implemented"); return errno!(EINVAL, "Not implemented");
}, }
_ => { _ => {
return errno!(EINVAL, "Unknown file action command"); return errno!(EINVAL, "Unknown file action command");
}, }
}; };
file_actions.push(file_action); file_actions.push(file_action);
@ -73,14 +66,13 @@ fn clone_file_actions_safely(fdop_ptr: *const FdOp)
Ok(file_actions) Ok(file_actions)
} }
fn do_spawn(child_pid_ptr: *mut c_uint, fn do_spawn(
child_pid_ptr: *mut c_uint,
path: *const c_char, path: *const c_char,
argv: *const *const c_char, argv: *const *const c_char,
envp: *const *const c_char, envp: *const *const c_char,
fdop_list: *const FdOp, fdop_list: *const FdOp,
) ) -> Result<(), Error> {
-> Result<(), Error>
{
check_mut_ptr(child_pid_ptr)?; check_mut_ptr(child_pid_ptr)?;
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
let argv = clone_cstrings_safely(argv)?; let argv = clone_cstrings_safely(argv)?;
@ -94,9 +86,7 @@ fn do_spawn(child_pid_ptr: *mut c_uint,
Ok(()) Ok(())
} }
fn do_read(fd: c_int, buf: *mut c_void, size: size_t) fn do_read(fd: c_int, buf: *mut c_void, size: size_t) -> Result<size_t, Error> {
-> Result<size_t, Error>
{
let fd = fd as FileDesc; let fd = fd as FileDesc;
let safe_buf = { let safe_buf = {
let buf = buf as *mut u8; let buf = buf as *mut u8;
@ -107,9 +97,7 @@ fn do_read(fd: c_int, buf: *mut c_void, size: size_t)
fs::do_read(fd, safe_buf) fs::do_read(fd, safe_buf)
} }
fn do_write(fd: c_int, buf: *const c_void, size: size_t) fn do_write(fd: c_int, buf: *const c_void, size: size_t) -> Result<size_t, Error> {
-> Result<size_t, Error>
{
let fd = fd as FileDesc; let fd = fd as FileDesc;
let safe_buf = { let safe_buf = {
let buf = buf as *mut u8; let buf = buf as *mut u8;
@ -120,9 +108,7 @@ fn do_write(fd: c_int, buf: *const c_void, size: size_t)
fs::do_write(fd, safe_buf) fs::do_write(fd, safe_buf)
} }
fn do_writev(fd: c_int, iov: *const iovec_t, count: c_int) fn do_writev(fd: c_int, iov: *const iovec_t, count: c_int) -> Result<size_t, Error> {
-> Result<size_t, Error>
{
let fd = fd as FileDesc; let fd = fd as FileDesc;
let count = { let count = {
@ -138,9 +124,7 @@ fn do_writev(fd: c_int, iov: *const iovec_t, count: c_int)
for iov_i in 0..count { for iov_i in 0..count {
let iov_ptr = unsafe { iov.offset(iov_i as isize) }; let iov_ptr = unsafe { iov.offset(iov_i as isize) };
let iov = unsafe { &*iov_ptr }; let iov = unsafe { &*iov_ptr };
let buf = unsafe { let buf = unsafe { std::slice::from_raw_parts(iov.base as *const u8, iov.len) };
std::slice::from_raw_parts(iov.base as * const u8, iov.len)
};
bufs_vec.push(buf); bufs_vec.push(buf);
} }
bufs_vec bufs_vec
@ -150,9 +134,7 @@ fn do_writev(fd: c_int, iov: *const iovec_t, count: c_int)
fs::do_writev(fd, bufs) fs::do_writev(fd, bufs)
} }
fn do_readv(fd: c_int, iov: *mut iovec_t, count: c_int) fn do_readv(fd: c_int, iov: *mut iovec_t, count: c_int) -> Result<size_t, Error> {
-> Result<size_t, Error>
{
let fd = fd as FileDesc; let fd = fd as FileDesc;
let count = { let count = {
@ -168,9 +150,7 @@ fn do_readv(fd: c_int, iov: *mut iovec_t, count: c_int)
for iov_i in 0..count { for iov_i in 0..count {
let iov_ptr = unsafe { iov.offset(iov_i as isize) }; let iov_ptr = unsafe { iov.offset(iov_i as isize) };
let iov = unsafe { &*iov_ptr }; let iov = unsafe { &*iov_ptr };
let buf = unsafe { let buf = unsafe { std::slice::from_raw_parts_mut(iov.base as *mut u8, iov.len) };
std::slice::from_raw_parts_mut(iov.base as * mut u8, iov.len)
};
bufs_vec.push(buf); bufs_vec.push(buf);
} }
bufs_vec bufs_vec
@ -180,23 +160,23 @@ fn do_readv(fd: c_int, iov: *mut iovec_t, count: c_int)
fs::do_readv(fd, bufs) fs::do_readv(fd, bufs)
} }
pub fn do_lseek(fd: c_int, offset: off_t, whence: c_int) -> Result<off_t, Error> {
pub fn do_lseek(fd: c_int, offset: off_t, whence: c_int) -> Result<off_t, Error>
{
let fd = fd as FileDesc; let fd = fd as FileDesc;
let seek_from = match whence { let seek_from = match whence {
0 => { // SEEK_SET 0 => {
// SEEK_SET
if offset < 0 { if offset < 0 {
return Err(Error::new(Errno::EINVAL, "Invalid offset")); return Err(Error::new(Errno::EINVAL, "Invalid offset"));
} }
SeekFrom::Start(offset as u64) SeekFrom::Start(offset as u64)
} }
1 => { // SEEK_CUR 1 => {
// SEEK_CUR
SeekFrom::Current(offset) SeekFrom::Current(offset)
} }
2 => { // SEEK_END 2 => {
// SEEK_END
SeekFrom::End(offset) SeekFrom::End(offset)
} }
_ => { _ => {
@ -207,10 +187,14 @@ pub fn do_lseek(fd: c_int, offset: off_t, whence: c_int) -> Result<off_t, Error>
fs::do_lseek(fd, seek_from) fs::do_lseek(fd, seek_from)
} }
fn do_mmap(addr: *const c_void, size: size_t, prot: c_int, fn do_mmap(
flags: c_int, fd: c_int, offset: off_t) addr: *const c_void,
-> Result<*const c_void, Error> size: size_t,
{ prot: c_int,
flags: c_int,
fd: c_int,
offset: off_t,
) -> Result<*const c_void, Error> {
let addr = addr as usize; let addr = addr as usize;
let size = size as usize; let size = size as usize;
let flags = VMAreaFlags(prot as u32); let flags = VMAreaFlags(prot as u32);
@ -223,16 +207,18 @@ fn do_munmap(addr: *const c_void, size: size_t) -> Result<(), Error> {
vm::do_munmap(addr, size) vm::do_munmap(addr, size)
} }
fn do_mremap(old_addr: *const c_void, old_size: size_t, fn do_mremap(
new_size: size_t, flags: c_int, new_addr: *const c_void) old_addr: *const c_void,
-> Result<*const c_void, Error> old_size: size_t,
{ new_size: size_t,
flags: c_int,
new_addr: *const c_void,
) -> Result<*const c_void, Error> {
let old_addr = old_addr as usize; let old_addr = old_addr as usize;
let old_size = old_size as usize; let old_size = old_size as usize;
let mut options = VMResizeOptions::new(new_size)?; let mut options = VMResizeOptions::new(new_size)?;
// TODO: handle flags and new_addr // TODO: handle flags and new_addr
vm::do_mremap(old_addr, old_size, &options) vm::do_mremap(old_addr, old_size, &options).map(|ret_addr| ret_addr as *const c_void)
.map(|ret_addr| ret_addr as *const c_void)
} }
fn do_brk(new_brk_addr: *const c_void) -> Result<*const c_void, Error> { fn do_brk(new_brk_addr: *const c_void) -> Result<*const c_void, Error> {
@ -246,19 +232,13 @@ fn do_wait4(pid: c_int, _exit_status: *mut c_int) -> Result<pid_t, Error> {
} }
let child_process_filter = match pid { let child_process_filter = match pid {
pid if pid < -1 => { pid if pid < -1 => process::ChildProcessFilter::WithPGID((-pid) as pid_t),
process::ChildProcessFilter::WithPGID((-pid) as pid_t) -1 => process::ChildProcessFilter::WithAnyPID,
},
-1 => {
process::ChildProcessFilter::WithAnyPID
},
0 => { 0 => {
let gpid = process::do_getgpid(); let gpid = process::do_getgpid();
process::ChildProcessFilter::WithPGID(gpid) process::ChildProcessFilter::WithPGID(gpid)
}, }
pid if pid > 0 => { pid if pid > 0 => process::ChildProcessFilter::WithPID(pid as pid_t),
process::ChildProcessFilter::WithPID(pid as pid_t)
},
_ => { _ => {
panic!("THIS SHOULD NEVER HAPPEN!"); panic!("THIS SHOULD NEVER HAPPEN!");
} }
@ -267,13 +247,13 @@ fn do_wait4(pid: c_int, _exit_status: *mut c_int) -> Result<pid_t, Error> {
match process::do_wait4(&child_process_filter, &mut exit_status) { match process::do_wait4(&child_process_filter, &mut exit_status) {
Ok(pid) => { Ok(pid) => {
if _exit_status != 0 as *mut c_int { if _exit_status != 0 as *mut c_int {
unsafe { *_exit_status = exit_status; } unsafe {
*_exit_status = exit_status;
}
} }
Ok(pid) Ok(pid)
} }
Err(e) => { Err(e) => Err(e),
Err(e)
}
} }
} }
@ -291,49 +271,56 @@ fn do_pipe2(fds_u: *mut c_int, flags: c_int) -> Result<(), Error> {
fn do_gettimeofday(tv_u: *mut timeval_t) -> Result<(), Error> { fn do_gettimeofday(tv_u: *mut timeval_t) -> Result<(), Error> {
check_mut_ptr(tv_u)?; check_mut_ptr(tv_u)?;
let tv = time::do_gettimeofday(); let tv = time::do_gettimeofday();
unsafe { *tv_u = tv; } unsafe {
*tv_u = tv;
}
Ok(()) Ok(())
} }
const MAP_FAILED: *const c_void = ((-1) as i64) as *const c_void;
const MAP_FAILED : *const c_void = ((-1) as i64) as *const c_void;
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_mmap(addr: *const c_void, length: size_t, prot: c_int, pub extern "C" fn occlum_mmap(
flags: c_int, fd: c_int, offset: off_t) addr: *const c_void,
-> *const c_void length: size_t,
{ prot: c_int,
flags: c_int,
fd: c_int,
offset: off_t,
) -> *const c_void {
match do_mmap(addr, length, prot, flags, fd, offset) { match do_mmap(addr, length, prot, flags, fd, offset) {
Ok(ret_addr) => { ret_addr }, Ok(ret_addr) => ret_addr,
Err(e) => { MAP_FAILED } Err(e) => MAP_FAILED,
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_munmap(addr: *const c_void, length: size_t) -> c_int { pub extern "C" fn occlum_munmap(addr: *const c_void, length: size_t) -> c_int {
match do_munmap(addr, length) { match do_munmap(addr, length) {
Ok(()) => { 0 }, Ok(()) => 0,
Err(e) => { -1 } Err(e) => -1,
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_mremap(old_addr: *const c_void, old_size: size_t, pub extern "C" fn occlum_mremap(
new_size: size_t, flags: c_int, old_addr: *const c_void,
new_addr: *const c_void) old_size: size_t,
-> *const c_void new_size: size_t,
{ flags: c_int,
new_addr: *const c_void,
) -> *const c_void {
match do_mremap(old_addr, old_size, new_size, flags, new_addr) { match do_mremap(old_addr, old_size, new_size, flags, new_addr) {
Ok(ret_addr) => { ret_addr }, Ok(ret_addr) => ret_addr,
Err(e) => { MAP_FAILED } Err(e) => MAP_FAILED,
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_brk(addr: *const c_void) -> *const c_void { pub extern "C" fn occlum_brk(addr: *const c_void) -> *const c_void {
match do_brk(addr) { match do_brk(addr) {
Ok(ret_addr) => { ret_addr }, Ok(ret_addr) => ret_addr,
Err(e) => { MAP_FAILED } Err(e) => MAP_FAILED,
} }
} }
@ -345,96 +332,68 @@ pub extern "C" fn occlum_pipe(fds: *mut c_int) -> c_int {
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_pipe2(fds: *mut c_int, flags: c_int) -> c_int { pub extern "C" fn occlum_pipe2(fds: *mut c_int, flags: c_int) -> c_int {
match do_pipe2(fds, flags) { match do_pipe2(fds, flags) {
Ok(()) => { Ok(()) => 0,
0 Err(e) => e.errno.as_retval(),
},
Err(e) => {
e.errno.as_retval()
}
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_open(path_buf: * const c_char, flags: c_int, mode: c_int) -> c_int { pub extern "C" fn occlum_open(path_buf: *const c_char, flags: c_int, mode: c_int) -> c_int {
let path = unsafe { let path = unsafe {
CStr::from_ptr(path_buf as * const i8).to_string_lossy().into_owned() CStr::from_ptr(path_buf as *const i8)
.to_string_lossy()
.into_owned()
}; };
match fs::do_open(&path, flags as u32, mode as u32) { match fs::do_open(&path, flags as u32, mode as u32) {
Ok(fd) => { Ok(fd) => fd as c_int,
fd as c_int Err(e) => e.errno.as_retval(),
},
Err(e) => {
e.errno.as_retval()
}
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_close(fd: c_int) -> c_int { pub extern "C" fn occlum_close(fd: c_int) -> c_int {
match fs::do_close(fd as FileDesc) { match fs::do_close(fd as FileDesc) {
Ok(()) => { Ok(()) => 0,
0 Err(e) => e.errno.as_retval(),
},
Err(e) => {
e.errno.as_retval()
}
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_read(fd: c_int, buf: * mut c_void, size: size_t) -> ssize_t { pub extern "C" fn occlum_read(fd: c_int, buf: *mut c_void, size: size_t) -> ssize_t {
match do_read(fd, buf, size) { match do_read(fd, buf, size) {
Ok(read_len) => { Ok(read_len) => read_len as ssize_t,
read_len as ssize_t Err(e) => e.errno.as_retval() as ssize_t,
},
Err(e) => {
e.errno.as_retval() as ssize_t
}
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_write(fd: c_int, buf: * const c_void, size: size_t) -> ssize_t { pub extern "C" fn occlum_write(fd: c_int, buf: *const c_void, size: size_t) -> ssize_t {
match do_write(fd, buf, size) { match do_write(fd, buf, size) {
Ok(write_len) => { Ok(write_len) => write_len as ssize_t,
write_len as ssize_t Err(e) => e.errno.as_retval() as ssize_t,
},
Err(e) => {
e.errno.as_retval() as ssize_t
}
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_readv(fd: c_int, iov: * mut iovec_t, count: c_int) -> ssize_t { pub extern "C" fn occlum_readv(fd: c_int, iov: *mut iovec_t, count: c_int) -> ssize_t {
match do_readv(fd, iov, count) { match do_readv(fd, iov, count) {
Ok(read_len) => { Ok(read_len) => read_len as ssize_t,
read_len as ssize_t Err(e) => e.errno.as_retval() as ssize_t,
},
Err(e) => {
e.errno.as_retval() as ssize_t
}
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_writev(fd: c_int, iov: * const iovec_t, count: c_int) -> ssize_t { pub extern "C" fn occlum_writev(fd: c_int, iov: *const iovec_t, count: c_int) -> ssize_t {
match do_writev(fd, iov, count) { match do_writev(fd, iov, count) {
Ok(write_len) => { Ok(write_len) => write_len as ssize_t,
write_len as ssize_t Err(e) => e.errno.as_retval() as ssize_t,
},
Err(e) => {
e.errno.as_retval() as ssize_t
}
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t { pub extern "C" fn occlum_lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t {
match do_lseek(fd, offset, whence) { match do_lseek(fd, offset, whence) {
Ok(ret) => { Ok(ret) => ret,
ret
},
Err(e) => { Err(e) => {
-1 as off_t // this special value indicates error -1 as off_t // this special value indicates error
} }
@ -442,26 +401,22 @@ pub extern "C" fn occlum_lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_getpid() -> c_uint pub extern "C" fn occlum_getpid() -> c_uint {
{
process::do_getpid() process::do_getpid()
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_getppid() -> c_uint pub extern "C" fn occlum_getppid() -> c_uint {
{
process::do_getppid() process::do_getppid()
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_exit(status: i32) pub extern "C" fn occlum_exit(status: i32) {
{
process::do_exit(status); process::do_exit(status);
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_unknown(num: u32) pub extern "C" fn occlum_unknown(num: u32) {
{
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
//println!("[WARNING] Unknown syscall (num = {})", num); //println!("[WARNING] Unknown syscall (num = {})", num);
} }
@ -469,100 +424,73 @@ pub extern "C" fn occlum_unknown(num: u32)
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_spawn( pub extern "C" fn occlum_spawn(
child_pid: *mut c_uint, path: *const c_char, child_pid: *mut c_uint,
argv: *const *const c_char, envp: *const *const c_char, path: *const c_char,
fdop_list: *const FdOp) -> c_int argv: *const *const c_char,
{ envp: *const *const c_char,
fdop_list: *const FdOp,
) -> c_int {
match do_spawn(child_pid, path, argv, envp, fdop_list) { match do_spawn(child_pid, path, argv, envp, fdop_list) {
Ok(()) => 0, Ok(()) => 0,
Err(e) => { e.errno.as_retval() } Err(e) => e.errno.as_retval(),
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_wait4(child_pid: c_int, exit_status: *mut c_int, pub extern "C" fn occlum_wait4(
options: c_int/*, rusage: *mut Rusage*/) -> c_int child_pid: c_int,
{ exit_status: *mut c_int,
options: c_int, /*, rusage: *mut Rusage*/
) -> c_int {
match do_wait4(child_pid, exit_status) { match do_wait4(child_pid, exit_status) {
Ok(pid) => { Ok(pid) => pid as c_int,
pid as c_int Err(e) => e.errno.as_retval(),
}
Err(e) => {
e.errno.as_retval()
}
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_dup(old_fd: c_int) -> c_int pub extern "C" fn occlum_dup(old_fd: c_int) -> c_int {
{
let old_fd = old_fd as FileDesc; let old_fd = old_fd as FileDesc;
match fs::do_dup(old_fd) { match fs::do_dup(old_fd) {
Ok(new_fd) => { Ok(new_fd) => new_fd as c_int,
new_fd as c_int Err(e) => e.errno.as_retval(),
}
Err(e) => {
e.errno.as_retval()
}
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_dup2(old_fd: c_int, new_fd: c_int) pub extern "C" fn occlum_dup2(old_fd: c_int, new_fd: c_int) -> c_int {
-> c_int
{
let old_fd = old_fd as FileDesc; let old_fd = old_fd as FileDesc;
let new_fd = new_fd as FileDesc; let new_fd = new_fd as FileDesc;
match fs::do_dup2(old_fd, new_fd) { match fs::do_dup2(old_fd, new_fd) {
Ok(new_fd) => { Ok(new_fd) => new_fd as c_int,
new_fd as c_int Err(e) => e.errno.as_retval(),
}
Err(e) => {
e.errno.as_retval()
}
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_dup3(old_fd: c_int, new_fd: c_int, flags: c_int) pub extern "C" fn occlum_dup3(old_fd: c_int, new_fd: c_int, flags: c_int) -> c_int {
-> c_int
{
let old_fd = old_fd as FileDesc; let old_fd = old_fd as FileDesc;
let new_fd = new_fd as FileDesc; let new_fd = new_fd as FileDesc;
let flags = flags as u32; let flags = flags as u32;
match fs::do_dup3(old_fd, new_fd, flags) { match fs::do_dup3(old_fd, new_fd, flags) {
Ok(new_fd) => { Ok(new_fd) => new_fd as c_int,
new_fd as c_int Err(e) => e.errno.as_retval(),
}
Err(e) => {
e.errno.as_retval()
}
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_sync() -> c_int pub extern "C" fn occlum_sync() -> c_int {
{
match fs::do_sync() { match fs::do_sync() {
Ok(()) => { Ok(()) => 0 as c_int,
0 as c_int Err(e) => e.errno.as_retval(),
}
Err(e) => {
e.errno.as_retval()
}
} }
} }
// TODO: handle tz: timezone_t // TODO: handle tz: timezone_t
#[no_mangle] #[no_mangle]
pub extern "C" fn occlum_gettimeofday(tv: *mut timeval_t) -> c_int pub extern "C" fn occlum_gettimeofday(tv: *mut timeval_t) -> c_int {
{
match do_gettimeofday(tv) { match do_gettimeofday(tv) {
Ok(()) => { Ok(()) => 0,
0 Err(e) => e.errno.as_retval(),
}
Err(e) => {
e.errno.as_retval()
}
} }
} }

@ -14,14 +14,13 @@ pub struct timeval_t {
} }
pub fn do_gettimeofday() -> timeval_t { pub fn do_gettimeofday() -> timeval_t {
let mut tv : timeval_t = Default::default(); let mut tv: timeval_t = Default::default();
unsafe { unsafe {
ocall_gettimeofday(&mut tv.sec as *mut time_t, ocall_gettimeofday(&mut tv.sec as *mut time_t, &mut tv.usec as *mut suseconds_t);
&mut tv.usec as *mut suseconds_t);
} }
tv tv
} }
extern { extern "C" {
fn ocall_gettimeofday(sec: *mut time_t, usec: *mut suseconds_t) -> sgx_status_t; fn ocall_gettimeofday(sec: *mut time_t, usec: *mut suseconds_t) -> sgx_status_t;
} }

@ -1,6 +1,6 @@
use super::*; use super::*;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::{ptr}; use std::ptr;
/// Memory utilities that deals with primitive types passed from user process /// Memory utilities that deals with primitive types passed from user process
/// running inside enclave /// running inside enclave
@ -28,9 +28,7 @@ pub mod from_user {
} }
/// Clone a C-string from the user process safely /// Clone a C-string from the user process safely
pub fn clone_cstring_safely(out_ptr: *const c_char) pub fn clone_cstring_safely(out_ptr: *const c_char) -> Result<CString, Error> {
-> Result<CString, Error>
{
check_ptr(out_ptr)?; check_ptr(out_ptr)?;
// TODO: using from_ptr directly is not safe // TODO: using from_ptr directly is not safe
let cstr = unsafe { CStr::from_ptr(out_ptr) }; let cstr = unsafe { CStr::from_ptr(out_ptr) };
@ -41,18 +39,20 @@ pub mod from_user {
/// Clone a C-string array (const char*[]) from the user process safely /// Clone a C-string array (const char*[]) from the user process safely
/// ///
/// This array must be ended with a NULL pointer. /// This array must be ended with a NULL pointer.
pub fn clone_cstrings_safely(user_ptr: *const *const c_char) pub fn clone_cstrings_safely(user_ptr: *const *const c_char) -> Result<Vec<CString>, Error> {
-> Result<Vec<CString>, Error>
{
let mut cstrings = Vec::new(); let mut cstrings = Vec::new();
if user_ptr == ptr::null() { return Ok(cstrings); } if user_ptr == ptr::null() {
return Ok(cstrings);
}
let mut user_ptr = user_ptr; let mut user_ptr = user_ptr;
loop { loop {
check_ptr(user_ptr); check_ptr(user_ptr);
let cstr_ptr = { let cstr_ptr = {
let cstr_ptr = unsafe { *user_ptr }; let cstr_ptr = unsafe { *user_ptr };
if cstr_ptr == ptr::null() { break; } if cstr_ptr == ptr::null() {
break;
}
check_ptr(cstr_ptr); check_ptr(cstr_ptr);
cstr_ptr cstr_ptr
}; };
@ -80,9 +80,7 @@ pub mod from_untrusted {
} }
/// Clone a C-string from outside the enclave /// Clone a C-string from outside the enclave
pub fn clone_cstring_safely(out_ptr: *const c_char) pub fn clone_cstring_safely(out_ptr: *const c_char) -> Result<CString, Error> {
-> Result<CString, Error>
{
check_ptr(out_ptr)?; check_ptr(out_ptr)?;
// TODO: using from_ptr directly is not safe // TODO: using from_ptr directly is not safe
let cstr = unsafe { CStr::from_ptr(out_ptr) }; let cstr = unsafe { CStr::from_ptr(out_ptr) };
@ -93,18 +91,20 @@ pub mod from_untrusted {
/// Clone a C-string array (const char*[]) from outside the enclave /// Clone a C-string array (const char*[]) from outside the enclave
/// ///
/// This array must be ended with a NULL pointer. /// This array must be ended with a NULL pointer.
pub fn clone_cstrings_safely(out_ptr: *const *const c_char) pub fn clone_cstrings_safely(out_ptr: *const *const c_char) -> Result<Vec<CString>, Error> {
-> Result<Vec<CString>, Error>
{
let mut cstrings = Vec::new(); let mut cstrings = Vec::new();
if out_ptr == ptr::null() { return Ok(cstrings); } if out_ptr == ptr::null() {
return Ok(cstrings);
}
let mut out_ptr = out_ptr; let mut out_ptr = out_ptr;
loop { loop {
check_ptr(out_ptr); check_ptr(out_ptr);
let cstr_ptr = { let cstr_ptr = {
let cstr_ptr = unsafe { *out_ptr }; let cstr_ptr = unsafe { *out_ptr };
if cstr_ptr == ptr::null() { break; } if cstr_ptr == ptr::null() {
break;
}
check_ptr(cstr_ptr); check_ptr(cstr_ptr);
cstr_ptr cstr_ptr
}; };
@ -116,4 +116,3 @@ pub mod from_untrusted {
Ok(cstrings) Ok(cstrings)
} }
} }

@ -1,5 +1,5 @@
use super::*; use super::*;
pub mod mem_util;
pub mod mpx_util; pub mod mpx_util;
pub mod ring_buf; pub mod ring_buf;
pub mod mem_util;

@ -1,9 +1,9 @@
use super::*; use super::*;
pub fn mpx_enable() -> Result<(), Error> { pub fn mpx_enable() -> Result<(), Error> {
match unsafe { __mpx_enable () } { match unsafe { __mpx_enable() } {
0 => { Ok(()) } 0 => Ok(()),
_ => { errno!(EPERM, "MPX cannot be enabled") } _ => errno!(EPERM, "MPX cannot be enabled"),
} }
} }
@ -47,8 +47,7 @@ pub fn mpx_bndcu(bndreg: MpxReg, addr: usize) {
} }
} }
extern "C" {
extern {
// See mpx_util.h // See mpx_util.h
fn __mpx_enable() -> i32; fn __mpx_enable() -> i32;
fn __mpx_bndmk0(base: usize, size: usize); fn __mpx_bndmk0(base: usize, size: usize);

@ -1,8 +1,8 @@
use super::{*}; use super::*;
use std::cmp::{max, min};
use std::ptr;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering};
use std::cmp::{min, max};
use std::{ptr};
#[derive(Debug)] #[derive(Debug)]
pub struct RingBuf { pub struct RingBuf {
@ -13,9 +13,14 @@ pub struct RingBuf {
impl RingBuf { impl RingBuf {
pub fn new(capacity: usize) -> RingBuf { pub fn new(capacity: usize) -> RingBuf {
let inner = Arc::new(RingBufInner::new(capacity)); let inner = Arc::new(RingBufInner::new(capacity));
let reader = RingBufReader { inner: inner.clone() }; let reader = RingBufReader {
inner: inner.clone(),
};
let writer = RingBufWriter { inner: inner }; let writer = RingBufWriter { inner: inner };
RingBuf { reader: reader, writer: writer } RingBuf {
reader: reader,
writer: writer,
}
} }
} }
@ -108,7 +113,6 @@ impl Drop for RingBufInner {
} }
} }
impl RingBufReader { impl RingBufReader {
pub fn read(&self, buf: &mut [u8]) -> Result<usize, Error> { pub fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
let mut tail = self.inner.get_tail(); let mut tail = self.inner.get_tail();
@ -123,7 +127,9 @@ impl RingBufReader {
} else { } else {
self.inner.capacity - tail self.inner.capacity - tail
}; };
if may_read_nbytes == 0 { break; } if may_read_nbytes == 0 {
break;
}
min(may_read_nbytes, buf_remain) min(may_read_nbytes, buf_remain)
}; };
@ -150,7 +156,6 @@ impl Drop for RingBufReader {
} }
} }
impl RingBufWriter { impl RingBufWriter {
pub fn write(&self, buf: &[u8]) -> Result<usize, Error> { pub fn write(&self, buf: &[u8]) -> Result<usize, Error> {
if self.inner.is_closed() { if self.inner.is_closed() {
@ -169,7 +174,9 @@ impl RingBufWriter {
} else { } else {
tail - head - 1 tail - head - 1
}; };
if may_write_nbytes == 0 { break; } if may_write_nbytes == 0 {
break;
}
min(may_write_nbytes, buf_remain) min(may_write_nbytes, buf_remain)
}; };

@ -1,25 +1,23 @@
use prelude::*;
use std::{fmt};
use fs::{off_t, FileDesc}; use fs::{off_t, FileDesc};
use process::{Process, ProcessRef, get_current}; use prelude::*;
use process::{get_current, Process, ProcessRef};
use std::fmt;
// TODO: Rename VMSpace to VMUniverse // TODO: Rename VMSpace to VMUniverse
#[macro_use] #[macro_use]
mod vm_range; mod vm_range;
mod vm_space;
mod vm_domain;
mod vm_area;
mod process_vm; mod process_vm;
mod vm_area;
mod vm_domain;
mod vm_space;
pub use self::process_vm::ProcessVM;
pub use self::vm_range::{VMRange, VMRangeTrait}; pub use self::vm_range::{VMRange, VMRangeTrait};
pub use self::process_vm::{ProcessVM};
// TODO: separate proc and flags // TODO: separate proc and flags
// TODO: accept fd and offset // TODO: accept fd and offset
pub fn do_mmap(addr: usize, size: usize, flags: VMAreaFlags) pub fn do_mmap(addr: usize, size: usize, flags: VMAreaFlags) -> Result<usize, Error> {
-> Result<usize, Error>
{
let current_ref = get_current(); let current_ref = get_current();
let mut current_process = current_ref.lock().unwrap(); let mut current_process = current_ref.lock().unwrap();
let current_vm = current_process.get_vm_mut(); let current_vm = current_process.get_vm_mut();
@ -34,9 +32,11 @@ pub fn do_munmap(addr: usize, size: usize) -> Result<(), Error> {
} }
// TODO: accept flags // TODO: accept flags
pub fn do_mremap(old_addr: usize, old_size: usize, options: &VMResizeOptions) pub fn do_mremap(
-> Result<usize, Error> old_addr: usize,
{ old_size: usize,
options: &VMResizeOptions,
) -> Result<usize, Error> {
let current_ref = get_current(); let current_ref = get_current();
let mut current_process = current_ref.lock().unwrap(); let mut current_process = current_ref.lock().unwrap();
let current_vm = current_process.get_vm_mut(); let current_vm = current_process.get_vm_mut();
@ -50,8 +50,7 @@ pub fn do_brk(addr: usize) -> Result<usize, Error> {
current_vm.brk(addr) current_vm.brk(addr)
} }
pub const PAGE_SIZE: usize = 4096;
pub const PAGE_SIZE : usize = 4096;
#[derive(Debug)] #[derive(Debug)]
pub struct VMSpace { pub struct VMSpace {
@ -70,7 +69,6 @@ pub struct VMArea {
flags: VMAreaFlags, flags: VMAreaFlags,
} }
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub enum VMGuardAreaType { pub enum VMGuardAreaType {
None, None,
@ -78,7 +76,6 @@ pub enum VMGuardAreaType {
Dynamic { size: usize }, Dynamic { size: usize },
} }
#[derive(Copy, Clone, Debug, Default, PartialEq)] #[derive(Copy, Clone, Debug, Default, PartialEq)]
pub struct VMAreaFlags(pub u32); pub struct VMAreaFlags(pub u32);
@ -100,8 +97,6 @@ impl VMAreaFlags {
} }
} }
#[derive(Clone, Copy, PartialEq)] #[derive(Clone, Copy, PartialEq)]
pub struct VMAllocOptions { pub struct VMAllocOptions {
size: usize, size: usize,
@ -114,7 +109,10 @@ impl VMAllocOptions {
if size % PAGE_SIZE != 0 { if size % PAGE_SIZE != 0 {
return Err(Error::new(Errno::EINVAL, "Size is not page-aligned")); return Err(Error::new(Errno::EINVAL, "Size is not page-aligned"));
} }
Ok(VMAllocOptions { size, ..Default::default() }) Ok(VMAllocOptions {
size,
..Default::default()
})
} }
pub fn addr(&mut self, addr: VMAddrOption) -> Result<&mut Self, Error> { pub fn addr(&mut self, addr: VMAddrOption) -> Result<&mut Self, Error> {
@ -133,13 +131,16 @@ impl VMAllocOptions {
impl fmt::Debug for VMAllocOptions { impl fmt::Debug for VMAllocOptions {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "VMAllocOptions {{ size: 0x{:X?}, addr: {:?}, growth: {:?} }}", write!(
self.size, self.addr, self.growth) f,
"VMAllocOptions {{ size: 0x{:X?}, addr: {:?}, growth: {:?} }}",
self.size, self.addr, self.growth
)
} }
} }
impl Default for VMAllocOptions { impl Default for VMAllocOptions {
fn default() -> VMAllocOptions{ fn default() -> VMAllocOptions {
VMAllocOptions { VMAllocOptions {
size: 0, size: 0,
addr: VMAddrOption::Any, addr: VMAddrOption::Any,
@ -148,7 +149,6 @@ impl Default for VMAllocOptions {
} }
} }
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub enum VMAddrOption { pub enum VMAddrOption {
Any, // Free to choose any address Any, // Free to choose any address
@ -167,15 +167,14 @@ impl VMAddrOption {
pub fn get_addr(&self) -> usize { pub fn get_addr(&self) -> usize {
match self { match self {
VMAddrOption::Hint(addr) | VMAddrOption::Hint(addr) | VMAddrOption::Fixed(addr) | VMAddrOption::Beyond(addr) => {
VMAddrOption::Fixed(addr) | *addr
VMAddrOption::Beyond(addr) => *addr, }
VMAddrOption::Any => panic!("No address given"), VMAddrOption::Any => panic!("No address given"),
} }
} }
} }
/// How VMRange may grow: /// How VMRange may grow:
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub enum VMGrowthType { pub enum VMGrowthType {
@ -184,7 +183,6 @@ pub enum VMGrowthType {
Fixed, Fixed,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct VMResizeOptions { pub struct VMResizeOptions {
new_size: usize, new_size: usize,
@ -196,7 +194,10 @@ impl VMResizeOptions {
if new_size % PAGE_SIZE != 0 { if new_size % PAGE_SIZE != 0 {
return Err(Error::new(Errno::EINVAL, "Size is not page-aligned")); return Err(Error::new(Errno::EINVAL, "Size is not page-aligned"));
} }
Ok(VMResizeOptions { new_size, ..Default::default() }) Ok(VMResizeOptions {
new_size,
..Default::default()
})
} }
pub fn addr(&mut self, new_addr: VMAddrOption) -> &mut Self { pub fn addr(&mut self, new_addr: VMAddrOption) -> &mut Self {
@ -206,7 +207,7 @@ impl VMResizeOptions {
} }
impl Default for VMResizeOptions { impl Default for VMResizeOptions {
fn default() -> VMResizeOptions{ fn default() -> VMResizeOptions {
VMResizeOptions { VMResizeOptions {
new_size: 0, new_size: 0,
new_addr: None, new_addr: None,

@ -5,8 +5,8 @@ use super::*;
lazy_static! { lazy_static! {
static ref DATA_SPACE: SgxMutex<VMSpace> = { static ref DATA_SPACE: SgxMutex<VMSpace> = {
let (addr, size) = { let (addr, size) = {
let mut addr : usize = 0; let mut addr: usize = 0;
let mut size : usize = 0; let mut size: usize = 0;
unsafe { vm_get_prealloced_data_space(&mut addr, &mut size) }; unsafe { vm_get_prealloced_data_space(&mut addr, &mut size) };
(addr, size) (addr, size)
}; };
@ -20,7 +20,7 @@ lazy_static! {
}; };
} }
extern { extern "C" {
pub fn vm_get_prealloced_data_space(addr: &mut usize, size: &mut usize); pub fn vm_get_prealloced_data_space(addr: &mut usize, size: &mut usize);
} }
@ -37,18 +37,23 @@ pub struct ProcessVM {
} }
impl ProcessVM { impl ProcessVM {
pub fn new(code_size: usize, data_size: usize, pub fn new(
heap_size: usize, stack_size: usize, code_size: usize,
mmap_size: usize) data_size: usize,
-> Result<ProcessVM, Error> heap_size: usize,
{ stack_size: usize,
mmap_size: usize,
) -> Result<ProcessVM, Error> {
let data_domain_size = code_size + data_size + heap_size + stack_size + mmap_size; let data_domain_size = code_size + data_size + heap_size + stack_size + mmap_size;
let mut data_domain = DATA_SPACE.lock().unwrap(). let mut data_domain = DATA_SPACE.lock().unwrap().alloc_domain(data_domain_size)?;
alloc_domain(data_domain_size)?;
let (code_vma, data_vma, heap_vma, stack_vma) = let (code_vma, data_vma, heap_vma, stack_vma) = ProcessVM::alloc_vmas(
ProcessVM::alloc_vmas(&mut data_domain, code_size, data_size, &mut data_domain,
heap_size, stack_size)?; code_size,
data_size,
heap_size,
stack_size,
)?;
// Initial value of the program break // Initial value of the program break
let brk = heap_vma.get_start(); let brk = heap_vma.get_start();
// No mmapped vmas initially // No mmapped vmas initially
@ -66,14 +71,17 @@ impl ProcessVM {
Ok(vm) Ok(vm)
} }
fn alloc_vmas(data_domain: &mut VMDomain, fn alloc_vmas(
code_size: usize, data_size: usize, data_domain: &mut VMDomain,
heap_size: usize, stack_size: usize) code_size: usize,
-> Result<(VMArea, VMArea, VMArea, VMArea), Error> data_size: usize,
{ heap_size: usize,
stack_size: usize,
) -> Result<(VMArea, VMArea, VMArea, VMArea), Error> {
let mut addr = data_domain.get_start(); let mut addr = data_domain.get_start();
let mut alloc_vma_continuously = |addr: &mut usize, size, flags, growth| -> Result<_, Error> { let mut alloc_vma_continuously =
|addr: &mut usize, size, flags, growth| -> Result<_, Error> {
let mut options = VMAllocOptions::new(size)?; let mut options = VMAllocOptions::new(size)?;
options.addr(VMAddrOption::Fixed(*addr))?.growth(growth)?; options.addr(VMAddrOption::Fixed(*addr))?.growth(growth)?;
let new_vma = data_domain.alloc_area(&options, flags)?; let new_vma = data_domain.alloc_area(&options, flags)?;
@ -84,21 +92,14 @@ impl ProcessVM {
let rx_flags = VMAreaFlags(VM_AREA_FLAG_R | VM_AREA_FLAG_X); let rx_flags = VMAreaFlags(VM_AREA_FLAG_R | VM_AREA_FLAG_X);
let rw_flags = VMAreaFlags(VM_AREA_FLAG_R | VM_AREA_FLAG_W); let rw_flags = VMAreaFlags(VM_AREA_FLAG_R | VM_AREA_FLAG_W);
let code_vma = alloc_vma_continuously(&mut addr, let code_vma = alloc_vma_continuously(&mut addr, code_size, rx_flags, VMGrowthType::Fixed)?;
code_size, rx_flags, let data_vma = alloc_vma_continuously(&mut addr, data_size, rw_flags, VMGrowthType::Fixed)?;
VMGrowthType::Fixed)?; let heap_vma = alloc_vma_continuously(&mut addr, 0, rw_flags, VMGrowthType::Upward)?;
let data_vma = alloc_vma_continuously(&mut addr,
data_size, rw_flags,
VMGrowthType::Fixed)?;
let heap_vma = alloc_vma_continuously(&mut addr,
0, rw_flags,
VMGrowthType::Upward)?;
// Preserve the space for heap // Preserve the space for heap
addr += heap_size; addr += heap_size;
// After the heap is the stack // After the heap is the stack
let stack_vma = alloc_vma_continuously(&mut addr, let stack_vma =
stack_size, rw_flags, alloc_vma_continuously(&mut addr, stack_size, rw_flags, VMGrowthType::Downward)?;
VMGrowthType::Downward)?;
Ok((code_vma, data_vma, heap_vma, stack_vma)) Ok((code_vma, data_vma, heap_vma, stack_vma))
} }
@ -143,25 +144,21 @@ impl ProcessVM {
} }
// TODO: support overriding the mmaping of already mmaped range // TODO: support overriding the mmaping of already mmaped range
pub fn mmap(&mut self, addr: usize, size: usize, flags: VMAreaFlags) pub fn mmap(&mut self, addr: usize, size: usize, flags: VMAreaFlags) -> Result<usize, Error> {
-> Result<usize, Error>
{
let alloc_options = { let alloc_options = {
let mmap_start_addr = self.get_mmap_start(); let mmap_start_addr = self.get_mmap_start();
let mut alloc_options = VMAllocOptions::new(size)?; let mut alloc_options = VMAllocOptions::new(size)?;
alloc_options.addr( alloc_options
if addr == 0 { .addr(if addr == 0 {
VMAddrOption::Beyond(mmap_start_addr) VMAddrOption::Beyond(mmap_start_addr)
} } else {
else {
if addr < mmap_start_addr { if addr < mmap_start_addr {
return Err(Error::new(Errno::EINVAL, return Err(Error::new(Errno::EINVAL, "Beyond valid memory range"));
"Beyond valid memory range"));
} }
VMAddrOption::Fixed(addr) VMAddrOption::Fixed(addr)
} })?
)?.growth(VMGrowthType::Upward)?; .growth(VMGrowthType::Upward)?;
alloc_options alloc_options
}; };
// TODO: when failed, try to resize data_domain // TODO: when failed, try to resize data_domain
@ -171,18 +168,19 @@ impl ProcessVM {
Ok(addr) Ok(addr)
} }
pub fn munmap(&mut self, addr: usize, size: usize) pub fn munmap(&mut self, addr: usize, size: usize) -> Result<(), Error> {
-> Result<(), Error>
{
// TODO: handle the case when the given range [addr, addr + size) // TODO: handle the case when the given range [addr, addr + size)
// does not match exactly with any vma. For example, when this range // does not match exactly with any vma. For example, when this range
// cover multiple ranges or cover some range partially. // cover multiple ranges or cover some range partially.
let mmap_vma_i = { let mmap_vma_i = {
let mmap_vma_i = self.get_mmap_vmas().iter().position(|vma| { let mmap_vma_i = self
vma.get_start() == addr && vma.get_end() == addr + size .get_mmap_vmas()
}); .iter()
if mmap_vma_i.is_none() { return Ok(()) } .position(|vma| vma.get_start() == addr && vma.get_end() == addr + size);
if mmap_vma_i.is_none() {
return Ok(());
}
mmap_vma_i.unwrap() mmap_vma_i.unwrap()
}; };
@ -191,10 +189,12 @@ impl ProcessVM {
Ok(()) Ok(())
} }
pub fn mremap(&mut self, old_addr: usize, old_size: usize, pub fn mremap(
options: &VMResizeOptions) &mut self,
-> Result<usize, Error> old_addr: usize,
{ old_size: usize,
options: &VMResizeOptions,
) -> Result<usize, Error> {
// TODO: Implement this! // TODO: Implement this!
Err(Error::new(Errno::EINVAL, "Not implemented")) Err(Error::new(Errno::EINVAL, "Not implemented"))
} }
@ -202,11 +202,9 @@ impl ProcessVM {
pub fn brk(&mut self, new_brk: usize) -> Result<usize, Error> { pub fn brk(&mut self, new_brk: usize) -> Result<usize, Error> {
if new_brk == 0 { if new_brk == 0 {
return Ok(self.get_brk()); return Ok(self.get_brk());
} } else if new_brk < self.heap_vma.get_start() {
else if new_brk < self.heap_vma.get_start() {
return errno!(EINVAL, "New brk address is too low"); return errno!(EINVAL, "New brk address is too low");
} } else if new_brk <= self.heap_vma.get_end() {
else if new_brk <= self.heap_vma.get_end() {
self.brk = new_brk; self.brk = new_brk;
return Ok(new_brk); return Ok(new_brk);
} }
@ -219,12 +217,12 @@ impl ProcessVM {
options.addr(VMAddrOption::Fixed(brk_start)); options.addr(VMAddrOption::Fixed(brk_start));
options options
}; };
self.data_domain.resize_area(&mut self.heap_vma, &resize_options)?; self.data_domain
.resize_area(&mut self.heap_vma, &resize_options)?;
Ok(new_brk) Ok(new_brk)
} }
} }
impl Drop for ProcessVM { impl Drop for ProcessVM {
fn drop(&mut self) { fn drop(&mut self) {
let data_domain = &mut self.data_domain; let data_domain = &mut self.data_domain;

@ -1,7 +1,11 @@
use super::*; use super::*;
impl VMDomain { impl VMDomain {
pub fn alloc_area(&mut self, options: &VMAllocOptions, flags: VMAreaFlags) -> Result<VMArea, Error> { pub fn alloc_area(
&mut self,
options: &VMAllocOptions,
flags: VMAreaFlags,
) -> Result<VMArea, Error> {
let new_range = self.range.alloc_subrange(options)?; let new_range = self.range.alloc_subrange(options)?;
// Init the memory area with all zeros // Init the memory area with all zeros
@ -11,22 +15,27 @@ impl VMDomain {
memset(mem_ptr, 0 as c_int, mem_size); memset(mem_ptr, 0 as c_int, mem_size);
} }
Ok(VMArea { range: new_range, flags: flags }) Ok(VMArea {
range: new_range,
flags: flags,
})
} }
pub fn dealloc_area(&mut self, area: &mut VMArea) { pub fn dealloc_area(&mut self, area: &mut VMArea) {
self.range.dealloc_subrange(&mut area.range) self.range.dealloc_subrange(&mut area.range)
} }
pub fn resize_area(&mut self, area: &mut VMArea, options: &VMResizeOptions) pub fn resize_area(
-> Result<(), Error> &mut self,
{ area: &mut VMArea,
options: &VMResizeOptions,
) -> Result<(), Error> {
// TODO: init memory with zeros when expanding! // TODO: init memory with zeros when expanding!
self.range.resize_subrange(&mut area.range, options) self.range.resize_subrange(&mut area.range, options)
} }
} }
#[link(name = "sgx_tstdc")] #[link(name = "sgx_tstdc")]
extern { extern "C" {
pub fn memset(p: *mut c_void, c: c_int, n: size_t) -> *mut c_void; pub fn memset(p: *mut c_void, c: c_int, n: size_t) -> *mut c_void;
} }

@ -1,5 +1,5 @@
use super::*; use super::*;
use std::{fmt}; use std::fmt;
pub trait VMRangeTrait { pub trait VMRangeTrait {
fn get_start(&self) -> usize; fn get_start(&self) -> usize;
@ -32,7 +32,7 @@ macro_rules! impl_vmrange_trait_for {
self.$field.contains_obj(ptr, size) self.$field.contains_obj(ptr, size)
} }
} }
} };
} }
impl_vmrange_trait_for!(VMRange, inner); impl_vmrange_trait_for!(VMRange, inner);
@ -40,7 +40,6 @@ impl_vmrange_trait_for!(VMSpace, range);
impl_vmrange_trait_for!(VMDomain, range); impl_vmrange_trait_for!(VMDomain, range);
impl_vmrange_trait_for!(VMArea, range); impl_vmrange_trait_for!(VMArea, range);
#[derive(Debug)] #[derive(Debug)]
pub struct VMRange { pub struct VMRange {
inner: VMRangeInner, inner: VMRangeInner,
@ -74,7 +73,7 @@ impl VMRange {
// Find a free space for allocating a VMRange // Find a free space for allocating a VMRange
let free_space = { let free_space = {
// Look for the minimal big-enough free space // Look for the minimal big-enough free space
let mut min_big_enough_free_space : Option<FreeSpace> = None; let mut min_big_enough_free_space: Option<FreeSpace> = None;
let sub_ranges = self.get_subranges(); let sub_ranges = self.get_subranges();
for (idx, range_pair) in sub_ranges.windows(2).enumerate() { for (idx, range_pair) in sub_ranges.windows(2).enumerate() {
let pre_range = &range_pair[0]; let pre_range = &range_pair[0];
@ -85,18 +84,24 @@ impl VMRange {
let free_range_end = next_range.get_start(); let free_range_end = next_range.get_start();
let free_range_size = free_range_end - free_range_start; let free_range_size = free_range_end - free_range_start;
if free_range_size < size { continue } if free_range_size < size {
continue;
}
free_range_start..free_range_end free_range_start..free_range_end
}; };
match addr { match addr {
VMAddrOption::Hint(addr) | VMAddrOption::Fixed(addr) => { VMAddrOption::Hint(addr) | VMAddrOption::Fixed(addr) => {
if !free_range.contains(&addr) { continue } if !free_range.contains(&addr) {
continue;
}
free_range.start = addr; free_range.start = addr;
} }
VMAddrOption::Beyond(addr) => { VMAddrOption::Beyond(addr) => {
if free_range.start < addr { continue } if free_range.start < addr {
continue;
}
} }
_ => {} _ => {}
} }
@ -105,20 +110,18 @@ impl VMRange {
index_in_subranges: idx + 1, index_in_subranges: idx + 1,
start: free_range.start, start: free_range.start,
end: free_range.end, end: free_range.end,
may_neighbor_grow: (pre_range.growth == VMGrowthType::Upward, may_neighbor_grow: (
next_range.growth == VMGrowthType::Downward), pre_range.growth == VMGrowthType::Upward,
next_range.growth == VMGrowthType::Downward,
),
}); });
if min_big_enough_free_space == None || if min_big_enough_free_space == None || free_space < min_big_enough_free_space {
free_space < min_big_enough_free_space
{
min_big_enough_free_space = free_space; min_big_enough_free_space = free_space;
match addr { match addr {
VMAddrOption::Hint(addr) | VMAddrOption::Fixed(addr) => { VMAddrOption::Hint(addr) | VMAddrOption::Fixed(addr) => break,
break _ => {}
}
_ => {},
} }
} }
} }
@ -133,18 +136,14 @@ impl VMRange {
let (new_subrange_start, new_subrange_end) = match addr { let (new_subrange_start, new_subrange_end) = match addr {
VMAddrOption::Any | VMAddrOption::Beyond(_) => { VMAddrOption::Any | VMAddrOption::Beyond(_) => {
let should_no_gap_to_pre_domain = let should_no_gap_to_pre_domain =
free_space.may_neighbor_grow.0 == false && free_space.may_neighbor_grow.0 == false && growth != VMGrowthType::Downward;
growth != VMGrowthType::Downward;
let should_no_gap_to_next_domain = let should_no_gap_to_next_domain =
free_space.may_neighbor_grow.1 == false && free_space.may_neighbor_grow.1 == false && growth != VMGrowthType::Upward;
growth != VMGrowthType::Upward;
let domain_start = if should_no_gap_to_pre_domain { let domain_start = if should_no_gap_to_pre_domain {
free_space.start free_space.start
} } else if should_no_gap_to_next_domain {
else if should_no_gap_to_next_domain {
free_space.end - size free_space.end - size
} } else {
else {
// We want to leave some space at both ends in case // We want to leave some space at both ends in case
// this sub-range or neighbor sub-range needs to grow later. // this sub-range or neighbor sub-range needs to grow later.
// As a simple heuristic, we put this sub-range near the // As a simple heuristic, we put this sub-range near the
@ -153,18 +152,15 @@ impl VMRange {
}; };
(domain_start, domain_start + size) (domain_start, domain_start + size)
} }
VMAddrOption::Fixed(addr) => { VMAddrOption::Fixed(addr) => (addr, addr + size),
(addr, addr + size)
}
VMAddrOption::Hint(addr) => { VMAddrOption::Hint(addr) => {
return errno!(EINVAL, "Not implemented"); return errno!(EINVAL, "Not implemented");
} }
}; };
let new_subrange_inner = VMRangeInner::new(new_subrange_start, let new_subrange_inner = VMRangeInner::new(new_subrange_start, new_subrange_end, growth);
new_subrange_end, growth); self.get_subranges_mut()
self.get_subranges_mut().insert(free_space.index_in_subranges, .insert(free_space.index_in_subranges, new_subrange_inner);
new_subrange_inner);
// Although there are two copies of the newly created VMRangeInner obj, // Although there are two copies of the newly created VMRangeInner obj,
// we can keep them in sync as all mutation on VMRange object must // we can keep them in sync as all mutation on VMRange object must
// be carried out through dealloc_subrange() and resize_subrange() that // be carried out through dealloc_subrange() and resize_subrange() that
@ -189,7 +185,8 @@ impl VMRange {
self.get_subranges_mut().remove(domain_i); self.get_subranges_mut().remove(domain_i);
// When all sub-ranges are removed, remove the sub-range array // When all sub-ranges are removed, remove the sub-range array
if self.get_subranges().len() == 2 { // two sentinel sub-ranges excluded if self.get_subranges().len() == 2 {
// two sentinel sub-ranges excluded
self.sub_ranges = None; self.sub_ranges = None;
} }
@ -197,8 +194,11 @@ impl VMRange {
subrange.mark_as_dealloced(); subrange.mark_as_dealloced();
} }
pub fn resize_subrange(&mut self, subrange: &mut VMRange, options: &VMResizeOptions) pub fn resize_subrange(
-> Result<(), Error> { &mut self,
subrange: &mut VMRange,
options: &VMResizeOptions,
) -> Result<(), Error> {
self.ensure_subrange_is_a_child(subrange); self.ensure_subrange_is_a_child(subrange);
// Get valid parameters from options // Get valid parameters from options
@ -243,7 +243,10 @@ impl VMRange {
fn position_subrange(&self, subrange: &VMRange) -> usize { fn position_subrange(&self, subrange: &VMRange) -> usize {
let sub_ranges = self.get_subranges(); let sub_ranges = self.get_subranges();
sub_ranges.iter().position(|d| d == &subrange.inner).unwrap() sub_ranges
.iter()
.position(|d| d == &subrange.inner)
.unwrap()
} }
fn get_subranges(&self) -> &Vec<VMRangeInner> { fn get_subranges(&self) -> &Vec<VMRangeInner> {
@ -258,9 +261,7 @@ impl VMRange {
self.sub_ranges.is_some() self.sub_ranges.is_some()
} }
fn shrink_subrange_to(&mut self, subrange: &mut VMRange, new_size: usize) fn shrink_subrange_to(&mut self, subrange: &mut VMRange, new_size: usize) -> Result<(), Error> {
-> Result<(), Error>
{
let subrange_i = self.position_subrange(subrange); let subrange_i = self.position_subrange(subrange);
let subranges = self.get_subranges_mut(); let subranges = self.get_subranges_mut();
@ -268,13 +269,10 @@ impl VMRange {
// Can we do shrink? // Can we do shrink?
let min_new_size = match subrange.sub_ranges.as_mut() { let min_new_size = match subrange.sub_ranges.as_mut() {
Some(child_subranges) => { Some(child_subranges) => {
let child_last_subrange = &child_subranges[ let child_last_subrange = &child_subranges[child_subranges.len() - 2];
child_subranges.len() - 2];
child_last_subrange.end - subrange.inner.start child_last_subrange.end - subrange.inner.start
} }
None => { None => 0,
0
}
}; };
if new_size < min_new_size { if new_size < min_new_size {
return errno!(ENOMEM, "Cannot shrink to new size"); return errno!(ENOMEM, "Cannot shrink to new size");
@ -284,17 +282,15 @@ impl VMRange {
subrange.inner.end = new_subrange_end; subrange.inner.end = new_subrange_end;
// Sync state // Sync state
subranges[subrange_i].end = new_subrange_end; subranges[subrange_i].end = new_subrange_end;
} } else {
else { // self.growth == VMGrowthType::Downward // self.growth == VMGrowthType::Downward
// Can we do shrink? // Can we do shrink?
let min_new_size = match subrange.sub_ranges.as_mut() { let min_new_size = match subrange.sub_ranges.as_mut() {
Some(child_subranges) => { Some(child_subranges) => {
let child_first_subrange = &child_subranges[1]; let child_first_subrange = &child_subranges[1];
subrange.inner.end - child_first_subrange.start subrange.inner.end - child_first_subrange.start
} }
None => { None => 0,
0
}
}; };
if new_size < min_new_size { if new_size < min_new_size {
return errno!(ENOMEM, "Cannot shrink to new size"); return errno!(ENOMEM, "Cannot shrink to new size");
@ -308,9 +304,7 @@ impl VMRange {
Ok(()) Ok(())
} }
fn grow_subrange_to(&mut self, subrange: &mut VMRange, new_size: usize) fn grow_subrange_to(&mut self, subrange: &mut VMRange, new_size: usize) -> Result<(), Error> {
-> Result<(), Error>
{
let subrange_i = self.position_subrange(subrange); let subrange_i = self.position_subrange(subrange);
let subranges = self.get_subranges_mut(); let subranges = self.get_subranges_mut();
@ -328,8 +322,8 @@ impl VMRange {
subrange.inner.end = subrange_new_end; subrange.inner.end = subrange_new_end;
// Sync state // Sync state
subranges[subrange_i].end = subrange_new_end; subranges[subrange_i].end = subrange_new_end;
} } else {
else { // self.growth == VMGrowthType::Downward // self.growth == VMGrowthType::Downward
// Can we grow? // Can we grow?
let max_new_size = { let max_new_size = {
let pre_subrange = &subranges[subrange_i - 1]; let pre_subrange = &subranges[subrange_i - 1];
@ -395,7 +389,6 @@ impl Default for VMRange {
} }
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct VMRangeInner { pub struct VMRangeInner {
start: usize, start: usize,
@ -404,8 +397,7 @@ pub struct VMRangeInner {
} }
impl VMRangeInner { impl VMRangeInner {
pub fn new(start: usize, end: usize, growth: VMGrowthType) -> VMRangeInner pub fn new(start: usize, end: usize, growth: VMGrowthType) -> VMRangeInner {
{
VMRangeInner { VMRangeInner {
start: start, start: start,
end: end, end: end,
@ -440,8 +432,14 @@ impl VMRangeTrait for VMRangeInner {
impl fmt::Debug for VMRangeInner { impl fmt::Debug for VMRangeInner {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "VMRangeInner {{ start: 0x{:X?}, end: 0x{:X?}, size: 0x{:X?}, growth: {:?} }}", write!(
self.start, self.end, self.get_size(), self.growth) f,
"VMRangeInner {{ start: 0x{:X?}, end: 0x{:X?}, size: 0x{:X?}, growth: {:?} }}",
self.start,
self.end,
self.get_size(),
self.growth
)
} }
} }
@ -449,14 +447,11 @@ impl PartialOrd for VMRangeInner {
fn partial_cmp(&self, other: &VMRangeInner) -> Option<Ordering> { fn partial_cmp(&self, other: &VMRangeInner) -> Option<Ordering> {
if self.end <= other.start { if self.end <= other.start {
return Some(Ordering::Less); return Some(Ordering::Less);
} } else if self.start >= other.end {
else if self.start >= other.end {
return Some(Ordering::Greater); return Some(Ordering::Greater);
} } else if self.start == other.start && self.end == other.end {
else if self.start == other.start && self.end == other.end {
return Some(Ordering::Equal); return Some(Ordering::Equal);
} } else {
else {
return None; return None;
} }
} }
@ -468,7 +463,6 @@ impl PartialEq for VMRangeInner {
} }
} }
#[derive(Debug)] #[derive(Debug)]
struct FreeSpace { struct FreeSpace {
index_in_subranges: usize, index_in_subranges: usize,
@ -491,8 +485,8 @@ impl FreeSpace {
impl PartialEq for FreeSpace { impl PartialEq for FreeSpace {
fn eq(&self, other: &FreeSpace) -> bool { fn eq(&self, other: &FreeSpace) -> bool {
self.get_size() == other.get_size() && self.get_size() == other.get_size()
self.get_neighbor_pressure() == other.get_neighbor_pressure() && self.get_neighbor_pressure() == other.get_neighbor_pressure()
} }
} }
@ -502,21 +496,17 @@ impl PartialOrd for FreeSpace {
let other_size = other.get_size(); let other_size = other.get_size();
if self_size < other_size { if self_size < other_size {
Some(Ordering::Less) Some(Ordering::Less)
} } else if self_size > other_size {
else if self_size > other_size {
Some(Ordering::Greater) Some(Ordering::Greater)
} } else {
else {
// The less neighbor pressure, the larger the free space // The less neighbor pressure, the larger the free space
let self_neighbor_pressure = self.get_neighbor_pressure(); let self_neighbor_pressure = self.get_neighbor_pressure();
let other_neighbor_pressure = other.get_neighbor_pressure(); let other_neighbor_pressure = other.get_neighbor_pressure();
if self_neighbor_pressure > other_neighbor_pressure { if self_neighbor_pressure > other_neighbor_pressure {
Some(Ordering::Less) Some(Ordering::Less)
} } else if self_neighbor_pressure < other_neighbor_pressure {
else if self_neighbor_pressure < other_neighbor_pressure {
Some(Ordering::Greater) Some(Ordering::Greater)
} } else {
else {
Some(Ordering::Equal) Some(Ordering::Equal)
} }
} }

@ -1,12 +1,12 @@
use super::*; use super::*;
impl VMSpace { impl VMSpace {
pub unsafe fn new(addr: usize, size: usize, guard_type: VMGuardAreaType) pub unsafe fn new(
-> Result<VMSpace, Error> addr: usize,
{ size: usize,
let range = unsafe { guard_type: VMGuardAreaType,
VMRange::new(addr, addr + size, VMGrowthType::Fixed)? ) -> Result<VMSpace, Error> {
}; let range = unsafe { VMRange::new(addr, addr + size, VMGrowthType::Fixed)? };
Ok(VMSpace { range, guard_type }) Ok(VMSpace { range, guard_type })
} }
@ -14,25 +14,19 @@ impl VMSpace {
self.guard_type self.guard_type
} }
pub fn alloc_domain(&mut self, size: usize) pub fn alloc_domain(&mut self, size: usize) -> Result<VMDomain, Error> {
-> Result<VMDomain, Error>
{
let mut options = VMAllocOptions::new(size)?; let mut options = VMAllocOptions::new(size)?;
options.growth(VMGrowthType::Upward)?; options.growth(VMGrowthType::Upward)?;
let new_range = self.range.alloc_subrange(&options)?; let new_range = self.range.alloc_subrange(&options)?;
Ok(VMDomain { Ok(VMDomain { range: new_range })
range: new_range,
})
} }
pub fn dealloc_domain(&mut self, domain: &mut VMDomain) { pub fn dealloc_domain(&mut self, domain: &mut VMDomain) {
self.range.dealloc_subrange(&mut domain.range) self.range.dealloc_subrange(&mut domain.range)
} }
pub fn resize_domain(&mut self, domain: &mut VMDomain, new_size: usize) pub fn resize_domain(&mut self, domain: &mut VMDomain, new_size: usize) -> Result<(), Error> {
-> Result<(), Error>
{
let options = VMResizeOptions::new(new_size)?; let options = VMResizeOptions::new(new_size)?;
self.range.resize_subrange(&mut domain.range, &options) self.range.resize_subrange(&mut domain.range, &options)
} }