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

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

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

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

@ -1,7 +1,7 @@
use super::*;
use prelude::*;
use {std, process};
use std::sgxfs as fs_impl;
use {process, std};
mod file;
mod file_table;
@ -9,7 +9,7 @@ mod pipe;
pub use self::file::{File, FileRef, SgxFile, StdinFile, StdoutFile};
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_WRONLY: u32 = 0x00000001;
@ -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) {
open_options.write(true);
}
else {
} else {
open_options.read(true);
}
open_options.update(true).binary(true);
@ -44,7 +43,8 @@ pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
let mut sgx_file = {
let key: sgx_key_128bit_t = [0 as uint8_t; 16];
// 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
.open_ex(path, &key)
.map_err(|e| (Errno::ENOENT, "Failed to open the SGX-protected file"))?;
Arc::new(SgxMutex::new(sgx_file))
};
@ -52,8 +52,12 @@ pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
let is_readable = (flags & O_WRONLY) == 0;
let is_writable = (flags & O_WRONLY != 0) || (flags & O_RDWR != 0);
let is_append = (flags & O_APPEND != 0);
let file_ref : Arc<Box<File>> = Arc::new(Box::new(
SgxFile::new(sgx_file, is_readable, is_writable, is_append)?));
let file_ref: Arc<Box<File>> = Arc::new(Box::new(SgxFile::new(
sgx_file,
is_readable,
is_writable,
is_append,
)?));
let fd = {
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 close_on_spawn = flags & O_CLOEXEC != 0;
let reader_fd = file_table.put(Arc::new(Box::new(pipe.reader)),
close_on_spawn);
let writer_fd = file_table.put(Arc::new(Box::new(pipe.writer)),
close_on_spawn);
let reader_fd = file_table.put(Arc::new(Box::new(pipe.reader)), close_on_spawn);
let writer_fd = file_table.put(Arc::new(Box::new(pipe.writer)), close_on_spawn);
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> {
unsafe { ocall_sync(); }
unsafe {
ocall_sync();
}
Ok(())
}
extern {
extern "C" {
fn ocall_sync() -> sgx_status_t;
}

@ -1,5 +1,5 @@
use super::*;
use util::ring_buf::{*};
use util::ring_buf::*;
// TODO: Use Waiter and WaitQueue infrastructure to sleep when blocking
@ -20,12 +20,11 @@ impl Pipe {
},
writer: PipeWriter {
inner: SgxMutex::new(ring_buf.writer),
}
},
})
}
}
#[derive(Debug)]
pub struct PipeReader {
inner: SgxMutex<RingBufReader>,
@ -44,7 +43,9 @@ impl File for PipeReader {
match ringbuf.read(buf) {
Ok(this_len) => {
total_bytes += this_len;
if this_len < buf.len() { break; }
if this_len < buf.len() {
break;
}
}
Err(e) => {
match total_bytes {
@ -60,11 +61,17 @@ impl File for PipeReader {
}
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> {
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> {
@ -75,7 +82,6 @@ impl File for PipeReader {
unsafe impl Send for PipeReader {}
unsafe impl Sync for PipeReader {}
#[derive(Debug)]
pub struct PipeWriter {
inner: SgxMutex<RingBufWriter>,
@ -94,7 +100,9 @@ impl File for PipeWriter {
match ringbuf.write(buf) {
Ok(this_len) => {
total_bytes += this_len;
if this_len < buf.len() { break; }
if this_len < buf.len() {
break;
}
}
Err(e) => {
match total_bytes {

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

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

@ -1,4 +1,4 @@
use super::{*};
use super::*;
// TODO: make sure Processes are released eventually
@ -11,7 +11,6 @@ pub enum ChildProcessFilter {
unsafe impl Send for ChildProcessFilter {}
pub fn do_exit(exit_status: i32) {
let current_ref = get_current();
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)
};
// 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();
wait_queue.del_and_wake_one_waiter(|waiter_data| -> Option<pid_t> {
match waiter_data {
ChildProcessFilter::WithAnyPID => {
},
ChildProcessFilter::WithAnyPID => {}
ChildProcessFilter::WithPID(required_pid) => {
if current.get_pid() != *required_pid {
return None;
}
},
}
ChildProcessFilter::WithPGID(required_pgid) => {
if current.get_pgid() != *required_pgid {
return None;
}
},
}
}
Some(current.get_pid())
});
}
pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32)
-> Result<pid_t, Error>
{
pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32) -> Result<pid_t, Error> {
let current_ref = get_current();
let waiter = {
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 may_wait_for = match child_filter {
ChildProcessFilter::WithAnyPID => {
true
},
ChildProcessFilter::WithPID(required_pid) => {
child.get_pid() == *required_pid
},
ChildProcessFilter::WithPGID(required_pgid) => {
child.get_pgid() == *required_pgid
}
ChildProcessFilter::WithAnyPID => true,
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
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;
}
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 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() {
let child_ref = child_weak.upgrade().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 {
panic!("THIS SHOULD NEVER HAPPEN!");
@ -126,9 +124,9 @@ pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32)
Ok(child_pid)
}
fn lock_two_in_order<'a>(first_ref: &'a ProcessRef, second_ref: &'a ProcessRef) ->
(SgxMutexGuard<'a, Process>, SgxMutexGuard<'a, Process>)
{
fn lock_two_in_order<'a>(
first_ref: &'a ProcessRef,
second_ref: &'a ProcessRef,
) -> (SgxMutexGuard<'a, Process>, SgxMutexGuard<'a, Process>) {
(first_ref.lock().unwrap(), second_ref.lock().unwrap())
}

@ -1,11 +1,11 @@
pub use self::process::{Status, IDLE_PROCESS};
pub use self::task::{get_current, run_task};
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::wait::{Waiter, WaitQueue};
pub use self::spawn::{do_spawn, FileAction};
pub use self::wait::{WaitQueue, Waiter};
#[allow(non_camel_case_types)]
pub type pid_t = u32;
@ -51,14 +51,14 @@ pub fn do_getppid() -> pid_t {
parent.get_pid()
}
mod task;
mod exit;
mod process;
mod process_table;
mod spawn;
mod task;
mod wait;
mod exit;
use super::{*};
use self::task::Task;
use super::*;
use fs::{File, FileRef, FileTable};
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::task::{Task};
use fs::{File, FileRef, FileTable};
use vm::{ProcessVM, VMRangeTrait};
use fs::{FileTable, File, FileRef};
lazy_static! {
// Dummy object to make all processes having a parent
@ -24,9 +24,12 @@ lazy_static! {
}
impl Process {
pub fn new(exec_path: &str, task: Task, vm: ProcessVM, file_table: FileTable)
-> Result<(pid_t, ProcessRef), Error>
{
pub fn new(
exec_path: &str,
task: Task,
vm: ProcessVM,
file_table: FileTable,
) -> Result<(pid_t, ProcessRef), Error> {
let new_pid = process_table::alloc_pid();
let new_process_ref = Arc::new(SgxMutex::new(Process {
task: task,
@ -45,20 +48,48 @@ impl Process {
Ok((new_pid, new_process_ref))
}
pub fn get_task(&self) -> &Task { &self.task }
pub fn get_task_mut(&mut self) -> &mut Task { &mut self.task }
pub fn get_pid(&self) -> pid_t { self.pid }
pub fn get_pgid(&self) -> pid_t { self.pgid }
pub fn get_tgid(&self) -> pid_t { 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 }
pub fn get_task(&self) -> &Task {
&self.task
}
pub fn get_task_mut(&mut self) -> &mut Task {
&mut self.task
}
pub fn get_pid(&self) -> pid_t {
self.pid
}
pub fn get_pgid(&self) -> pid_t {
self.pgid
}
pub fn get_tgid(&self) -> pid_t {
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 {
@ -67,7 +98,6 @@ impl Drop for Process {
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Status {
RUNNING,

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

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

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

@ -1,7 +1,7 @@
use self::segment::*;
use super::*;
use std::{ptr};
use xmas_elf::{ElfFile, header, program, sections};
use self::segment::{*};
use std::ptr;
use xmas_elf::{header, program, sections, ElfFile};
pub const DEFAULT_STACK_SIZE: usize = 1 * 1024 * 1024;
pub const DEFAULT_HEAP_SIZE: usize = 2 * 1024 * 1024;
@ -21,8 +21,7 @@ pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result<ProcessVM, Error> {
let stack_size = DEFAULT_STACK_SIZE;
let heap_size = DEFAULT_HEAP_SIZE;
let mmap_size = DEFAULT_MMAP_SIZE;
let mut process_vm = ProcessVM::new(code_size, data_size, heap_size,
stack_size, mmap_size)?;
let mut process_vm = ProcessVM::new(code_size, data_size, heap_size, stack_size, mmap_size)?;
// Calculate the "real" addresses
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)
}
fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile)
-> Result<(), Error>
{
fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile) -> Result<(), Error> {
let rela_entries = elf_helper::get_rela_entries(elf_file, ".rela.dyn")?;
for rela_entry in rela_entries {
/*
@ -73,9 +70,7 @@ fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile)
Ok(())
}
fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile)
-> Result<(), Error>
{
fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile) -> Result<(), Error> {
let syscall_addr = __occlum_syscall as *const () as usize;
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 {
let dynsym_idx = rela_entry.get_symbol_table_index() as usize;
let dynsym_entry = &dynsym_entries[dynsym_idx];
let dynsym_str = dynsym_entry.get_name(elf_file)
.map_err(|e| Error::new(Errno::ENOEXEC,
"Failed to get the name of dynamic symbol"))?;
let dynsym_str = dynsym_entry
.get_name(elf_file)
.map_err(|e| Error::new(Errno::ENOEXEC, "Failed to get the name of dynamic symbol"))?;
if dynsym_str == "__occlum_syscall" {
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(())
}
extern {
extern "C" {
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 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 xmas_elf::symbol_table::Entry;
use xmas_elf::{header, program, sections, ElfFile};
mod elf_helper;
mod init_stack;
mod init_vm;
mod elf_helper;
mod segment;
#[derive(Debug)]
@ -22,10 +22,13 @@ pub enum FileAction {
Close(FileDesc),
}
pub fn do_spawn<P: AsRef<Path>>(elf_path: &P, argv: &[CString], envp: &[CString],
file_actions: &[FileAction], parent_ref: &ProcessRef)
-> Result<u32, Error>
{
pub fn do_spawn<P: AsRef<Path>>(
elf_path: &P,
argv: &[CString],
envp: &[CString],
file_actions: &[FileAction],
parent_ref: &ProcessRef,
) -> Result<u32, Error> {
let mut elf_buf = {
let key: sgx_key_128bit_t = [0 as uint8_t; 16];
let mut sgx_file = SgxFile::open_ex(elf_path, &key)
@ -37,8 +40,8 @@ pub fn do_spawn<P: AsRef<Path>>(elf_path: &P, argv: &[CString], envp: &[CString]
};
let elf_file = {
let elf_file = ElfFile::new(&elf_buf)
.map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?;
let elf_file =
ElfFile::new(&elf_buf).map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?;
header::sanity_check(&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 task = {
let program_entry = {
let program_entry = vm.get_base_addr() +
elf_helper::get_start_address(&elf_file)?;
let program_entry = vm.get_base_addr() + elf_helper::get_start_address(&elf_file)?;
if !vm.get_code_vma().contains_obj(program_entry, 16) {
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)
}
fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction])
-> Result<FileTable, Error>
{
fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction]) -> Result<FileTable, Error> {
// Usually, we just inherit the file table from the parent
let parent = parent_ref.lock().unwrap();
let should_inherit_file_table = parent.get_pid() > 0;
@ -89,7 +89,7 @@ fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction])
if old_fd != new_fd {
cloned_file_table.put_at(*new_fd, file, false);
}
},
}
FileAction::Close(fd) => {
cloned_file_table.del(*fd)?;
}
@ -111,10 +111,12 @@ fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction])
Ok(file_table)
}
fn init_task(user_entry: usize, stack_top: usize,
argv: &[CString], envp: &[CString])
-> Result<Task, Error>
{
fn init_task(
user_entry: usize,
stack_top: usize,
argv: &[CString],
envp: &[CString],
) -> Result<Task, Error> {
let user_stack = init_stack(stack_top, argv, envp)?;
Ok(Task {
user_stack_addr: user_stack,
@ -123,9 +125,7 @@ fn init_task(user_entry: usize, stack_top: usize,
})
}
fn init_stack(stack_top: usize, argv: &[CString], envp: &[CString])
-> Result<usize, Error>
{
fn init_stack(stack_top: usize, argv: &[CString], envp: &[CString]) -> Result<usize, Error> {
let mut auxtbl = AuxTable::new();
auxtbl.set_val(AuxKey::AT_PAGESZ, 4096)?;
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)
}
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 child = child_ref.lock().unwrap();
parent.children.push(Arc::downgrade(child_ref));

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

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

@ -1,18 +1,27 @@
use super::{*};
use super::*;
#[derive(Debug)]
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>>>,
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)]
struct WaiterInner<D, R>
where D: Sized + Copy, R: Sized + Copy
where
D: Sized + Copy,
R: Sized + Copy,
{
is_woken: bool,
data: D,
@ -20,7 +29,9 @@ struct WaiterInner<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> {
Waiter {
@ -50,17 +61,19 @@ impl<D, R> Waiter<D, R>
#[derive(Debug)]
pub struct WaitQueue<D, R>
where D: Sized + Copy, R: Sized + Copy
where
D: Sized + Copy,
R: Sized + Copy,
{
waiters: Vec<Waiter<D, R>>,
}
impl<D, R> WaitQueue<D, R>
where D: Sized + Copy, R: Sized + Copy
{
pub fn new() -> WaitQueue<D, R>
where
D: Sized + Copy,
R: Sized + Copy,
{
pub fn new() -> WaitQueue<D, R> {
WaitQueue {
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
where F: Fn(&D) -> Option<R>
where
F: Fn(&D) -> Option<R>,
{
let mut waiters = &mut self.waiters;
let del_waiter_i = {
@ -84,12 +98,13 @@ impl<D, R> WaitQueue<D, R>
waiter_inner.is_woken = true;
waiter_inner.result = Some(waiter_result);
true
}
else {
} else {
false
}
});
if waiter_i.is_none() { return 0; }
if waiter_i.is_none() {
return 0;
}
waiter_i.unwrap()
};
let del_waiter = waiters.swap_remove(del_waiter_i);
@ -120,20 +135,27 @@ fn set_event(thread: *const c_void) {
}
}
extern {
extern "C" {
fn sgx_thread_get_self() -> *const c_void;
/* 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;
/* 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 */
fn sgx_thread_setwait_untrusted_events_ocall(ret: *mut c_int,
waiter_thread: *const c_void, self_thread: *const c_void) -> c_int;
fn sgx_thread_setwait_untrusted_events_ocall(
ret: *mut c_int,
waiter_thread: *const c_void,
self_thread: *const c_void,
) -> c_int;
/* Wake multiple threads waiting on their untrusted events */
fn sgx_thread_set_multiple_untrusted_events_ocall(ret: *mut c_int,
waiter_threads: *const *const c_void, total: size_t ) -> c_int;
fn sgx_thread_set_multiple_untrusted_events_ocall(
ret: *mut c_int,
waiter_threads: *const *const c_void,
total: size_t,
) -> c_int;
}

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

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

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

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

@ -2,8 +2,8 @@ use super::*;
pub fn mpx_enable() -> Result<(), Error> {
match unsafe { __mpx_enable() } {
0 => { Ok(()) }
_ => { errno!(EPERM, "MPX cannot be enabled") }
0 => Ok(()),
_ => errno!(EPERM, "MPX cannot be enabled"),
}
}
@ -47,8 +47,7 @@ pub fn mpx_bndcu(bndreg: MpxReg, addr: usize) {
}
}
extern {
extern "C" {
// See mpx_util.h
fn __mpx_enable() -> i32;
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::atomic::{AtomicUsize, AtomicBool, Ordering};
use std::cmp::{min, max};
use std::{ptr};
#[derive(Debug)]
pub struct RingBuf {
@ -13,9 +13,14 @@ pub struct RingBuf {
impl RingBuf {
pub fn new(capacity: usize) -> RingBuf {
let inner = Arc::new(RingBufInner::new(capacity));
let reader = RingBufReader { inner: inner.clone() };
let reader = RingBufReader {
inner: inner.clone(),
};
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 {
pub fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
let mut tail = self.inner.get_tail();
@ -123,7 +127,9 @@ impl RingBufReader {
} else {
self.inner.capacity - tail
};
if may_read_nbytes == 0 { break; }
if may_read_nbytes == 0 {
break;
}
min(may_read_nbytes, buf_remain)
};
@ -150,7 +156,6 @@ impl Drop for RingBufReader {
}
}
impl RingBufWriter {
pub fn write(&self, buf: &[u8]) -> Result<usize, Error> {
if self.inner.is_closed() {
@ -169,7 +174,9 @@ impl RingBufWriter {
} else {
tail - head - 1
};
if may_write_nbytes == 0 { break; }
if may_write_nbytes == 0 {
break;
}
min(may_write_nbytes, buf_remain)
};

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

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

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

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

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