Format all Rust code with cargo fmt
In addition, to ensure that all future Rust code complies with `cargo fmt`, we add a Git post-commit hook that generates warnings if the commited code is not formated consistently.
This commit is contained in:
parent
dff0dbf77d
commit
7001b32a4a
@ -1,50 +1,61 @@
|
||||
use super::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sgxfs::{SgxFile};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sgxfs::SgxFile;
|
||||
|
||||
const LIBOS_CONFIG_PATH : &str = "Occlum.json.protected";
|
||||
const LIBOS_CONFIG_PATH: &str = "Occlum.json.protected";
|
||||
|
||||
lazy_static! {
|
||||
pub static ref LIBOS_CONFIG: Config = {
|
||||
let mut config_file = {
|
||||
let config_file = match SgxFile::open_integrity_only(LIBOS_CONFIG_PATH) {
|
||||
Err(_) => panic!("Failed to find or open Occlum's config file: {}",
|
||||
LIBOS_CONFIG_PATH),
|
||||
Err(_) => panic!(
|
||||
"Failed to find or open Occlum's config file: {}",
|
||||
LIBOS_CONFIG_PATH
|
||||
),
|
||||
Ok(file) => file,
|
||||
};
|
||||
|
||||
let actual_mac = match config_file.get_mac() {
|
||||
Err(_) => panic!("Failed to get the MAC of Occlum's config file: {}",
|
||||
LIBOS_CONFIG_PATH),
|
||||
Err(_) => panic!(
|
||||
"Failed to get the MAC of Occlum's config file: {}",
|
||||
LIBOS_CONFIG_PATH
|
||||
),
|
||||
Ok(mac) => mac,
|
||||
};
|
||||
let expected_mac = conf_get_hardcoded_file_mac();
|
||||
if actual_mac != expected_mac {
|
||||
panic!("The MAC of Occlum's config file is not as expected: {}",
|
||||
LIBOS_CONFIG_PATH);
|
||||
panic!(
|
||||
"The MAC of Occlum's config file is not as expected: {}",
|
||||
LIBOS_CONFIG_PATH
|
||||
);
|
||||
}
|
||||
|
||||
config_file
|
||||
};
|
||||
let config_json = {
|
||||
let mut config_json = String::new();
|
||||
config_file.read_to_string(&mut config_json)
|
||||
.map_err(|_| {
|
||||
panic!("Failed to read from Occlum's config file: {}",
|
||||
LIBOS_CONFIG_PATH);
|
||||
});
|
||||
config_file.read_to_string(&mut config_json).map_err(|_| {
|
||||
panic!(
|
||||
"Failed to read from Occlum's config file: {}",
|
||||
LIBOS_CONFIG_PATH
|
||||
);
|
||||
});
|
||||
config_json
|
||||
};
|
||||
let config_input: InputConfig = match serde_json::from_str(&config_json) {
|
||||
Err(_) => panic!("Failed to parse JSON from Occlum's config file: {}",
|
||||
LIBOS_CONFIG_PATH),
|
||||
Ok(config_input) => config_input
|
||||
Err(_) => panic!(
|
||||
"Failed to parse JSON from Occlum's config file: {}",
|
||||
LIBOS_CONFIG_PATH
|
||||
),
|
||||
Ok(config_input) => config_input,
|
||||
};
|
||||
let config = match Config::from_input(&config_input) {
|
||||
Err(_) => panic!("Found invalid config in Occlum's config file: {}",
|
||||
LIBOS_CONFIG_PATH),
|
||||
Ok(config) => config
|
||||
Err(_) => panic!(
|
||||
"Found invalid config in Occlum's config file: {}",
|
||||
LIBOS_CONFIG_PATH
|
||||
),
|
||||
Ok(config) => config,
|
||||
};
|
||||
config
|
||||
};
|
||||
@ -61,20 +72,19 @@ fn conf_get_hardcoded_file_mac() -> sgx_aes_gcm_128bit_tag_t {
|
||||
.to_str()
|
||||
.expect("Invalid MAC")
|
||||
};
|
||||
let mac = parse_mac(mac_str)
|
||||
.expect("Invalid MAC");
|
||||
let mac = parse_mac(mac_str).expect("Invalid MAC");
|
||||
mac
|
||||
}
|
||||
|
||||
fn parse_mac(mac_str: &str) -> Result<sgx_aes_gcm_128bit_tag_t, Error> {
|
||||
let bytes_str_vec = {
|
||||
let bytes_str_vec : Vec<&str> = mac_str.split("-").collect();
|
||||
let bytes_str_vec: Vec<&str> = mac_str.split("-").collect();
|
||||
if bytes_str_vec.len() != 16 {
|
||||
return errno!(EINVAL, "The length or format of MAC string is invalid");
|
||||
}
|
||||
bytes_str_vec
|
||||
};
|
||||
let mut mac : sgx_aes_gcm_128bit_tag_t = Default::default();
|
||||
let mut mac: sgx_aes_gcm_128bit_tag_t = Default::default();
|
||||
for (byte_i, byte_str) in bytes_str_vec.iter().enumerate() {
|
||||
mac[byte_i] = u8::from_str_radix(byte_str, 16)
|
||||
.map_err(|_| Error::new(Errno::EINVAL, "The format of MAC string is invalid"))?;
|
||||
@ -82,7 +92,6 @@ fn parse_mac(mac_str: &str) -> Result<sgx_aes_gcm_128bit_tag_t, Error> {
|
||||
Ok(mac)
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Config {
|
||||
pub vm: ConfigVM,
|
||||
@ -92,7 +101,7 @@ pub struct Config {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ConfigVM {
|
||||
pub user_space_size : usize,
|
||||
pub user_space_size: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -124,7 +133,6 @@ pub struct ConfigMountOptions {
|
||||
pub mac: Option<sgx_aes_gcm_128bit_tag_t>,
|
||||
}
|
||||
|
||||
|
||||
impl Config {
|
||||
fn from_input(input: &InputConfig) -> Result<Config, Error> {
|
||||
let vm = ConfigVM::from_input(&input.vm)?;
|
||||
@ -162,7 +170,7 @@ impl ConfigProcess {
|
||||
|
||||
impl ConfigMount {
|
||||
fn from_input(input: &InputConfigMount) -> Result<ConfigMount, Error> {
|
||||
const ALL_FS_TYPES : [&str; 3] = [ "sefs", "hostfs", "ramfs" ];
|
||||
const ALL_FS_TYPES: [&str; 3] = ["sefs", "hostfs", "ramfs"];
|
||||
|
||||
let type_ = match input.type_.as_str() {
|
||||
"sefs" => ConfigMountFsType::TYPE_SEFS,
|
||||
@ -181,28 +189,34 @@ impl ConfigMount {
|
||||
};
|
||||
let source = input.source.as_ref().map(|s| PathBuf::from(s));
|
||||
let options = ConfigMountOptions::from_input(&input.options)?;
|
||||
Ok(ConfigMount { type_, target, source, options, })
|
||||
Ok(ConfigMount {
|
||||
type_,
|
||||
target,
|
||||
source,
|
||||
options,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigMountOptions {
|
||||
fn from_input(input: &InputConfigMountOptions) -> Result<ConfigMountOptions, Error> {
|
||||
let (integrity_only, mac) =
|
||||
if !input.integrity_only {
|
||||
(false, None)
|
||||
} else {
|
||||
if input.mac.is_none() {
|
||||
return errno!(EINVAL, "MAC is expected");
|
||||
}
|
||||
(true, Some(parse_mac(&input.mac.as_ref().unwrap())?))
|
||||
};
|
||||
Ok(ConfigMountOptions { integrity_only, mac })
|
||||
let (integrity_only, mac) = if !input.integrity_only {
|
||||
(false, None)
|
||||
} else {
|
||||
if input.mac.is_none() {
|
||||
return errno!(EINVAL, "MAC is expected");
|
||||
}
|
||||
(true, Some(parse_mac(&input.mac.as_ref().unwrap())?))
|
||||
};
|
||||
Ok(ConfigMountOptions {
|
||||
integrity_only,
|
||||
mac,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn parse_memory_size(mem_str: &str) -> Result<usize, Error> {
|
||||
const UNIT2FACTOR : [(&str, usize); 5]= [
|
||||
const UNIT2FACTOR: [(&str, usize); 5] = [
|
||||
("KB", 1024),
|
||||
("MB", 1024 * 1024),
|
||||
("GB", 1024 * 1024 * 1024),
|
||||
@ -216,18 +230,16 @@ fn parse_memory_size(mem_str: &str) -> Result<usize, Error> {
|
||||
.position(|(unit, _)| mem_str.ends_with(unit))
|
||||
.ok_or_else(|| Error::new(Errno::EINVAL, "No unit"))
|
||||
.map(|unit_i| &UNIT2FACTOR[unit_i])?;
|
||||
let number =
|
||||
match mem_str[0..mem_str.len() - unit.len()]
|
||||
.trim()
|
||||
.parse::<usize>()
|
||||
{
|
||||
Err(_) => return errno!(EINVAL, "No number"),
|
||||
Ok(number) => number
|
||||
};
|
||||
let number = match mem_str[0..mem_str.len() - unit.len()]
|
||||
.trim()
|
||||
.parse::<usize>()
|
||||
{
|
||||
Err(_) => return errno!(EINVAL, "No number"),
|
||||
Ok(number) => number,
|
||||
};
|
||||
Ok(number * factor)
|
||||
}
|
||||
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct InputConfig {
|
||||
@ -243,7 +255,7 @@ struct InputConfig {
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct InputConfigVM {
|
||||
#[serde(default = "InputConfigVM::get_user_space_size")]
|
||||
pub user_space_size : String,
|
||||
pub user_space_size: String,
|
||||
}
|
||||
|
||||
impl InputConfigVM {
|
||||
@ -255,7 +267,7 @@ impl InputConfigVM {
|
||||
impl Default for InputConfigVM {
|
||||
fn default() -> InputConfigVM {
|
||||
InputConfigVM {
|
||||
user_space_size: InputConfigVM::get_user_space_size()
|
||||
user_space_size: InputConfigVM::get_user_space_size(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,9 +81,7 @@ fn do_boot(path_str: &str, argv: &Vec<CString>) -> Result<(), Error> {
|
||||
util::mpx_util::mpx_enable()?;
|
||||
|
||||
// The default environment variables
|
||||
let envp = vec![
|
||||
CString::new("OCCLUM=yes").unwrap()
|
||||
];
|
||||
let envp = vec![CString::new("OCCLUM=yes").unwrap()];
|
||||
let file_actions = Vec::new();
|
||||
let parent = &process::IDLE_PROCESS;
|
||||
process::do_spawn(&path_str, argv, &envp, &file_actions, parent)?;
|
||||
|
@ -31,9 +31,8 @@ impl File for DevRandom {
|
||||
}
|
||||
Err(e) => {
|
||||
if total_nbytes > 0 {
|
||||
break
|
||||
}
|
||||
else {
|
||||
break;
|
||||
} else {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
|
@ -7,32 +7,32 @@ use {process, std};
|
||||
use super::*;
|
||||
|
||||
pub use self::access::{do_access, do_faccessat, AccessFlags, AccessModes, AT_FDCWD};
|
||||
use self::dev_null::DevNull;
|
||||
use self::dev_random::DevRandom;
|
||||
use self::dev_zero::DevZero;
|
||||
pub use self::file::{File, FileRef, SgxFile, StdinFile, StdoutFile};
|
||||
pub use self::file_table::{FileDesc, FileTable};
|
||||
use self::inode_file::OpenOptions;
|
||||
pub use self::inode_file::{INodeExt, INodeFile};
|
||||
pub use self::root_inode::{ROOT_INODE};
|
||||
pub use self::io_multiplexing::*;
|
||||
use self::dev_null::DevNull;
|
||||
use self::dev_zero::DevZero;
|
||||
use self::dev_random::DevRandom;
|
||||
pub use self::pipe::Pipe;
|
||||
pub use self::root_inode::ROOT_INODE;
|
||||
pub use self::socket_file::{AsSocket, SocketFile};
|
||||
pub use self::unix_socket::{AsUnixSocket, UnixSocketFile};
|
||||
use std::any::Any;
|
||||
use std::mem::uninitialized;
|
||||
|
||||
mod access;
|
||||
mod dev_null;
|
||||
mod dev_random;
|
||||
mod dev_zero;
|
||||
mod file;
|
||||
mod file_table;
|
||||
mod hostfs;
|
||||
mod inode_file;
|
||||
mod root_inode;
|
||||
mod io_multiplexing;
|
||||
mod dev_null;
|
||||
mod dev_zero;
|
||||
mod dev_random;
|
||||
mod pipe;
|
||||
mod root_inode;
|
||||
mod sgx_impl;
|
||||
mod socket_file;
|
||||
mod unix_socket;
|
||||
|
@ -1,14 +1,14 @@
|
||||
use super::*;
|
||||
use super::hostfs::HostFS;
|
||||
use super::sgx_impl::SgxStorage;
|
||||
use super::*;
|
||||
use config::{ConfigMount, ConfigMountFsType};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use rcore_fs::vfs::{FileSystem, FileType, FsError, INode};
|
||||
use rcore_fs_sefs::SEFS;
|
||||
use rcore_fs_sefs::dev::*;
|
||||
use rcore_fs_mountfs::{MountFS, MNode};
|
||||
use rcore_fs_mountfs::{MNode, MountFS};
|
||||
use rcore_fs_ramfs::RamFS;
|
||||
use rcore_fs_sefs::dev::*;
|
||||
use rcore_fs_sefs::SEFS;
|
||||
|
||||
lazy_static! {
|
||||
/// The root of file system
|
||||
@ -26,42 +26,53 @@ lazy_static! {
|
||||
};
|
||||
}
|
||||
|
||||
fn open_or_create_root_fs_according_to(mount_config: &Vec<ConfigMount>)
|
||||
-> Result<Arc<MountFS>, Error>
|
||||
{
|
||||
fn open_or_create_root_fs_according_to(
|
||||
mount_config: &Vec<ConfigMount>,
|
||||
) -> Result<Arc<MountFS>, Error> {
|
||||
let root_sefs_source = {
|
||||
let root_mount_config = mount_config
|
||||
.iter()
|
||||
.find(|m| m.target == Path::new("/"))
|
||||
.ok_or_else(|| Error::new(Errno::ENOENT, "The mount point at / is not specified"))?;
|
||||
|
||||
if root_mount_config.type_ != ConfigMountFsType::TYPE_SEFS {
|
||||
if root_mount_config.type_ != ConfigMountFsType::TYPE_SEFS {
|
||||
return errno!(EINVAL, "The mount point at / must be SEFS");
|
||||
}
|
||||
if root_mount_config.options.integrity_only {
|
||||
return errno!(EINVAL, "The root SEFS at / must be encrypted (i.e., integrity-only is not enough)");
|
||||
return errno!(
|
||||
EINVAL,
|
||||
"The root SEFS at / must be encrypted (i.e., integrity-only is not enough)"
|
||||
);
|
||||
}
|
||||
if root_mount_config.source.is_none() {
|
||||
return errno!(EINVAL, "The root SEFS must be given a source path (on host)");
|
||||
return errno!(
|
||||
EINVAL,
|
||||
"The root SEFS must be given a source path (on host)"
|
||||
);
|
||||
}
|
||||
root_mount_config.source.as_ref().unwrap()
|
||||
};
|
||||
|
||||
let root_sefs = {
|
||||
SEFS::open(Box::new(SgxStorage::new(root_sefs_source, false)),
|
||||
&time::OcclumTimeProvider)
|
||||
SEFS::open(
|
||||
Box::new(SgxStorage::new(root_sefs_source, false)),
|
||||
&time::OcclumTimeProvider,
|
||||
)
|
||||
}
|
||||
.or_else(|_| {
|
||||
SEFS::create(Box::new(SgxStorage::new(root_sefs_source, false)),
|
||||
&time::OcclumTimeProvider)
|
||||
SEFS::create(
|
||||
Box::new(SgxStorage::new(root_sefs_source, false)),
|
||||
&time::OcclumTimeProvider,
|
||||
)
|
||||
})?;
|
||||
let root_mountable_sefs = MountFS::new(root_sefs);
|
||||
Ok(root_mountable_sefs)
|
||||
}
|
||||
|
||||
fn mount_nonroot_fs_according_to(mount_config: &Vec<ConfigMount>, root: &MNode)
|
||||
-> Result<(), Error>
|
||||
{
|
||||
fn mount_nonroot_fs_according_to(
|
||||
mount_config: &Vec<ConfigMount>,
|
||||
root: &MNode,
|
||||
) -> Result<(), Error> {
|
||||
for mc in mount_config {
|
||||
if mc.target == Path::new("/") {
|
||||
continue;
|
||||
@ -79,10 +90,13 @@ fn mount_nonroot_fs_according_to(mount_config: &Vec<ConfigMount>, root: &MNode)
|
||||
match mc.type_ {
|
||||
TYPE_SEFS => {
|
||||
if !mc.options.integrity_only {
|
||||
return errno!(EINVAL, "Must be integrity-only SEFS")
|
||||
return errno!(EINVAL, "Must be integrity-only SEFS");
|
||||
}
|
||||
if mc.source.is_none() {
|
||||
return errno!(EINVAL, "Source is expected for integrity-only SEFS is supported")
|
||||
return errno!(
|
||||
EINVAL,
|
||||
"Source is expected for integrity-only SEFS is supported"
|
||||
);
|
||||
}
|
||||
let source_path = mc.source.as_ref().unwrap();
|
||||
|
||||
@ -93,28 +107,26 @@ fn mount_nonroot_fs_according_to(mount_config: &Vec<ConfigMount>, root: &MNode)
|
||||
};
|
||||
let sefs = SEFS::open(device, &time::OcclumTimeProvider)?;
|
||||
mount_fs_at(sefs, &root, target_dirname)?;
|
||||
},
|
||||
}
|
||||
TYPE_HOSTFS => {
|
||||
if mc.source.is_none() {
|
||||
return errno!(EINVAL, "Source is expected for HostFS")
|
||||
return errno!(EINVAL, "Source is expected for HostFS");
|
||||
}
|
||||
let source_path = mc.source.as_ref().unwrap();
|
||||
|
||||
let hostfs = HostFS::new(source_path);
|
||||
mount_fs_at(hostfs, &root, target_dirname)?;
|
||||
},
|
||||
}
|
||||
TYPE_RAMFS => {
|
||||
let ramfs = RamFS::new();
|
||||
mount_fs_at(ramfs, &root, target_dirname)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mount_fs_at(fs: Arc<dyn FileSystem>, parent_inode: &MNode, dirname: &str)
|
||||
-> Result<(), Error>
|
||||
{
|
||||
fn mount_fs_at(fs: Arc<dyn FileSystem>, parent_inode: &MNode, dirname: &str) -> Result<(), Error> {
|
||||
let mount_dir = match parent_inode.find(false, dirname) {
|
||||
Ok(existing_dir) => {
|
||||
if existing_dir.metadata()?.type_ != FileType::Dir {
|
||||
@ -122,9 +134,7 @@ fn mount_fs_at(fs: Arc<dyn FileSystem>, parent_inode: &MNode, dirname: &str)
|
||||
}
|
||||
existing_dir
|
||||
}
|
||||
Err(_) => {
|
||||
parent_inode.create(dirname, FileType::Dir, 0o777)?
|
||||
}
|
||||
Err(_) => parent_inode.create(dirname, FileType::Dir, 0o777)?,
|
||||
};
|
||||
mount_dir.mount(fs);
|
||||
Ok(())
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{sgx_aes_gcm_128bit_tag_t};
|
||||
use super::sgx_aes_gcm_128bit_tag_t;
|
||||
use rcore_fs::dev::TimeProvider;
|
||||
use rcore_fs::vfs::Timespec;
|
||||
use rcore_fs_sefs::dev::*;
|
||||
@ -31,7 +31,11 @@ impl SgxStorage {
|
||||
/// It lookups cache first, if miss, then call `open_fn` to open one,
|
||||
/// and add it to cache before return.
|
||||
#[cfg(feature = "sgx_file_cache")]
|
||||
fn get(&self, file_id: usize, open_fn: impl FnOnce(&Self) -> DevResult<LockedFile>) -> DevResult<LockedFile> {
|
||||
fn get(
|
||||
&self,
|
||||
file_id: usize,
|
||||
open_fn: impl FnOnce(&Self) -> DevResult<LockedFile>,
|
||||
) -> DevResult<LockedFile> {
|
||||
// query cache
|
||||
let mut caches = self.file_cache.lock().unwrap();
|
||||
if let Some(locked_file) = caches.get(&file_id) {
|
||||
@ -46,7 +50,11 @@ impl SgxStorage {
|
||||
}
|
||||
/// Get file by `file_id` without cache.
|
||||
#[cfg(not(feature = "sgx_file_cache"))]
|
||||
fn get(&self, file_id: usize, open_fn: impl FnOnce(&Self) -> DevResult<LockedFile>) -> LockedFile {
|
||||
fn get(
|
||||
&self,
|
||||
file_id: usize,
|
||||
open_fn: impl FnOnce(&Self) -> DevResult<LockedFile>,
|
||||
) -> LockedFile {
|
||||
open_fn(self)
|
||||
}
|
||||
|
||||
@ -84,11 +92,13 @@ impl Storage for SgxStorage {
|
||||
|
||||
// Check the MAC of the root file against the given root MAC of the storage
|
||||
if file_id == 0 && self.root_mac.is_some() {
|
||||
let root_file_mac = file.get_mac()
|
||||
.expect("Failed to get mac");
|
||||
let root_file_mac = file.get_mac().expect("Failed to get mac");
|
||||
if root_file_mac != self.root_mac.unwrap() {
|
||||
println!("Expected MAC = {:#?}, actual MAC = {:?}",
|
||||
self.root_mac.unwrap(), root_file_mac);
|
||||
println!(
|
||||
"Expected MAC = {:#?}, actual MAC = {:?}",
|
||||
self.root_mac.unwrap(),
|
||||
root_file_mac
|
||||
);
|
||||
return Err(DeviceError);
|
||||
}
|
||||
}
|
||||
|
@ -23,9 +23,9 @@ extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate rcore_fs;
|
||||
extern crate rcore_fs_sefs;
|
||||
extern crate rcore_fs_ramfs;
|
||||
extern crate rcore_fs_mountfs;
|
||||
extern crate rcore_fs_ramfs;
|
||||
extern crate rcore_fs_sefs;
|
||||
#[macro_use]
|
||||
extern crate derive_builder;
|
||||
extern crate serde;
|
||||
@ -39,9 +39,9 @@ use std::panic;
|
||||
|
||||
#[macro_use]
|
||||
mod prelude;
|
||||
mod errno;
|
||||
mod entry;
|
||||
mod config;
|
||||
mod entry;
|
||||
mod errno;
|
||||
mod fs;
|
||||
mod misc;
|
||||
mod process;
|
||||
|
@ -3,11 +3,11 @@ pub use self::exit::{do_exit, do_wait4, ChildProcessFilter};
|
||||
pub use self::futex::{futex_op_and_flags_from_u32, futex_wait, futex_wake, FutexFlags, FutexOp};
|
||||
pub use self::process::{Status, IDLE_PROCESS};
|
||||
pub use self::process_table::get;
|
||||
pub use self::sched::{do_sched_getaffinity, do_sched_setaffinity, CpuSet};
|
||||
pub use self::spawn::{do_spawn, FileAction};
|
||||
pub use self::task::{current_pid, get_current, run_task};
|
||||
pub use self::thread::{do_clone, do_set_tid_address, CloneFlags, ThreadGroup};
|
||||
pub use self::wait::{WaitQueue, Waiter};
|
||||
pub use self::sched::{CpuSet, do_sched_getaffinity, do_sched_setaffinity};
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type pid_t = u32;
|
||||
@ -71,14 +71,14 @@ mod exit;
|
||||
mod futex;
|
||||
mod process;
|
||||
mod process_table;
|
||||
mod sched;
|
||||
mod spawn;
|
||||
mod task;
|
||||
mod thread;
|
||||
mod wait;
|
||||
mod sched;
|
||||
|
||||
use self::task::Task;
|
||||
use super::*;
|
||||
use fs::{File, FileRef, FileTable};
|
||||
use misc::ResourceLimitsRef;
|
||||
use vm::{ProcessVM};
|
||||
use vm::ProcessVM;
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::task::Task;
|
||||
use super::*;
|
||||
use fs::{File, FileRef, FileTable};
|
||||
use vm::{ProcessVM};
|
||||
use vm::ProcessVM;
|
||||
|
||||
lazy_static! {
|
||||
// Dummy object to make all processes having a parent
|
||||
|
@ -1,8 +1,20 @@
|
||||
use super::*;
|
||||
|
||||
extern "C" {
|
||||
fn ocall_sched_getaffinity(ret: *mut i32, errno: *mut i32, pid: i32, cpusetsize: size_t, mask: *mut c_uchar) -> sgx_status_t;
|
||||
fn ocall_sched_setaffinity(ret: *mut i32, errno: *mut i32, pid: i32, cpusetsize: size_t, mask: *const c_uchar) -> sgx_status_t;
|
||||
fn ocall_sched_getaffinity(
|
||||
ret: *mut i32,
|
||||
errno: *mut i32,
|
||||
pid: i32,
|
||||
cpusetsize: size_t,
|
||||
mask: *mut c_uchar,
|
||||
) -> sgx_status_t;
|
||||
fn ocall_sched_setaffinity(
|
||||
ret: *mut i32,
|
||||
errno: *mut i32,
|
||||
pid: i32,
|
||||
cpusetsize: size_t,
|
||||
mask: *const c_uchar,
|
||||
) -> sgx_status_t;
|
||||
}
|
||||
|
||||
pub struct CpuSet {
|
||||
@ -11,13 +23,17 @@ pub struct CpuSet {
|
||||
|
||||
impl CpuSet {
|
||||
pub fn new(len: usize) -> CpuSet {
|
||||
let mut cpuset = CpuSet { vec: Vec::with_capacity(len) };
|
||||
let mut cpuset = CpuSet {
|
||||
vec: Vec::with_capacity(len),
|
||||
};
|
||||
cpuset.vec.resize(len, 0);
|
||||
cpuset
|
||||
}
|
||||
|
||||
pub fn from_raw_buf(ptr: *const u8, cpusize: usize) -> CpuSet {
|
||||
let mut cpuset = CpuSet { vec: Vec::with_capacity(cpusize) };
|
||||
let mut cpuset = CpuSet {
|
||||
vec: Vec::with_capacity(cpusize),
|
||||
};
|
||||
let buf_slice = unsafe { std::slice::from_raw_parts(ptr, cpusize) };
|
||||
cpuset.vec.extend_from_slice(buf_slice);
|
||||
cpuset
|
||||
@ -63,11 +79,7 @@ impl std::fmt::UpperHex for CpuSet {
|
||||
}
|
||||
|
||||
fn find_host_tid(pid: pid_t) -> Result<pid_t, Error> {
|
||||
let process_ref = if pid == 0 {
|
||||
get_current()
|
||||
} else {
|
||||
get(pid)?
|
||||
};
|
||||
let process_ref = if pid == 0 { get_current() } else { get(pid)? };
|
||||
let mut process = process_ref.lock().unwrap();
|
||||
let host_tid = process.get_host_tid();
|
||||
Ok(host_tid)
|
||||
|
@ -86,8 +86,7 @@ impl StackBuf {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn put(&self, val: u64) -> Result<*const u64, Error>
|
||||
{
|
||||
pub fn put(&self, val: u64) -> Result<*const u64, Error> {
|
||||
let val_ptr = self.alloc(8, 8)? as *mut u64;
|
||||
unsafe {
|
||||
ptr::write(val_ptr, val);
|
||||
@ -206,14 +205,14 @@ pub enum AuxKey {
|
||||
AT_CLKTCK = 17, /* frequency at which times() increments */
|
||||
|
||||
/* 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
|
||||
* differ from AT_PLATFORM. */
|
||||
AT_RANDOM = 25, /* address of 16 random bytes */
|
||||
AT_HWCAP2 = 26, /* extension of AT_HWCAP */
|
||||
AT_RANDOM = 25, /* address of 16 random bytes */
|
||||
AT_HWCAP2 = 26, /* extension of AT_HWCAP */
|
||||
|
||||
/* 28...30 not used */
|
||||
AT_EXECFN = 31, /* filename of program */
|
||||
AT_EXECFN = 31, /* filename of program */
|
||||
AT_SYSINFO = 32,
|
||||
|
||||
/* Occlum-specific entries */
|
||||
@ -238,7 +237,8 @@ impl AuxTable {
|
||||
if key == AuxKey::AT_NULL || key == AuxKey::AT_IGNORE {
|
||||
return errno!(EINVAL, "Illegal key");
|
||||
}
|
||||
self.table.entry(key)
|
||||
self.table
|
||||
.entry(key)
|
||||
.and_modify(|val_mut| *val_mut = val)
|
||||
.or_insert(val);
|
||||
Ok(())
|
||||
@ -248,7 +248,7 @@ impl AuxTable {
|
||||
self.table.get(&key).map(|val_ref| *val_ref)
|
||||
}
|
||||
|
||||
pub fn del(&mut self, key: AuxKey) -> Option<u64>{
|
||||
pub fn del(&mut self, key: AuxKey) -> Option<u64> {
|
||||
self.table.remove(&key)
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ pub fn do_init(
|
||||
elf_file: &ElfFile,
|
||||
elf_buf: &[u8],
|
||||
ldso_elf_file: &ElfFile,
|
||||
ldso_elf_buf: &[u8]
|
||||
ldso_elf_buf: &[u8],
|
||||
) -> Result<ProcessVM, Error> {
|
||||
// Alloc all virtual memory areas
|
||||
let mut code_seg = get_code_segment(elf_file)?;
|
||||
@ -24,7 +24,10 @@ pub fn do_init(
|
||||
let ldso_code_start = 0;
|
||||
let ldso_code_end = align_down(ldso_data_seg.get_mem_addr(), ldso_data_seg.get_mem_align());
|
||||
let ldso_data_start = ldso_code_end;
|
||||
let ldso_data_end = align_up(ldso_data_seg.get_mem_addr() + ldso_data_seg.get_mem_size(), 4096);
|
||||
let ldso_data_end = align_up(
|
||||
ldso_data_seg.get_mem_addr() + ldso_data_seg.get_mem_size(),
|
||||
4096,
|
||||
);
|
||||
let ldso_code_size = ldso_code_end - ldso_code_start;
|
||||
let ldso_data_size = ldso_data_end - ldso_data_start;
|
||||
|
||||
|
@ -64,8 +64,8 @@ pub fn do_spawn<P: AsRef<Path>>(
|
||||
};
|
||||
|
||||
let ldso_elf_file = {
|
||||
let ldso_elf_file =
|
||||
ElfFile::new(&ldso_elf_buf).map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?;
|
||||
let ldso_elf_file = ElfFile::new(&ldso_elf_buf)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?;
|
||||
header::sanity_check(&ldso_elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?;
|
||||
/*
|
||||
@ -78,15 +78,13 @@ pub fn do_spawn<P: AsRef<Path>>(
|
||||
|
||||
let (new_pid, new_process_ref) = {
|
||||
let cwd = parent_ref.lock().unwrap().get_cwd().to_owned();
|
||||
let vm = init_vm::do_init(&elf_file, &elf_buf[..],
|
||||
&ldso_elf_file, &ldso_elf_buf[..])?;
|
||||
let vm = init_vm::do_init(&elf_file, &elf_buf[..], &ldso_elf_file, &ldso_elf_buf[..])?;
|
||||
let base_addr = vm.get_base_addr();
|
||||
let auxtbl = init_auxtbl(&vm, &elf_file)?;
|
||||
let task = {
|
||||
let ldso_entry = {
|
||||
let ldso_base_addr = vm.get_ldso_code_range().start();
|
||||
let ldso_entry = ldso_base_addr +
|
||||
elf_helper::get_start_address(&ldso_elf_file)?;
|
||||
let ldso_entry = ldso_base_addr + elf_helper::get_start_address(&ldso_elf_file)?;
|
||||
if !vm.get_ldso_code_range().contains(ldso_entry) {
|
||||
return errno!(EINVAL, "Invalid program entry");
|
||||
}
|
||||
@ -96,8 +94,13 @@ pub fn do_spawn<P: AsRef<Path>>(
|
||||
let user_stack_limit = vm.get_stack_limit();
|
||||
let user_rsp = init_stack::do_init(user_stack_base, 4096, argv, envp, &auxtbl)?;
|
||||
unsafe {
|
||||
Task::new(ldso_entry, user_rsp,
|
||||
user_stack_base, user_stack_limit, None)?
|
||||
Task::new(
|
||||
ldso_entry,
|
||||
user_rsp,
|
||||
user_stack_base,
|
||||
user_stack_limit,
|
||||
None,
|
||||
)?
|
||||
}
|
||||
};
|
||||
let vm_ref = Arc::new(SgxMutex::new(vm));
|
||||
@ -167,10 +170,7 @@ fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction]) -> Result<Fi
|
||||
Ok(file_table)
|
||||
}
|
||||
|
||||
fn init_auxtbl(
|
||||
process_vm: &ProcessVM,
|
||||
elf_file: &ElfFile,
|
||||
) -> Result<AuxTable, Error> {
|
||||
fn init_auxtbl(process_vm: &ProcessVM, elf_file: &ElfFile) -> Result<AuxTable, Error> {
|
||||
let mut auxtbl = AuxTable::new();
|
||||
auxtbl.set(AuxKey::AT_PAGESZ, 4096)?;
|
||||
auxtbl.set(AuxKey::AT_UID, 0)?;
|
||||
|
@ -40,7 +40,8 @@ impl Segment {
|
||||
return Err((
|
||||
Errno::EINVAL,
|
||||
"Memory address and file offset is not equal, per modulo",
|
||||
).into());
|
||||
)
|
||||
.into());
|
||||
}
|
||||
if ph64.mem_size < ph64.file_size {
|
||||
return Err((Errno::EINVAL, "Memory size must be greater than file size").into());
|
||||
|
@ -52,7 +52,6 @@ impl Task {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lazy_static! {
|
||||
static ref NEW_PROCESS_QUEUE: SgxMutex<VecDeque<ProcessRef>> =
|
||||
{ SgxMutex::new(VecDeque::new()) };
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::vm::VMRange;
|
||||
use super::*;
|
||||
use super::vm::{VMRange};
|
||||
|
||||
pub struct ThreadGroup {
|
||||
threads: Vec<ProcessRef>,
|
||||
@ -64,9 +64,13 @@ pub fn do_clone(
|
||||
let user_stack_base = user_stack_range.end();
|
||||
let user_stack_limit = user_stack_range.start();
|
||||
unsafe {
|
||||
Task::new(thread_entry, user_rsp,
|
||||
user_stack_base, user_stack_limit,
|
||||
new_tls)?
|
||||
Task::new(
|
||||
thread_entry,
|
||||
user_rsp,
|
||||
user_stack_base,
|
||||
user_stack_limit,
|
||||
new_tls,
|
||||
)?
|
||||
}
|
||||
};
|
||||
let files_ref = current.get_files().clone();
|
||||
@ -119,11 +123,9 @@ fn guess_user_stack_bound(vm: &ProcessVM, user_rsp: usize) -> Result<&VMRange, E
|
||||
// The next three cases are very unlikely, but valid
|
||||
else if vm.get_stack_range().contains(user_rsp) {
|
||||
Ok(vm.get_stack_range())
|
||||
}
|
||||
else if vm.get_heap_range().contains(user_rsp) {
|
||||
} else if vm.get_heap_range().contains(user_rsp) {
|
||||
Ok(vm.get_heap_range())
|
||||
}
|
||||
else if vm.get_data_range().contains(user_rsp) {
|
||||
} else if vm.get_data_range().contains(user_rsp) {
|
||||
Ok(vm.get_data_range())
|
||||
}
|
||||
// Invalid
|
||||
|
@ -10,12 +10,12 @@
|
||||
use fs::*;
|
||||
use misc::{resource_t, rlimit_t, utsname_t};
|
||||
use prelude::*;
|
||||
use process::{pid_t, ChildProcessFilter, CloneFlags, FileAction, FutexFlags, FutexOp, CpuSet};
|
||||
use process::{pid_t, ChildProcessFilter, CloneFlags, CpuSet, FileAction, FutexFlags, FutexOp};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::ptr;
|
||||
use time::{timeval_t, clockid_t, timespec_t};
|
||||
use time::{clockid_t, timespec_t, timeval_t};
|
||||
use util::mem_util::from_user::*;
|
||||
use vm::{VMPerms, MMapFlags};
|
||||
use vm::{MMapFlags, VMPerms};
|
||||
use {fs, process, std, vm};
|
||||
|
||||
use super::*;
|
||||
@ -175,8 +175,12 @@ pub extern "C" fn dispatch_syscall(
|
||||
),
|
||||
SYS_ARCH_PRCTL => do_arch_prctl(arg0 as u32, arg1 as *mut usize),
|
||||
SYS_SET_TID_ADDRESS => do_set_tid_address(arg0 as *mut pid_t),
|
||||
SYS_SCHED_GETAFFINITY => do_sched_getaffinity(arg0 as pid_t, arg1 as size_t, arg2 as *mut c_uchar),
|
||||
SYS_SCHED_SETAFFINITY => do_sched_setaffinity(arg0 as pid_t, arg1 as size_t, arg2 as *const c_uchar),
|
||||
SYS_SCHED_GETAFFINITY => {
|
||||
do_sched_getaffinity(arg0 as pid_t, arg1 as size_t, arg2 as *mut c_uchar)
|
||||
}
|
||||
SYS_SCHED_SETAFFINITY => {
|
||||
do_sched_setaffinity(arg0 as pid_t, arg1 as size_t, arg2 as *const c_uchar)
|
||||
}
|
||||
|
||||
// memory
|
||||
SYS_MMAP => do_mmap(
|
||||
@ -803,7 +807,6 @@ fn do_clock_gettime(clockid: clockid_t, ts_u: *mut timespec_t) -> Result<isize,
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
|
||||
// FIXME: use this
|
||||
const MAP_FAILED: *const c_void = ((-1) as i64) as *const c_void;
|
||||
|
||||
@ -962,7 +965,7 @@ fn do_set_tid_address(tidptr: *mut pid_t) -> Result<isize, Error> {
|
||||
process::do_set_tid_address(tidptr).map(|tid| tid as isize)
|
||||
}
|
||||
|
||||
fn do_sched_getaffinity(pid: pid_t, cpusize: size_t, buf: *mut c_uchar) -> Result<isize, Error> {
|
||||
fn do_sched_getaffinity(pid: pid_t, cpusize: size_t, buf: *mut c_uchar) -> Result<isize, Error> {
|
||||
// Construct safe Rust types
|
||||
let mut buf_slice = {
|
||||
check_mut_array(buf, cpusize)?;
|
||||
@ -983,7 +986,7 @@ fn do_sched_getaffinity(pid: pid_t, cpusize: size_t, buf: *mut c_uchar) -> Resu
|
||||
Ok(ret as isize)
|
||||
}
|
||||
|
||||
fn do_sched_setaffinity(pid: pid_t, cpusize: size_t, buf: *const c_uchar) -> Result<isize, Error> {
|
||||
fn do_sched_setaffinity(pid: pid_t, cpusize: size_t, buf: *const c_uchar) -> Result<isize, Error> {
|
||||
// Convert unsafe C types into safe Rust types
|
||||
let cpuset = {
|
||||
check_array(buf, cpusize)?;
|
||||
|
@ -35,7 +35,6 @@ extern "C" {
|
||||
fn ocall_gettimeofday(sec: *mut time_t, usec: *mut suseconds_t) -> sgx_status_t;
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
@ -50,14 +49,14 @@ pub type clockid_t = i32;
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum ClockID {
|
||||
CLOCK_REALTIME = 0,
|
||||
CLOCK_MONOTONIC = 1,
|
||||
CLOCK_REALTIME = 0,
|
||||
CLOCK_MONOTONIC = 1,
|
||||
CLOCK_PROCESS_CPUTIME_ID = 2,
|
||||
CLOCK_THREAD_CPUTIME_ID = 3,
|
||||
CLOCK_MONOTONIC_RAW = 4,
|
||||
CLOCK_REALTIME_COARSE = 5,
|
||||
CLOCK_MONOTONIC_COARSE = 6,
|
||||
CLOCK_BOOTTIME = 7,
|
||||
CLOCK_THREAD_CPUTIME_ID = 3,
|
||||
CLOCK_MONOTONIC_RAW = 4,
|
||||
CLOCK_REALTIME_COARSE = 5,
|
||||
CLOCK_MONOTONIC_COARSE = 6,
|
||||
CLOCK_BOOTTIME = 7,
|
||||
}
|
||||
|
||||
impl ClockID {
|
||||
@ -81,7 +80,11 @@ pub fn do_clock_gettime(clockid: ClockID) -> Result<timespec_t, Error> {
|
||||
let mut sec = 0;
|
||||
let mut nsec = 0;
|
||||
unsafe {
|
||||
ocall_clock_gettime(clockid as clockid_t, &mut sec as *mut time_t, &mut nsec as *mut i64);
|
||||
ocall_clock_gettime(
|
||||
clockid as clockid_t,
|
||||
&mut sec as *mut time_t,
|
||||
&mut nsec as *mut i64,
|
||||
);
|
||||
}
|
||||
Ok(timespec_t { sec, nsec })
|
||||
}
|
||||
@ -90,7 +93,6 @@ extern "C" {
|
||||
fn ocall_clock_gettime(clockid: clockid_t, sec: *mut time_t, ns: *mut i64) -> sgx_status_t;
|
||||
}
|
||||
|
||||
|
||||
// For SEFS
|
||||
|
||||
pub struct OcclumTimeProvider;
|
||||
|
@ -1,14 +1,14 @@
|
||||
use fs::{File, FileDesc, FileRef};
|
||||
use prelude::*;
|
||||
use process::{get_current, Process, ProcessRef};
|
||||
use fs::{FileDesc, FileRef, File};
|
||||
use std::fmt;
|
||||
|
||||
mod vm_manager;
|
||||
mod user_space_vm;
|
||||
mod process_vm;
|
||||
mod user_space_vm;
|
||||
mod vm_manager;
|
||||
|
||||
pub use self::process_vm::{ProcessVM, ProcessVMBuilder, MMapFlags, VMPerms};
|
||||
pub use self::vm_manager::{VMRange};
|
||||
pub use self::process_vm::{MMapFlags, ProcessVM, ProcessVMBuilder, VMPerms};
|
||||
pub use self::vm_manager::VMRange;
|
||||
|
||||
pub fn do_mmap(
|
||||
addr: usize,
|
||||
|
@ -1,10 +1,11 @@
|
||||
use super::*;
|
||||
use super::vm_manager::{VMRange, VMManager, VMMapOptionsBuilder, VMMapOptions, VMMapAddr, VMInitializer};
|
||||
use super::user_space_vm::{UserSpaceVMManager, UserSpaceVMRange, USER_SPACE_VM_MANAGER};
|
||||
use super::super::config;
|
||||
use super::user_space_vm::{UserSpaceVMManager, UserSpaceVMRange, USER_SPACE_VM_MANAGER};
|
||||
use super::vm_manager::{
|
||||
VMInitializer, VMManager, VMMapAddr, VMMapOptions, VMMapOptionsBuilder, VMRange,
|
||||
};
|
||||
use super::*;
|
||||
use std::slice;
|
||||
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ProcessVMBuilder {
|
||||
code_size: usize,
|
||||
@ -47,17 +48,23 @@ impl ProcessVMBuilder {
|
||||
let data_size = self.data_size;
|
||||
let ldso_code_size = self.ldso_code_size.unwrap_or(0);
|
||||
let ldso_data_size = self.ldso_data_size.unwrap_or(0);
|
||||
let heap_size = self.heap_size.unwrap_or(
|
||||
config::LIBOS_CONFIG.process.default_heap_size);
|
||||
let stack_size = self.stack_size.unwrap_or(
|
||||
config::LIBOS_CONFIG.process.default_stack_size);
|
||||
let mmap_size = self.mmap_size.unwrap_or(
|
||||
config::LIBOS_CONFIG.process.default_mmap_size);
|
||||
let heap_size = self
|
||||
.heap_size
|
||||
.unwrap_or(config::LIBOS_CONFIG.process.default_heap_size);
|
||||
let stack_size = self
|
||||
.stack_size
|
||||
.unwrap_or(config::LIBOS_CONFIG.process.default_stack_size);
|
||||
let mmap_size = self
|
||||
.mmap_size
|
||||
.unwrap_or(config::LIBOS_CONFIG.process.default_mmap_size);
|
||||
let range_sizes = vec![
|
||||
code_size, data_size,
|
||||
ldso_code_size, ldso_data_size,
|
||||
heap_size, stack_size,
|
||||
mmap_size
|
||||
code_size,
|
||||
data_size,
|
||||
ldso_code_size,
|
||||
ldso_data_size,
|
||||
heap_size,
|
||||
stack_size,
|
||||
mmap_size,
|
||||
];
|
||||
|
||||
let process_range = {
|
||||
@ -109,7 +116,6 @@ impl ProcessVMBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// The per-process virtual memory
|
||||
#[derive(Debug)]
|
||||
pub struct ProcessVM {
|
||||
@ -212,7 +218,7 @@ impl ProcessVM {
|
||||
perms: VMPerms,
|
||||
flags: MMapFlags,
|
||||
fd: FileDesc,
|
||||
offset: usize
|
||||
offset: usize,
|
||||
) -> Result<usize, Error> {
|
||||
let addr_option = {
|
||||
if flags.contains(MMapFlags::MAP_FIXED) {
|
||||
@ -235,7 +241,10 @@ impl ProcessVM {
|
||||
let current_ref = get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
let file_ref = current_process.get_files().lock().unwrap().get(fd)?;
|
||||
VMInitializer::LoadFromFile { file: file_ref, offset: offset }
|
||||
VMInitializer::LoadFromFile {
|
||||
file: file_ref,
|
||||
offset: offset,
|
||||
}
|
||||
}
|
||||
};
|
||||
let mmap_options = VMMapOptionsBuilder::default()
|
||||
@ -256,7 +265,6 @@ impl ProcessVM {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bitflags! {
|
||||
pub struct MMapFlags : u32 {
|
||||
const MAP_FILE = 0x0;
|
||||
@ -283,12 +291,10 @@ bitflags! {
|
||||
impl MMapFlags {
|
||||
pub fn from_u32(bits: u32) -> Result<MMapFlags, Error> {
|
||||
// TODO: detect non-supporting flags
|
||||
MMapFlags::from_bits(bits)
|
||||
.ok_or_else(|| (Errno::EINVAL, "Unknown mmap flags").into())
|
||||
MMapFlags::from_bits(bits).ok_or_else(|| (Errno::EINVAL, "Unknown mmap flags").into())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bitflags! {
|
||||
pub struct VMPerms : u32 {
|
||||
const READ = 0x1;
|
||||
@ -311,12 +317,10 @@ impl VMPerms {
|
||||
}
|
||||
|
||||
pub fn from_u32(bits: u32) -> Result<VMPerms, Error> {
|
||||
VMPerms::from_bits(bits)
|
||||
.ok_or_else(|| (Errno::EINVAL, "Unknown permission bits").into())
|
||||
VMPerms::from_bits(bits).ok_or_else(|| (Errno::EINVAL, "Unknown permission bits").into())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsafe fn fill_zeros(addr: usize, size: usize) {
|
||||
let ptr = addr as *mut u8;
|
||||
let buf = slice::from_raw_parts_mut(ptr, size);
|
||||
@ -324,4 +328,3 @@ unsafe fn fill_zeros(addr: usize, size: usize) {
|
||||
*b = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::vm_manager::{VMManager, VMMapOptions, VMMapOptionsBuilder, VMRange};
|
||||
use super::*;
|
||||
use super::vm_manager::{VMRange, VMManager, VMMapOptionsBuilder, VMMapOptions};
|
||||
|
||||
/// The virtual memory manager for the entire user space
|
||||
#[derive(Debug)]
|
||||
@ -10,28 +10,25 @@ pub struct UserSpaceVMManager {
|
||||
impl UserSpaceVMManager {
|
||||
pub unsafe fn from(addr: usize, size: usize) -> Result<UserSpaceVMManager, Error> {
|
||||
let vm_manager = Arc::new(SgxMutex::new(VMManager::from(addr, size)?));
|
||||
Ok(UserSpaceVMManager {
|
||||
vm_manager,
|
||||
})
|
||||
Ok(UserSpaceVMManager { vm_manager })
|
||||
}
|
||||
|
||||
pub fn alloc(&self, size: usize) -> Result<UserSpaceVMRange, Error> {
|
||||
let user_vm_range = unsafe {
|
||||
let mmap_options = VMMapOptionsBuilder::default()
|
||||
.size(size)
|
||||
.build()?;
|
||||
let mmap_options = VMMapOptionsBuilder::default().size(size).build()?;
|
||||
|
||||
let mut vm_manager = self.vm_manager.lock().unwrap();
|
||||
let user_vm_addr = vm_manager.mmap(&mmap_options)?;
|
||||
VMRange::from_unchecked(user_vm_addr, user_vm_addr + size)
|
||||
};
|
||||
Ok(UserSpaceVMRange::new(user_vm_range, self.vm_manager.clone()))
|
||||
Ok(UserSpaceVMRange::new(
|
||||
user_vm_range,
|
||||
self.vm_manager.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn alloc_dummy(&self) -> UserSpaceVMRange {
|
||||
let empty_user_vm_range = unsafe {
|
||||
VMRange::from_unchecked(0, 0)
|
||||
};
|
||||
let empty_user_vm_range = unsafe { VMRange::from_unchecked(0, 0) };
|
||||
UserSpaceVMRange::new(empty_user_vm_range, self.vm_manager.clone())
|
||||
}
|
||||
}
|
||||
@ -58,7 +55,6 @@ extern "C" {
|
||||
pub fn vm_get_preallocated_user_space_memory(addr: &mut usize, size: &mut usize);
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UserSpaceVMRange {
|
||||
vm_range: VMRange,
|
||||
@ -82,8 +78,12 @@ impl Drop for UserSpaceVMRange {
|
||||
fn drop(&mut self) {
|
||||
let addr = self.vm_range.start();
|
||||
let size = self.vm_range.size();
|
||||
if size == 0 { return; }
|
||||
if size == 0 {
|
||||
return;
|
||||
}
|
||||
let mut vm_manager = self.vm_manager.lock().unwrap();
|
||||
vm_manager.munmap(addr, size).expect("munmap should always succeed");
|
||||
vm_manager
|
||||
.munmap(addr, size)
|
||||
.expect("munmap should always succeed");
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::*;
|
||||
use std::{slice};
|
||||
use std::slice;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum VMInitializer {
|
||||
@ -19,12 +19,12 @@ impl VMInitializer {
|
||||
match self {
|
||||
VMInitializer::DoNothing() => {
|
||||
// Do nothing
|
||||
},
|
||||
}
|
||||
VMInitializer::FillZeros() => {
|
||||
for b in buf {
|
||||
*b = 0;
|
||||
}
|
||||
},
|
||||
}
|
||||
VMInitializer::LoadFromFile { file, offset } => {
|
||||
// TODO: make sure that read_at does not move file cursor
|
||||
let len = file.read_at(*offset, buf)?;
|
||||
@ -37,12 +37,11 @@ impl VMInitializer {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum VMMapAddr {
|
||||
Any, // Free to choose any address
|
||||
Hint(usize), // Prefer the given address
|
||||
Fixed(usize), // Must be the given address
|
||||
Any, // Free to choose any address
|
||||
Hint(usize), // Prefer the given address
|
||||
Fixed(usize), // Must be the given address
|
||||
}
|
||||
|
||||
impl Default for VMMapAddr {
|
||||
@ -51,21 +50,22 @@ impl Default for VMMapAddr {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Builder, Debug, Default)]
|
||||
#[builder(build_fn(skip), no_std)]
|
||||
pub struct VMMapOptions {
|
||||
size: usize,
|
||||
align: usize,
|
||||
addr: VMMapAddr,
|
||||
initializer: VMInitializer
|
||||
initializer: VMInitializer,
|
||||
}
|
||||
|
||||
// VMMapOptionsBuilder is generated automatically, except the build function
|
||||
impl VMMapOptionsBuilder {
|
||||
pub fn build(&self) -> Result<VMMapOptions, Error> {
|
||||
let size = {
|
||||
let size = self.size.ok_or_else(|| (Errno::EINVAL, "Invalid size for mmap"))?;
|
||||
let size = self
|
||||
.size
|
||||
.ok_or_else(|| (Errno::EINVAL, "Invalid size for mmap"))?;
|
||||
if size == 0 {
|
||||
return errno!(EINVAL, "Invalid size for mmap");
|
||||
}
|
||||
@ -82,9 +82,7 @@ impl VMMapOptionsBuilder {
|
||||
let addr = self.addr.unwrap_or_default();
|
||||
match addr {
|
||||
// TODO: check addr + size overflow
|
||||
VMMapAddr::Any => {
|
||||
VMMapAddr::Any
|
||||
}
|
||||
VMMapAddr::Any => VMMapAddr::Any,
|
||||
VMMapAddr::Hint(addr) => {
|
||||
let addr = align_down(addr, PAGE_SIZE);
|
||||
VMMapAddr::Hint(addr)
|
||||
@ -98,8 +96,8 @@ impl VMMapOptionsBuilder {
|
||||
}
|
||||
};
|
||||
let initializer = match self.initializer.as_ref() {
|
||||
Some(initializer) => { initializer.clone() }
|
||||
None => { VMInitializer::default() }
|
||||
Some(initializer) => initializer.clone(),
|
||||
None => VMInitializer::default(),
|
||||
};
|
||||
Ok(VMMapOptions {
|
||||
size,
|
||||
@ -124,7 +122,6 @@ impl VMMapOptions {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct VMManager {
|
||||
range: VMRange,
|
||||
@ -141,20 +138,14 @@ impl VMManager {
|
||||
let end_sentry = VMRange::from(end, end)?;
|
||||
vec![start_sentry, end_sentry]
|
||||
};
|
||||
Ok(VMManager {
|
||||
range,
|
||||
sub_ranges,
|
||||
})
|
||||
Ok(VMManager { range, sub_ranges })
|
||||
}
|
||||
|
||||
pub fn range(&self) -> &VMRange {
|
||||
&self.range
|
||||
}
|
||||
|
||||
pub fn mmap(
|
||||
&mut self,
|
||||
options: &VMMapOptions,
|
||||
) -> Result<usize, Error> {
|
||||
pub fn mmap(&mut self, options: &VMMapOptions) -> Result<usize, Error> {
|
||||
// TODO: respect options.align when mmap
|
||||
let addr = *options.addr();
|
||||
let size = *options.size();
|
||||
@ -194,22 +185,24 @@ impl VMManager {
|
||||
|
||||
let effective_munmap_range_opt = munmap_range.intersect(&self.range);
|
||||
if effective_munmap_range_opt.is_none() {
|
||||
return Ok(())
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let effective_munmap_range = effective_munmap_range_opt.unwrap();
|
||||
if effective_munmap_range.empty() {
|
||||
return Ok(())
|
||||
return Ok(());
|
||||
}
|
||||
effective_munmap_range
|
||||
};
|
||||
|
||||
let new_sub_ranges = self.sub_ranges
|
||||
let new_sub_ranges = self
|
||||
.sub_ranges
|
||||
.iter()
|
||||
.flat_map(|subrange| {
|
||||
if subrange.size() > 0 {
|
||||
subrange.subtract(&munmap_range)
|
||||
} else { // Keep the two sentry subranges intact
|
||||
} else {
|
||||
// Keep the two sentry subranges intact
|
||||
vec![*subrange]
|
||||
}
|
||||
})
|
||||
@ -219,17 +212,20 @@ impl VMManager {
|
||||
}
|
||||
|
||||
pub fn find_mmap_region(&self, addr: usize) -> Result<&VMRange, Error> {
|
||||
self.sub_ranges.iter()
|
||||
self.sub_ranges
|
||||
.iter()
|
||||
.find(|subrange| subrange.contains(addr))
|
||||
.ok_or(Error::new(Errno::ESRCH,
|
||||
"no mmap regions that contains the address"))
|
||||
.ok_or(Error::new(
|
||||
Errno::ESRCH,
|
||||
"no mmap regions that contains the address",
|
||||
))
|
||||
}
|
||||
|
||||
// Find the free subrange that satisfies the constraints of size and address
|
||||
fn find_free_subrange(
|
||||
&mut self,
|
||||
size: usize,
|
||||
addr: VMMapAddr
|
||||
addr: VMMapAddr,
|
||||
) -> Result<(usize, VMRange), Error> {
|
||||
// TODO: reduce the complexity from O(N) to O(log(N)), where N is
|
||||
// the number of existing subranges.
|
||||
@ -253,9 +249,7 @@ impl VMManager {
|
||||
continue;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
VMRange::from_unchecked(free_range_start, free_range_end)
|
||||
}
|
||||
unsafe { VMRange::from_unchecked(free_range_start, free_range_end) }
|
||||
};
|
||||
|
||||
match addr {
|
||||
@ -289,7 +283,8 @@ impl VMManager {
|
||||
}
|
||||
|
||||
if result_free_range == None
|
||||
|| result_free_range.as_ref().unwrap().size() > free_range.size() {
|
||||
|| result_free_range.as_ref().unwrap().size() > free_range.size()
|
||||
{
|
||||
result_free_range = Some(free_range);
|
||||
result_idx = Some(idx);
|
||||
}
|
||||
@ -308,7 +303,7 @@ impl VMManager {
|
||||
&self,
|
||||
size: usize,
|
||||
addr: VMMapAddr,
|
||||
free_subrange: &VMRange
|
||||
free_subrange: &VMRange,
|
||||
) -> VMRange {
|
||||
debug_assert!(free_subrange.size() >= size);
|
||||
|
||||
@ -384,19 +379,22 @@ impl VMRange {
|
||||
let other_end = other.end();
|
||||
|
||||
match (self_start < other_start, other_end < self_end) {
|
||||
(false, false) => {
|
||||
Vec::new()
|
||||
}
|
||||
(false, false) => Vec::new(),
|
||||
(false, true) => unsafe {
|
||||
vec![VMRange::from_unchecked(self_start.max(other_end), self_end)]
|
||||
}
|
||||
},
|
||||
(true, false) => unsafe {
|
||||
vec![VMRange::from_unchecked(self_start, self_end.min(other_start))]
|
||||
}
|
||||
vec![VMRange::from_unchecked(
|
||||
self_start,
|
||||
self_end.min(other_start),
|
||||
)]
|
||||
},
|
||||
(true, true) => unsafe {
|
||||
vec![VMRange::from_unchecked(self_start, other_start),
|
||||
VMRange::from_unchecked(other_end, self_end)]
|
||||
}
|
||||
vec![
|
||||
VMRange::from_unchecked(self_start, other_start),
|
||||
VMRange::from_unchecked(other_end, self_end),
|
||||
]
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -407,7 +405,10 @@ impl VMRange {
|
||||
return None;
|
||||
}
|
||||
unsafe {
|
||||
Some(VMRange::from_unchecked(intersection_start, intersection_end))
|
||||
Some(VMRange::from_unchecked(
|
||||
intersection_start,
|
||||
intersection_end,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user