impl SGX app: sefs-fuse

master
WangRunji 6 years ago
parent 946f1e119f
commit 3463196120

@ -1,7 +0,0 @@
[workspace]
members = [
"rcore-fs",
"rcore-fs-sfs",
"rcore-fs-sefs",
"rcore-fs-fuse"
]

@ -3,8 +3,14 @@ name = "app"
version = "1.0.0"
authors = ["Baidu"]
build = "build.rs"
edition = "2018"
[dependencies]
sgx_types = "1.0.6"
sgx_urts = "1.0.6"
dirs = "1.0.2"
fuse = "0.3"
structopt = "0.2"
env_logger = "0.3"
rcore-fs-fuse = { path = "../../rcore-fs-fuse" }
rcore-fs-sefs = { path = "../../rcore-fs-sefs" }

@ -29,6 +29,8 @@
use std::env;
fn main () {
println!("cargo:rerun-if-env-changed=SGX_SDK");
println!("cargo:rerun-if-env-changed=SGX_MODE");
let sdk_dir = env::var("SGX_SDK")
.unwrap_or_else(|_| "/opt/intel/sgxsdk".to_string());

@ -0,0 +1,78 @@
use std::fs;
use std::io::{Read, Write};
use std::path;
use sgx_types::*;
use sgx_urts::SgxEnclave;
static ENCLAVE_FILE: &'static str = "enclave.signed.so";
static ENCLAVE_TOKEN: &'static str = "enclave.token";
pub fn init_enclave() -> SgxResult<SgxEnclave> {
let mut launch_token: sgx_launch_token_t = [0; 1024];
let mut launch_token_updated: i32 = 0;
// Step 1: try to retrieve the launch token saved by last transaction
// if there is no token, then create a new one.
//
// try to get the token saved in $HOME */
let mut home_dir = path::PathBuf::new();
let use_token = match dirs::home_dir() {
Some(path) => {
println!("[+] Home dir is {}", path.display());
home_dir = path;
true
}
None => {
println!("[-] Cannot get home dir");
false
}
};
let token_file: path::PathBuf = home_dir.join(ENCLAVE_TOKEN);
;
if use_token == true {
match fs::File::open(&token_file) {
Err(_) => {
println!("[-] Open token file {} error! Will create one.", token_file.as_path().to_str().unwrap());
}
Ok(mut f) => {
println!("[+] Open token file success! ");
match f.read(&mut launch_token) {
Ok(1024) => {
println!("[+] Token file valid!");
}
_ => println!("[+] Token file invalid, will create new token file"),
}
}
}
}
// Step 2: call sgx_create_enclave to initialize an enclave instance
// Debug Support: set 2nd parameter to 1
let debug = 1;
let mut misc_attr = sgx_misc_attribute_t { secs_attr: sgx_attributes_t { flags: 0, xfrm: 0 }, misc_select: 0 };
let enclave = SgxEnclave::create(ENCLAVE_FILE,
debug,
&mut launch_token,
&mut launch_token_updated,
&mut misc_attr)?;
// Step 3: save the launch token if it is updated
if use_token == true && launch_token_updated != 0 {
// reopen the file with write capablity
match fs::File::create(&token_file) {
Ok(mut f) => {
match f.write_all(&launch_token) {
Ok(()) => println!("[+] Saved updated launch token!"),
Err(_) => println!("[-] Failed to save updated launch token!"),
}
}
Err(_) => {
println!("[-] Failed to save updated enclave token, but doesn't matter");
}
}
}
Ok(enclave)
}

@ -26,96 +26,32 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
extern crate sgx_types;
extern crate sgx_urts;
extern crate dirs;
use std::path::PathBuf;
use sgx_types::*;
use sgx_urts::SgxEnclave;
use structopt::StructOpt;
use std::io::{Read, Write};
use std::fs;
use std::path;
use rcore_fs_fuse::VfsFuse;
use rcore_fs_sefs as sefs;
static ENCLAVE_FILE: &'static str = "enclave.signed.so";
static ENCLAVE_TOKEN: &'static str = "enclave.token";
mod sgx_dev;
mod enclave;
extern {
fn say_something(eid: sgx_enclave_id_t, retval: *mut sgx_status_t,
some_string: *const u8, len: usize) -> sgx_status_t;
}
fn init_enclave() -> SgxResult<SgxEnclave> {
let mut launch_token: sgx_launch_token_t = [0; 1024];
let mut launch_token_updated: i32 = 0;
// Step 1: try to retrieve the launch token saved by last transaction
// if there is no token, then create a new one.
//
// try to get the token saved in $HOME */
let mut home_dir = path::PathBuf::new();
let use_token = match dirs::home_dir() {
Some(path) => {
println!("[+] Home dir is {}", path.display());
home_dir = path;
true
},
None => {
println!("[-] Cannot get home dir");
false
}
};
let token_file: path::PathBuf = home_dir.join(ENCLAVE_TOKEN);;
if use_token == true {
match fs::File::open(&token_file) {
Err(_) => {
println!("[-] Open token file {} error! Will create one.", token_file.as_path().to_str().unwrap());
},
Ok(mut f) => {
println!("[+] Open token file success! ");
match f.read(&mut launch_token) {
Ok(1024) => {
println!("[+] Token file valid!");
},
_ => println!("[+] Token file invalid, will create new token file"),
}
}
}
}
// Step 2: call sgx_create_enclave to initialize an enclave instance
// Debug Support: set 2nd parameter to 1
let debug = 1;
let mut misc_attr = sgx_misc_attribute_t {secs_attr: sgx_attributes_t { flags:0, xfrm:0}, misc_select:0};
let enclave = try!(SgxEnclave::create(ENCLAVE_FILE,
debug,
&mut launch_token,
&mut launch_token_updated,
&mut misc_attr));
// Step 3: save the launch token if it is updated
if use_token == true && launch_token_updated != 0 {
// reopen the file with write capablity
match fs::File::create(&token_file) {
Ok(mut f) => {
match f.write_all(&launch_token) {
Ok(()) => println!("[+] Saved updated launch token!"),
Err(_) => println!("[-] Failed to save updated launch token!"),
}
},
Err(_) => {
println!("[-] Failed to save updated enclave token, but doesn't matter");
},
}
}
Ok(enclave)
#[derive(Debug, StructOpt)]
struct Opt {
/// Image file
#[structopt(parse(from_os_str))]
image: PathBuf,
/// Mount point
#[structopt(parse(from_os_str))]
mount_point: PathBuf,
}
fn main() {
env_logger::init().unwrap();
let opt = Opt::from_args();
let enclave = match init_enclave() {
let enclave = match enclave::init_enclave() {
Ok(r) => {
println!("[+] Init Enclave Successful {}!", r.geteid());
r
@ -126,26 +62,16 @@ fn main() {
},
};
let input_string = String::from("This is a normal world string passed into Enclave!\n");
let mut retval = sgx_status_t::SGX_SUCCESS;
let result = unsafe {
say_something(enclave.geteid(),
&mut retval,
input_string.as_ptr() as * const u8,
input_string.len())
let sfs = if opt.image.is_dir() {
let img = sgx_dev::SgxStorage::new(enclave.geteid(), &opt.image);
sefs::SEFS::open(Box::new(img))
.expect("failed to open sefs")
} else {
std::fs::create_dir_all(&opt.image).unwrap();
let img = sgx_dev::SgxStorage::new(enclave.geteid(), &opt.image);
sefs::SEFS::create(Box::new(img))
.expect("failed to create sefs")
};
match result {
sgx_status_t::SGX_SUCCESS => {},
_ => {
println!("[-] ECALL Enclave Failed {}!", result.as_str());
return;
}
}
println!("[+] say_something success...");
enclave.destroy();
fuse::mount(VfsFuse::new(sfs), &opt.mount_point, &[])
.expect("failed to mount fs");
}

@ -0,0 +1,162 @@
use sgx_types::*;
use rcore_fs_sefs::dev::{File, Storage, DevResult, DeviceError};
use std::path::*;
use std::fs::remove_file;
pub struct SgxStorage {
path: PathBuf,
}
impl SgxStorage {
pub fn new(eid: sgx_enclave_id_t, path: impl AsRef<Path>) -> Self {
unsafe { EID = eid; }
let path_str = path.as_ref().to_str().unwrap();
let ret = set_sefs_dir(path_str);
assert_eq!(ret, 0);
SgxStorage { path: path.as_ref().to_path_buf() }
}
}
impl Storage for SgxStorage {
fn open(&self, file_id: usize) -> DevResult<Box<File>> {
match file_open(file_id) {
0 => Ok(Box::new(SgxFile { fd: file_id })),
_ => panic!(),
}
}
fn create(&self, file_id: usize) -> DevResult<Box<File>> {
match file_open(file_id) {
0 => Ok(Box::new(SgxFile { fd: file_id })),
_ => panic!(),
}
}
fn remove(&self, file_id: usize) -> DevResult<()> {
let mut path = self.path.to_path_buf();
path.push(format!("{}", file_id));
match remove_file(path) {
Ok(_) => Ok(()),
Err(_) => panic!(),
}
}
}
pub struct SgxFile {
fd: usize,
}
impl File for SgxFile {
fn read_at(&self, buf: &mut [u8], offset: usize) -> DevResult<usize> {
match file_read_at(self.fd, offset, buf) {
size if size > 0 => Ok(size as usize),
e => panic!("read_at {}", e),
}
}
fn write_at(&self, buf: &[u8], offset: usize) -> DevResult<usize> {
match file_write_at(self.fd, offset, buf) {
size if size > 0 => Ok(size as usize),
_ => panic!(),
}
}
fn set_len(&self, len: usize) -> DevResult<()> {
match file_set_len(self.fd, len) {
0 => Ok(()),
_ => panic!(),
}
}
fn flush(&self) -> DevResult<()> {
match file_flush(self.fd) {
0 => Ok(()),
_ => panic!(),
}
}
}
impl Drop for SgxFile {
fn drop(&mut self) {
let _ = file_close(self.fd);
}
}
/// Ecall functions to access SgxFile
extern {
fn ecall_set_sefs_dir(eid: sgx_enclave_id_t, retval: *mut i32, path: *const u8, len: size_t) -> sgx_status_t;
fn ecall_file_open(eid: sgx_enclave_id_t, retval: *mut i32, fd: size_t) -> sgx_status_t;
fn ecall_file_close(eid: sgx_enclave_id_t, retval: *mut i32, fd: size_t) -> sgx_status_t;
fn ecall_file_flush(eid: sgx_enclave_id_t, retval: *mut i32, fd: size_t) -> sgx_status_t;
fn ecall_file_read_at(eid: sgx_enclave_id_t, retval: *mut i32, fd: size_t, offset: size_t, buf: *mut uint8_t, len: size_t) -> sgx_status_t;
fn ecall_file_write_at(eid: sgx_enclave_id_t, retval: *mut i32, fd: size_t, offset: size_t, buf: *const uint8_t, len: size_t) -> sgx_status_t;
fn ecall_file_set_len(eid: sgx_enclave_id_t, retval: *mut i32, fd: size_t, len: size_t) -> sgx_status_t;
}
/// Must be set when init enclave
static mut EID: sgx_enclave_id_t = 0;
fn set_sefs_dir(path: &str) -> i32 {
let mut ret_val = -1;
unsafe {
let ret = ecall_set_sefs_dir(EID, &mut ret_val, path.as_ptr(), path.len());
assert_eq!(ret, sgx_status_t::SGX_SUCCESS);
}
ret_val
}
fn file_open(fd: usize) -> i32 {
let mut ret_val = -1;
unsafe {
let ret = ecall_file_open(EID, &mut ret_val, fd);
assert_eq!(ret, sgx_status_t::SGX_SUCCESS);
}
ret_val
}
fn file_close(fd: usize) -> i32 {
let mut ret_val = -1;
unsafe {
let ret = ecall_file_close(EID, &mut ret_val, fd);
assert_eq!(ret, sgx_status_t::SGX_SUCCESS);
}
ret_val
}
fn file_flush(fd: usize) -> i32 {
let mut ret_val = -1;
unsafe {
let ret = ecall_file_flush(EID, &mut ret_val, fd);
assert_eq!(ret, sgx_status_t::SGX_SUCCESS);
}
ret_val
}
fn file_read_at(fd: usize, offset: usize, buf: &mut [u8]) -> i32 {
let mut ret_val = -1;
unsafe {
let ret = ecall_file_read_at(EID, &mut ret_val, fd, offset, buf.as_mut_ptr(), buf.len());
assert_eq!(ret, sgx_status_t::SGX_SUCCESS);
}
ret_val
}
fn file_write_at(fd: usize, offset: usize, buf: &[u8]) -> i32 {
let mut ret_val = -1;
unsafe {
let ret = ecall_file_write_at(EID, &mut ret_val, fd, offset, buf.as_ptr(), buf.len());
assert_eq!(ret, sgx_status_t::SGX_SUCCESS);
}
ret_val
}
fn file_set_len(fd: usize, len: usize) -> i32 {
let mut ret_val = -1;
unsafe {
let ret = ecall_file_set_len(EID, &mut ret_val, fd, len);
assert_eq!(ret, sgx_status_t::SGX_SUCCESS);
}
ret_val
}

@ -10,6 +10,9 @@ crate-type = ["staticlib"]
[features]
default = []
[dependencies]
lazy_static = { version = "1.1.0", features = ["spin_no_std"] } # Implies nightly
[target.'cfg(not(target_env = "sgx"))'.dependencies]
sgx_types = { path = "../../../rust-sgx-sdk/sgx_types" }
sgx_tstd = { path = "../../../rust-sgx-sdk/sgx_tstd" }
sgx_types = "1.0.6"
sgx_tstd = "1.0.6"

@ -39,6 +39,12 @@ enclave {
trusted {
/* define ECALLs here. */
public sgx_status_t say_something([in, size=len] const uint8_t* some_string, size_t len);
public int ecall_set_sefs_dir([in, size=len] const char* path, size_t len);
public int ecall_file_open(size_t fd);
public int ecall_file_close(size_t fd);
public int ecall_file_flush(size_t fd);
public int ecall_file_read_at(size_t fd, size_t offset, [out, size=len] uint8_t* buf, size_t len);
public int ecall_file_write_at(size_t fd, size_t offset, [in, size=len] const uint8_t* buf, size_t len);
public int ecall_file_set_len(size_t fd, size_t len);
};
};

@ -32,26 +32,137 @@
#![cfg_attr(not(target_env = "sgx"), no_std)]
#![cfg_attr(target_env = "sgx", feature(rustc_private))]
extern crate sgx_types;
#[macro_use]
extern crate lazy_static;
#[cfg(not(target_env = "sgx"))]
#[macro_use]
extern crate sgx_tstd as std;
extern crate sgx_types;
use sgx_types::*;
use std::string::String;
use std::collections::BTreeMap;
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::PathBuf;
use std::sgxfs::{OpenOptions, SgxFile};
use std::sync::{SgxMutex as Mutex, SgxRwLock as RwLock};
use std::untrusted::path::PathEx;
use std::vec::Vec;
use std::io::{self, Write};
use std::slice;
use std::sgxfs::SgxFile;
#[no_mangle]
pub extern "C" fn say_something(some_string: *const u8, some_len: usize) -> sgx_status_t {
pub extern "C" fn ecall_set_sefs_dir(path: *const u8, len: usize) -> i32 {
unsafe {
assert!(PATH.is_none());
let path = std::slice::from_raw_parts(path, len);
let path = std::str::from_utf8(path).unwrap();
let path = PathBuf::from(path);
PATH = Some(path);
0
}
}
#[no_mangle]
pub extern "C" fn ecall_file_open(fd: usize) -> i32 {
let path = get_path(fd);
let file = match OpenOptions::new().append(true).update(true).open(&path) {
Ok(f) => f,
Err(e) => { println!("open err {}", e); panic!() }
};
let file = LockedFile(Mutex::new(file));
let mut files = FILES.write().unwrap();
files.insert(fd, file);
0
}
#[no_mangle]
pub extern "C" fn ecall_file_close(fd: usize) -> i32 {
let mut files = FILES.write().unwrap();
files.remove(&fd);
0
}
#[no_mangle]
pub extern "C" fn ecall_file_flush(fd: usize) -> i32 {
let files = FILES.read().unwrap();
let mut file = files[&fd].0.lock().unwrap();
match file.flush() {
Ok(_) => 0,
Err(_) => -1,
}
}
#[no_mangle]
pub extern "C" fn ecall_file_read_at(fd: usize, offset: usize, buf: *mut u8, len: usize) -> i32 {
let files = FILES.read().unwrap();
let mut file = files[&fd].0.lock().unwrap();
println!("read_at fd = {}, offset = {}, len = {}", fd, offset, len);
let offset = offset as u64;
match file.seek(SeekFrom::Start(offset)) {
Ok(real_offset) if real_offset == offset => {},
_ => return -1,
}
let buf = unsafe { std::slice::from_raw_parts_mut(buf, len) };
match file.read(buf) {
Ok(len) => len as i32,
Err(e) => {println!("read_at fail {}", e); -2},
}
}
#[no_mangle]
pub extern "C" fn ecall_file_write_at(fd: usize, offset: usize, buf: *const u8, len: usize) -> i32 {
let files = FILES.read().unwrap();
let mut file = files[&fd].0.lock().unwrap();
let offset = offset as u64;
println!("write_at fd = {}, offset = {}, len = {}", fd, offset, len);
match file.seek(SeekFrom::Start(offset)) {
Ok(real_offset) if real_offset == offset => {},
_ => return -1,
}
let buf = unsafe { std::slice::from_raw_parts(buf, len) };
match file.write(buf) {
Ok(len) => len as i32,
Err(_) => return -2,
}
}
#[no_mangle]
pub extern "C" fn ecall_file_set_len(fd: usize, len: usize) -> i32 {
let files = FILES.read().unwrap();
let mut file = files[&fd].0.lock().unwrap();
println!("set_len fd = {}, len = {}", fd, len);
let current_len = match file.seek(SeekFrom::End(0)) {
Ok(len) => len as usize,
Err(_) => return -1,
};
if current_len < len {
let mut zeros = Vec::<u8>::new();
zeros.resize(len - current_len, 0);
match file.write(zeros.as_slice()) {
Ok(_) => {}
Err(_) => return -2,
}
}
// TODO: how to shrink a file?
0
}
static mut PATH: Option<PathBuf> = None;
lazy_static! {
static ref FILES: RwLock<BTreeMap<usize, LockedFile>> = RwLock::new(BTreeMap::new());
}
let mut file = SgxFile::create("test").unwrap();
file.write(b"hello").unwrap();
struct LockedFile(Mutex<SgxFile>);
// Ocall to normal world for output
println!("{}", "hello");
// `sgx_tstd::sgxfs::SgxFile` not impl Send ...
unsafe impl Send for LockedFile {}
unsafe impl Sync for LockedFile {}
sgx_status_t::SGX_SUCCESS
/// Get file path of `fd`.
///
/// `ecall_set_sefs_dir` must be called first, or this will panic.
fn get_path(fd: usize) -> PathBuf {
let mut path = unsafe { PATH.as_ref().unwrap().clone() };
path.push(format!("{}", fd));
path
}

@ -445,6 +445,7 @@ impl SEFS {
bitset
};
let meta_file = device.create(0)?;
meta_file.set_len(blocks * BLKSIZE)?;
let sefs = SEFS {
super_block: RwLock::new(Dirty::new_dirty(super_block)),

Loading…
Cancel
Save