From a66c55f95ff094d11b8a76e7ae6c30674c7723e7 Mon Sep 17 00:00:00 2001 From: "Tate, Hongliang Tian" Date: Fri, 5 Oct 2018 16:41:25 +0800 Subject: [PATCH] Add open, read, write and close --- src/libos/src/elf_helper.rs | 66 ++++++++----- src/libos/src/errno.rs | 72 ++++++++++---- src/libos/src/file.rs | 177 ++++++++++++++++++++++++++++++++++ src/libos/src/file_table.rs | 81 ++++++++++++++++ src/libos/src/fs.rs | 74 ++++++++++++++ src/libos/src/lib.rs | 15 +-- src/libos/src/mm.rs | 13 +-- src/libos/src/prelude.rs | 18 ++++ src/libos/src/process.rs | 133 +++++++++++++++---------- src/libos/src/syscall.h | 3 + src/libos/src/syscall.rs | 106 ++++++++++++++------ src/libos/src/syscall_entry.c | 19 ++++ src/libos/src/vma.rs | 36 ++++--- test/Makefile | 2 +- test/file_io/Makefile | 4 + test/file_io/main.c | 66 +++++++++++++ test/include/rusgx_stub.h | 34 +++++++ test/rusgx_stub/stub_impl.c | 41 ++++++++ 18 files changed, 805 insertions(+), 155 deletions(-) create mode 100644 src/libos/src/file.rs create mode 100644 src/libos/src/file_table.rs create mode 100644 src/libos/src/fs.rs create mode 100644 src/libos/src/prelude.rs create mode 100644 test/file_io/Makefile create mode 100644 test/file_io/main.c diff --git a/src/libos/src/elf_helper.rs b/src/libos/src/elf_helper.rs index efdda0f2..716ed529 100644 --- a/src/libos/src/elf_helper.rs +++ b/src/libos/src/elf_helper.rs @@ -1,34 +1,46 @@ -use xmas_elf::{ElfFile, program, P64}; -use xmas_elf::sections; +use prelude::*; + +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::symbol_table::Entry; -pub fn print_program_headers(elf_file: &ElfFile) -> Result<(), &'static str> { +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)?; + program::sanity_check(sect, &elf_file) + .map_err(|e| (Errno::ENOEXEC, + "Sanity check for program header failed"))?; println!("\t{:?}", sect.get_type()); } Ok(()) } -pub fn print_sections(elf_file: &ElfFile) -> Result<(), &'static str> { +pub fn print_sections(elf_file: &ElfFile) -> Result<(), Error> { println!("Sections:"); let mut sect_iter = elf_file.section_iter(); sect_iter.next(); // Skip the first, dummy section for sect in sect_iter { - sections::sanity_check(sect, &elf_file)?; - println!("\t{}\n{:?}", sect.get_name(&elf_file)?, sect); + 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"))?; + println!("\t{}\n{:?}", sec_name, sect); } Ok(()) } -pub fn print_pltrel_section(elf_file: &ElfFile) -> Result<(), &'static str> { - let rela_entries = get_pltrel_entries(elf_file)?; - let dynsym_entries = get_dynsym_entries(elf_file)?; +pub fn print_pltrel_section(elf_file: &ElfFile) -> Result<(), Error> { + let rela_entries = get_pltrel_entries(elf_file) + .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"))?; println!(".plt.rela section:"); for entry in rela_entries { @@ -40,51 +52,55 @@ pub fn print_pltrel_section(elf_file: &ElfFile) -> Result<(), &'static str> { let symidx = entry.get_symbol_table_index() as usize; let dynsym_entry = &dynsym_entries[symidx]; - println!("\t\t{} = {:?}", - dynsym_entry.get_name(&elf_file)?, dynsym_entry); + 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, &'static str> + -> Result, 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()) - .ok_or("Cannot find .data in the program header of ELF") + .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, &'static str> + -> Result, 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()) - .ok_or("Cannot find .text in the program header of ELF") + .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 + -> Result { let sym_entries = get_sym_entries(elf_file)?; for sym_entry in sym_entries { - let sym_str = sym_entry.get_name(elf_file)?; + 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) } } - Err("Cannot find _start symbol") + 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], &'static str> + -> Result<&'a [Entry64], Error> { elf_file.find_section_by_name(".symtab") .and_then(|symtab_section| { @@ -94,11 +110,11 @@ pub fn get_sym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) sections::SectionData::SymbolTable64(entries) => Some(entries), _ => None, } - }).ok_or("Cannot find or load .dynsym section") + }).ok_or_else(|| (Errno::ENOEXEC, "Failed get the symbol entries").into()) } pub fn get_pltrel_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) - -> Result<&'a [Rela], &'static str> + -> Result<&'a [Rela], Error> { elf_file.find_section_by_name(".rela.plt") .and_then(|plt_rela_section| { @@ -108,11 +124,11 @@ pub fn get_pltrel_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) sections::SectionData::Rela64(entries) => Some(entries), _ => None, } - }).ok_or("Cannot find or load .rela.plt section") + }).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], &'static str> + -> Result<&'a [DynEntry64], Error> { elf_file.find_section_by_name(".dynsym") .and_then(|dynamic_section| { @@ -122,5 +138,5 @@ pub fn get_dynsym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) sections::SectionData::DynSymbolTable64(entries) => Some(entries), _ => None, } - }).ok_or("Cannot find or load .dynsym section") + }).ok_or_else(|| (Errno::ENOEXEC, "Failed to get .dynsym entries").into()) } diff --git a/src/libos/src/errno.rs b/src/libos/src/errno.rs index aeb0b5f8..01a598cc 100644 --- a/src/libos/src/errno.rs +++ b/src/libos/src/errno.rs @@ -1,9 +1,51 @@ -use std; -use std::fmt; +use prelude::*; +use std::{fmt, error, convert,}; #[derive(Clone, Copy, Debug, PartialEq)] -enum Errno { - OK = 0, +pub struct Error { + pub errno: Errno, + pub desc: &'static str, +} + +impl Error { + pub fn new(errno: Errno, desc: &'static str) -> Error { + let ret = Error { + errno, + desc, + }; + println!("{}", ret); + ret + } +} + +impl convert::From<(Errno, &'static str)> for Error { + fn from(info: (Errno, &'static str)) -> Error { + Error::new( + info.0, + info.1, + ) + } +} + +impl error::Error for Error { + fn description(&self) -> &str { + self.desc + } + + fn cause(&self) -> Option<&error::Error> { + None + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Error: {} ({})", self.desc, self.errno) + } +} + +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum Errno { + EUNDEF = 0, EPERM = 1, ENOENT = 2, ESRCH = 3, @@ -44,23 +86,16 @@ enum Errno { } impl Errno { - fn as_retval(&self) -> i32 { - *self as i32 - } -} - -impl Default for Errno { - fn default() -> Errno { - Errno::OK + pub fn as_retval(&self) -> i32 { + - (*self as i32) } } impl fmt::Display for Errno { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} ({})", - *self as i32, + write!(f, "errno = {}, \"{}\"", + *self as u32, match *self { - Errno::OK => "Ok", Errno::EPERM => "Operation not permitted", Errno::ENOENT => "No such file or directory", Errno::ESRCH => "No such process", @@ -98,7 +133,10 @@ impl fmt::Display for Errno { Errno::EDEADLK => "Resource deadlock would occur", Errno::ENAMETOOLONG => "File name too long", Errno::ENOLCK => "No record locks available", - _ => "Unknown", - }) + _ => "Unknown error", + }, + ) } } + + diff --git a/src/libos/src/file.rs b/src/libos/src/file.rs new file mode 100644 index 00000000..f653c0c6 --- /dev/null +++ b/src/libos/src/file.rs @@ -0,0 +1,177 @@ +use prelude::*; +use {std}; +use std::{fmt}; + +use std::sgxfs as fs_impl; +use std::io::{Read, Write, Seek, SeekFrom}; + +pub trait File : Debug + Sync + Send { + fn read(&self, buf: &mut [u8]) -> Result; + fn write(&self, buf: &[u8]) -> Result; + //pub seek(&mut self, ) -> Result; + +} + +pub type FileRef = Arc>; + +#[derive(Debug)] +#[repr(C)] +pub struct SgxFile { + inner: SgxMutex, +} + +impl SgxFile { + pub fn new(file: Arc>, + is_readable: bool, is_writable: bool, is_append: bool) -> SgxFile + { + SgxFile { + inner: SgxMutex::new(SgxFileInner { + pos: 0 as usize, + file: file, + is_readable, + is_writable, + is_append, + }), + } + } +} + +impl File for SgxFile { + fn read(&self, buf: &mut [u8]) -> Result { + let mut inner_guard = self.inner.lock().unwrap(); + let inner = inner_guard.borrow_mut(); + inner.read(buf) + } + + fn write(&self, buf: &[u8]) -> Result { + let mut inner_guard = self.inner.lock().unwrap(); + let inner = inner_guard.borrow_mut(); + inner.write(buf) + } +} + +#[derive(Clone)] +#[repr(C)] +struct SgxFileInner { +// perms: FilePerms, + pos: usize, + file: Arc>, + is_readable: bool, + is_writable: bool, + is_append: bool, +} + +impl SgxFileInner { + pub fn write(&mut self, buf: &[u8]) -> Result { + let mut file_guard = self.file.lock().unwrap(); + 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"))?; + + let write_len = { + file.write(buf).map_err( + |e| Error::new(Errno::EINVAL, "Failed to write"))? + }; + + self.pos += write_len; + Ok(write_len) + } + + pub fn read(&mut self, buf: &mut [u8]) -> Result { + let mut file_guard = self.file.lock().unwrap(); + 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"))?; + + let read_len = { + file.read(buf).map_err( + |e| Error::new(Errno::EINVAL, "Failed to write"))? + }; + + self.pos += read_len; + Ok(read_len) + } +} + +unsafe impl Send for SgxFileInner {} +unsafe impl Sync for SgxFileInner {} + +impl Debug for SgxFileInner { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "SgxFileInner {{ pos: {}, file: ??? }}", self.pos) + } +} + +pub struct StdoutFile { + inner: std::io::Stdout, +} + +impl StdoutFile { + pub fn new() -> StdoutFile { + StdoutFile { + inner: std::io::stdout(), + } + } +} + +impl File for StdoutFile { + fn write(&self, buf: &[u8]) -> Result { + let write_len = { + self.inner.lock().write(buf).map_err(|e| (Errno::EINVAL, + "Failed to write"))? + }; + Ok(write_len) + } + + fn read(&self, buf: &mut [u8]) -> Result { + Err(Error::new(Errno::EBADF, "Stdout does not support reading")) + } +} + +impl Debug for StdoutFile { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "StdoutFile") + } +} + +unsafe impl Send for StdoutFile {} +unsafe impl Sync for StdoutFile {} + +pub struct StdinFile { + inner: std::io::Stdin, +} + +impl StdinFile { + pub fn new() -> StdinFile { + StdinFile { + inner: std::io::stdin(), + } + } +} + +impl File for StdinFile { + fn read(&self, buf: &mut [u8]) -> Result { + let read_len = { + self.inner.lock().read(buf).map_err(|e| (Errno::EINVAL, + "Failed to read"))? + }; + Ok(read_len) + } + + fn write(&self, buf: &[u8]) -> Result { + Err(Error::new(Errno::EBADF, "Stdin does not support reading")) + } +} + +impl Debug for StdinFile { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "StdinFile") + } +} + +unsafe impl Send for StdinFile {} +unsafe impl Sync for StdinFile {} diff --git a/src/libos/src/file_table.rs b/src/libos/src/file_table.rs new file mode 100644 index 00000000..fd531955 --- /dev/null +++ b/src/libos/src/file_table.rs @@ -0,0 +1,81 @@ +use prelude::*; +use {std, file}; +use file::{File, FileRef}; + +pub type FileDesc = u32; + +// Invariant 1: fd < max_fd, where fd is any fd in the table +// Invariant 2: max_fd = table.size() +// Invariant 3: num_fds <= table.size() +#[derive(Clone, Debug)] +#[repr(C)] +pub struct FileTable { + table: Vec>, + max_fd: FileDesc, + num_fds: u32, +} + +impl FileTable { + pub fn new() -> FileTable { + FileTable { + table: Vec::with_capacity(0), + max_fd: 0, + num_fds: 0, + } + } + + pub fn put(&mut self, file: FileRef) -> FileDesc { + let mut table = &mut self.table; + + let free_fd = if self.num_fds < self.max_fd { + table.iter().enumerate() + .find(|&(idx, opt)| opt.is_none()).unwrap().0 as FileDesc + } else { + table.push(None); + self.max_fd += 1; + self.num_fds + }; + + table[free_fd as usize] = Some(file); + self.num_fds += 1; + + free_fd + } + + pub fn get(&self, fd: FileDesc) -> Option { + if fd >= self.max_fd { + return None; + } + + let table = &self.table; + table[fd as usize].as_ref().map(|file_ref| file_ref.clone()) + } + + pub fn del(&mut self, fd: FileDesc) -> Option { + if fd >= self.max_fd { + return None; + } + + let mut del_file = None; + let table = &mut self.table; + std::mem::swap(&mut del_file, &mut table[fd as usize]); + if del_file.is_none() { + return None; + } + + self.num_fds -= 1; + if fd + 1 == self.max_fd { + self.max_fd = table.iter().enumerate().rev() + .find(|&(idx, opt)| opt.is_some()) + .map_or(0, |(max_used_fd,opt)| max_used_fd + 1) as FileDesc; + } + del_file + } +} + +impl Default for FileTable { + fn default() -> FileTable { + FileTable::new() + } +} + diff --git a/src/libos/src/fs.rs b/src/libos/src/fs.rs new file mode 100644 index 00000000..4d8ff7f0 --- /dev/null +++ b/src/libos/src/fs.rs @@ -0,0 +1,74 @@ +use prelude::*; +use {std, file, file_table, process}; +use file::{File, SgxFile}; +use file_table::{FileDesc}; + +use std::sgxfs as fs_impl; + +pub const O_RDONLY : u32 = 0x00000000; +pub const O_WRONLY : u32 = 0x00000001; +pub const O_RDWR : u32 = 0x00000002; +pub const O_CREAT : u32 = 0x00000040; +pub const O_TRUNC : u32 = 0x00000200; +pub const O_APPEND : u32 = 0x00000400; + +pub fn do_open(path: &str, flags: u32, mode: u32) -> Result { + let open_options = { + let mut open_options = fs_impl::OpenOptions::new(); + + if ((flags & O_TRUNC) != 0 || (flags & O_CREAT) != 0) { + open_options.write(true); + } + else { + open_options.read(true); + } + open_options.update(true).binary(true); + + open_options + }; + + let mut sgx_file = { + let key : sgx_key_128bit_t = [0 as uint8_t; 16]; + 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)) + }; + + let is_readable = (flags & O_RDONLY != 0) || (flags & O_RDWR != 0); + let is_writable = (flags & O_WRONLY != 0) || (flags & O_RDWR != 0); + let is_append = (flags & O_APPEND != 0); + let file_ref : Arc> = Arc::new(Box::new( + SgxFile::new(sgx_file, is_readable, is_writable, is_append))); + + let current_ref = process::get_current(); + let mut current_process = current_ref.lock().unwrap(); + let fd = current_process.file_table.put(file_ref); + + Ok(fd) +} + +pub fn do_write(fd: FileDesc, buf: &[u8]) -> Result { + let current_ref = process::get_current(); + let current_process = current_ref.lock().unwrap(); + let file_ref = current_process.file_table.get(fd) + .ok_or_else(|| Error::new(Errno::EBADF, "Invalid file descriptor"))?; + file_ref.write(buf) +} + +pub fn do_read(fd: FileDesc, buf: &mut [u8]) -> Result { + let current_ref = process::get_current(); + let current_process = current_ref.lock().unwrap(); + let file_ref = current_process.file_table.get(fd) + .ok_or_else(|| Error::new(Errno::EBADF, "Invalid file descriptor"))?; + file_ref.read(buf) +} + +pub fn do_close(fd: FileDesc) -> Result<(), Error> { + let current_ref = process::get_current(); + let mut current_process = current_ref.lock().unwrap(); + let file_table = &mut current_process.file_table; + match file_table.del(fd) { + Some(_) => Ok(()), + None => Err(Error::new(Errno::EBADF, "Invalid file descriptor")), + } +} diff --git a/src/libos/src/lib.rs b/src/libos/src/lib.rs index 6e580fff..df013ae7 100644 --- a/src/libos/src/lib.rs +++ b/src/libos/src/lib.rs @@ -24,12 +24,16 @@ use std::panic; use sgx_types::*; use sgx_trts::libc; -mod vma; +mod prelude; +mod elf_helper; +mod errno; +mod file; +mod file_table; +mod fs; +mod mm; mod process; mod syscall; -mod elf_helper; -mod mm; -mod errno; +mod vma; /// Export system calls pub use syscall::*; @@ -44,8 +48,7 @@ pub extern "C" fn libos_boot(path_buf: *const i8) -> i32 { let _ = backtrace::enable_backtrace("librusgx.signed.so", PrintFormat::Short); panic::catch_unwind(||{ backtrace::__rust_begin_short_backtrace(||{ - let mut pid = 0; - let _ = process::do_spawn(&mut pid, &path_str); + process::do_spawn(&path_str); }) }).ok(); diff --git a/src/libos/src/mm.rs b/src/libos/src/mm.rs index d79cb039..67b9d06d 100644 --- a/src/libos/src/mm.rs +++ b/src/libos/src/mm.rs @@ -1,8 +1,6 @@ -use sgx_types::{c_void, c_int, size_t}; -use sgx_trts::libc; +use prelude::*; + use std::mem; -use std::marker::Send; -use std::marker::Sync; #[derive(Clone, Debug)] pub struct MemObj { @@ -13,16 +11,16 @@ pub struct MemObj { impl MemObj { pub fn new(mem_size: usize, mem_align: usize) - -> Result + -> Result { if mem_size == 0 || !is_power_of_two(mem_align) || mem_align % mem::size_of::<*const c_void>() != 0 { - return Err("Invalid argument"); + return Err((Errno::EINVAL, "Invalid argument").into()); } let mem_ptr = unsafe { aligned_malloc(mem_size, mem_align) }; if mem_ptr == (0 as *mut c_void) { - return Err("Out of memory"); + return Err((Errno::ENOMEM, "Out of memory").into()); }; unsafe { memset(mem_ptr, 0 as c_int, mem_size as size_t) }; @@ -59,7 +57,6 @@ impl Drop for MemObj { unsafe impl Send for MemObj {} unsafe impl Sync for MemObj {} - fn is_power_of_two(x: usize) -> bool { return (x != 0) && ((x & (x - 1)) == 0); } diff --git a/src/libos/src/prelude.rs b/src/libos/src/prelude.rs new file mode 100644 index 00000000..cb3d1716 --- /dev/null +++ b/src/libos/src/prelude.rs @@ -0,0 +1,18 @@ +use std; +pub use sgx_types::*; +pub use sgx_trts::libc; + +//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::result::Result; +pub use std::borrow::BorrowMut; +pub use std::boxed::Box; +pub use std::vec::Vec; +pub use std::collections::{HashMap, VecDeque}; +pub use std::fmt::{Debug, Display}; + +pub use errno::Error as Error; +pub use errno::Errno; diff --git a/src/libos/src/process.rs b/src/libos/src/process.rs index af95481c..e9f2fb2c 100644 --- a/src/libos/src/process.rs +++ b/src/libos/src/process.rs @@ -1,26 +1,20 @@ -use std; -use std::vec::Vec; +use prelude::*; +use {std, elf_helper, vma, syscall, file, file_table}; +use std::{io, mem}; use std::path::Path; -use std::sgxfs::SgxFile; -use std::io; use std::io::{Read}; -use std::mem; - -use sgx_types::*; - -use xmas_elf::{ElfFile, header, program}; -use xmas_elf::sections; -use xmas_elf::symbol_table::Entry; - -use {elf_helper, vma, syscall}; -use vma::Vma; use std::sync::atomic::{AtomicU32, Ordering}; -use std::sync::{SgxMutex, SgxMutexGuard}; -use std::sync::Arc; -use std::collections::{HashMap, VecDeque}; +use std::sgxfs::SgxFile; use std::thread; use std::cell::Cell; +use xmas_elf::{ElfFile, header, program, sections}; +use xmas_elf::symbol_table::Entry; + +use vma::Vma; +use file::{File, StdinFile, StdoutFile/*, StderrFile*/}; +use file_table::{FileTable}; + lazy_static! { static ref PROCESS_TABLE: SgxMutex> = { SgxMutex::new(HashMap::new()) @@ -51,30 +45,56 @@ fn free_pid(pid: u32) { } -pub fn do_spawn>(new_pid: &mut u32, elf_path: &P) -> Result<(), &'static str> { - let elf_buf = open_elf(elf_path).unwrap(); - let elf_file = ElfFile::new(&elf_buf).unwrap(); - header::sanity_check(&elf_file).unwrap(); -/* - elf_helper::print_program_headers(&elf_file)?; - elf_helper::print_sections(&elf_file)?; - elf_helper::print_pltrel_section(&elf_file)?; -*/ - let new_process = Process::new(&elf_file)?; - *new_pid = new_process.pid; - let new_process = Arc::new(SgxMutex::new(new_process)); - //println!("new_process: {:#x?}", &new_process); +pub fn do_spawn>(elf_path: &P) -> Result { + let elf_buf = open_elf(elf_path) + .map_err(|e| (e.errno, "Failed to open the ELF file"))?; - enqueue_new_process(new_process.clone()); - put_into_pid_table(*new_pid, new_process); + let 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"))?; + /* + elf_helper::print_program_headers(&elf_file)?; + elf_helper::print_sections(&elf_file)?; + elf_helper::print_pltrel_section(&elf_file)?; + */ + elf_file + }; + + let new_process = { + let mut new_process = Process::new(&elf_file) + .map_err(|e| (Errno::EUNDEF, "Failed to create the process"))?; + + { + let file_table = &mut new_process.file_table; + + //let stdin = Arc::new(SgxMutex::new(Box::new(StdinFile::new()))); + let stdin : Arc> = Arc::new(Box::new(StdinFile::new())); + let stdout : Arc> = Arc::new(Box::new(StdoutFile::new())); + let stderr = stdout.clone(); + file_table.put(stdin); + file_table.put(stdout); + file_table.put(stderr); + }; + + new_process + }; + + let new_pid = new_process.pid; + let new_process_ref = Arc::new(SgxMutex::new(new_process)); + enqueue_new_process(new_process_ref.clone()); + put_into_pid_table(new_pid, new_process_ref.clone()); + + // FIXME: if ocall_new_task failed, then new_process will not be dropped let mut ret = 0; let ocall_status = unsafe { ocall_run_new_task(&mut ret) }; if ocall_status != sgx_status_t::SGX_SUCCESS || ret != 0 { - return Err("ocall_run_new_task failed"); + return Err((Errno::EUNDEF, "Failed to start the process").into()); } - Ok(()) + Ok(new_pid) } thread_local! { @@ -127,12 +147,14 @@ pub fn do_exit(exit_code: i32) { } } -pub fn do_wait4(child_pid: u32, exit_code: &mut i32) -> Result<(), &'static str> { - let child_process = look_up_pid_table(child_pid).ok_or("Not found")?; +pub fn do_wait4(child_pid: u32) -> Result { + let child_process = look_up_pid_table(child_pid) + .ok_or_else(|| (Errno::ECHILD, "Cannot find child process with the given PID"))?; + let mut exit_code = 0; loop { let guard = child_process.lock().unwrap(); if guard.status == Status::ZOMBIE { - *exit_code = guard.exit_code; + exit_code = guard.exit_code; break; } drop(guard); @@ -141,11 +163,12 @@ pub fn do_wait4(child_pid: u32, exit_code: &mut i32) -> Result<(), &'static str> let child_pid = child_process.lock().unwrap().pid; del_from_pid_table(child_pid); - Ok(()) + Ok(exit_code) } -pub fn run_task() -> Result<(), &'static str> { - let new_process : ProcessRef = dequeue_new_process().ok_or("No new process to run")?; +pub fn run_task() -> Result<(), Error> { + let new_process : ProcessRef = dequeue_new_process() + .ok_or_else(|| (Errno::EAGAIN, "No new processes to run"))?; set_current(&new_process); let pid; @@ -171,13 +194,14 @@ pub fn run_task() -> Result<(), &'static str> { Ok(()) } -fn open_elf>(path: &P) -> io::Result> { +fn open_elf>(path: &P) -> Result, Error> { let key : sgx_key_128bit_t = [0 as uint8_t; 16]; - let mut elf_file = SgxFile::open_ex(path, &key)?; + let mut elf_file = SgxFile::open_ex(path, &key) + .map_err(|e| (Errno::ENOENT, "Failed to open the SGX-protected file"))?; let mut elf_buf = Vec::::new(); elf_file.read_to_end(&mut elf_buf); - drop(elf_file); + Ok(elf_buf) } @@ -194,11 +218,12 @@ pub struct Process { pub stack_vma: Vma, pub program_base_addr: usize, pub program_entry_addr: usize, + pub file_table: FileTable, } pub type ProcessRef = Arc>; impl Process { - pub fn new(elf_file: &ElfFile) -> Result { + pub fn new(elf_file: &ElfFile) -> Result { let mut new_process : Process = Default::default(); new_process.create_process_image(elf_file)?; new_process.link_syscalls(elf_file)?; @@ -217,10 +242,12 @@ impl Process { } fn create_process_image(self: &mut Process, elf_file: &ElfFile) - -> Result<(), &'static str> + -> Result<(), Error> { - let code_ph = elf_helper::get_code_program_header(elf_file)?; - let data_ph = elf_helper::get_data_program_header(elf_file)?; + let code_ph = elf_helper::get_code_program_header(elf_file) + .map_err(|e| (Errno::ENOEXEC, "Failed to get the program header of code"))?; + let data_ph = elf_helper::get_data_program_header(elf_file) + .map_err(|e| (Errno::ENOEXEC, "Failed to get the program header of code"))?; self.code_vma = Vma::from_program_header(&code_ph)?; self.data_vma = Vma::from_program_header(&data_ph)?; @@ -231,14 +258,14 @@ impl Process { self.program_entry_addr = self.program_base_addr + elf_helper::get_start_address(elf_file)?; if !self.code_vma.contains(self.program_entry_addr) { - return Err("Entry address is out of the code segment"); + return Err((Errno::EINVAL, "Entry address is out of the code segment").into()); } Ok(()) } fn alloc_mem_for_vmas(self: &mut Process, elf_file: &ElfFile) - -> Result + -> Result { let mut vma_list = vec![&mut self.code_vma, &mut self.data_vma, &mut self.stack_vma]; let base_addr = vma::malloc_batch(&mut vma_list, elf_file.input)?; @@ -247,7 +274,7 @@ impl Process { } fn link_syscalls(self: &mut Process, elf_file: &ElfFile) - -> Result<(), &'static str> + -> Result<(), Error> { let syscall_addr = rusgx_syscall as *const () as usize; @@ -256,7 +283,9 @@ impl Process { 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)?; + 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 == "rusgx_syscall" { let rela_addr = self.program_base_addr + rela_entry.get_offset() as usize; @@ -269,7 +298,7 @@ impl Process { Ok(()) } - fn mprotect(self: &mut Process) -> Result<(), &'static str> { + fn mprotect(self: &mut Process) -> Result<(), Error> { let vma_list = vec![&self.code_vma, &self.data_vma, &self.stack_vma]; vma::mprotect_batch(&vma_list) } diff --git a/src/libos/src/syscall.h b/src/libos/src/syscall.h index afb4fdb7..d040b719 100644 --- a/src/libos/src/syscall.h +++ b/src/libos/src/syscall.h @@ -8,6 +8,9 @@ extern "C" { #endif +extern int rusgx_open(const char* path, int flags, int mode); +extern int rusgx_close(int fd); +extern ssize_t rusgx_read(int fd, void* buf, size_t size); extern ssize_t rusgx_write(int fd, const void* buf, size_t size); extern int rusgx_spawn(int* child_pid, const char* path, const char** argv, diff --git a/src/libos/src/syscall.rs b/src/libos/src/syscall.rs index 92e85f23..08c0dbb6 100644 --- a/src/libos/src/syscall.rs +++ b/src/libos/src/syscall.rs @@ -1,36 +1,76 @@ -use sgx_types::*; - -use process; +use prelude::*; +use {std, file, file_table, fs, process}; use std::ffi::CStr; // a borrowed C string -use std::collections::HashMap; // Use the internal syscall wrappers from sgx_tstd //use std::libc_fs as fs; //use std::libc_io as io; +// TODO: check all pointer passed from user belongs to user space + /* -#[no_mangle] -pub unsafe extern "C" fn sys_open(path: * const c_char, flags: c_int, mode: c_int) -> c_int { - fs::open64(path, flags, mode) -} -#[no_mangle] -pub unsafe extern "C" fn sys_close(fd: c_int) -> c_int { - io::close(fd) -} - -#[no_mangle] -pub unsafe extern "C" fn sys_read(fd: c_int, buf: * mut c_void, size: size_t) -> ssize_t { - io::read(fd, buf, size) -} */ +#[no_mangle] +pub extern "C" fn rusgx_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() + }; + match fs::do_open(&path, flags as u32, mode as u32) { + Ok(fd) => { + fd as c_int + }, + Err(e) => { + e.errno.as_retval() + } + } +} + +#[no_mangle] +pub extern "C" fn rusgx_close(fd: c_int) -> c_int { + match fs::do_close(fd as file_table::FileDesc) { + Ok(()) => { + 0 + }, + Err(e) => { + e.errno.as_retval() + } + } +} + +#[no_mangle] +pub extern "C" fn rusgx_read(fd: c_int, buf: * mut c_void, size: size_t) -> ssize_t { + let buf = unsafe { + std::slice::from_raw_parts_mut(buf as *mut u8, size as usize) + }; + match fs::do_read(fd as file_table::FileDesc, buf) { + Ok(read_len) => { + read_len as ssize_t + }, + Err(e) => { + e.errno.as_retval() as ssize_t + } + } +} #[no_mangle] pub extern "C" fn rusgx_write(fd: c_int, buf: * const c_void, size: size_t) -> ssize_t { - let str_from_c = unsafe { +/* let str_from_c = unsafe { CStr::from_ptr(buf as * const i8).to_string_lossy().into_owned() }; println!("rusgx_write: {}", str_from_c); size as ssize_t +*/ + let buf = unsafe { + std::slice::from_raw_parts(buf as *const u8, size as usize) + }; + match fs::do_write(fd as file_table::FileDesc, buf) { + Ok(write_len) => { + write_len as ssize_t + }, + Err(e) => { + e.errno.as_retval() as ssize_t + } + } } #[no_mangle] @@ -46,31 +86,35 @@ pub extern "C" fn rusgx_exit(status: i32) } #[no_mangle] -pub extern "C" fn rusgx_spawn(_child_pid: *mut c_int, path: *const c_char, +pub extern "C" fn rusgx_spawn(child_pid: *mut c_int, path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int { let mut ret = 0; - let mut child_pid = 0; let path_str = unsafe { CStr::from_ptr(path as * const i8).to_string_lossy().into_owned() }; - if process::do_spawn(&mut child_pid, &path_str) != Ok(()) { - ret = -1; + match process::do_spawn(&path_str) { + Ok(new_pid) => unsafe { + *child_pid = new_pid as c_int; + 0 + }, + Err(e) => { + e.errno.as_retval() + } } - unsafe { - *_child_pid = child_pid as c_int; - } - ret } #[no_mangle] pub extern "C" fn rusgx_wait4(child_pid: c_int, _exit_code: *mut c_int, options: c_int/*, rusage: *mut Rusage*/) -> c_int { - let mut exit_code = 0; - process::do_wait4(child_pid as u32, &mut exit_code); - unsafe { - *_exit_code = exit_code; + match process::do_wait4(child_pid as u32) { + Ok(exit_code) => unsafe { + *_exit_code = exit_code; + 0 + } + Err(e) => { + e.errno.as_retval() + } } - 0 } diff --git a/src/libos/src/syscall_entry.c b/src/libos/src/syscall_entry.c index 7842e38d..c975dcb7 100644 --- a/src/libos/src/syscall_entry.c +++ b/src/libos/src/syscall_entry.c @@ -14,6 +14,18 @@ long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long do_exit_task(); break; } + case SYS_open: { + DECL_SYSCALL_ARG(const void*, path, arg0); + DECL_SYSCALL_ARG(int, flags, arg1); + DECL_SYSCALL_ARG(int, mode, arg2); + ret = rusgx_open(path, flags, mode); + break; + } + case SYS_close: { + DECL_SYSCALL_ARG(int, fd, arg0); + ret = rusgx_close(fd); + break; + } case SYS_write: { DECL_SYSCALL_ARG(int, fd, arg0); DECL_SYSCALL_ARG(const void*, buf, arg1); @@ -21,6 +33,13 @@ long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long ret = rusgx_write(fd, buf, buf_size); break; } + case SYS_read: { + DECL_SYSCALL_ARG(int, fd, arg0); + DECL_SYSCALL_ARG(void*, buf, arg1); + DECL_SYSCALL_ARG(size_t, buf_size, arg2); + ret = rusgx_read(fd, buf, buf_size); + break; + } case SYS_spawn: { DECL_SYSCALL_ARG(int*, child_pid, arg0); DECL_SYSCALL_ARG(const char*, path, arg1); diff --git a/src/libos/src/vma.rs b/src/libos/src/vma.rs index 74b87474..7da1c610 100644 --- a/src/libos/src/vma.rs +++ b/src/libos/src/vma.rs @@ -1,11 +1,11 @@ /// Virtuam Memory Area (VMA) +use prelude::*; +use {std}; use xmas_elf::program; use xmas_elf::program::{ProgramHeader}; -use std; -use std::sync::Arc; + use mm::MemObj; -use sgx_types::*; #[derive(Clone, Debug, Default)] #[repr(C)] @@ -31,11 +31,11 @@ const VMA_MIN_MEM_ALIGN: usize = (4 * 1024); impl Vma { pub fn from_program_header<'a>(ph: &ProgramHeader<'a>) - -> Result + -> Result { let ph64 = match ph { ProgramHeader::Ph32(ph) => { - return Err("Not support 32-bit ELF") + return Err((Errno::ENOEXEC, "Not support 32-bit ELF").into()) } ProgramHeader::Ph64(ph64) => { ph64 @@ -43,10 +43,12 @@ impl Vma { }; if ph64.align > 1 && ((ph64.offset % ph64.align) != (ph64.virtual_addr % ph64.align)) { - return Err("Memory address and file offset is not equal, per modulo"); + return Err((Errno::EINVAL, + "Memory address and file offset is not equal, per modulo").into()); } if ph64.mem_size < ph64.file_size { - return Err("Memory size must be greater than file size"); + return Err((Errno::EINVAL, + "Memory size must be greater than file size").into()); } let mut new_vma = Vma::new(ph64.mem_size as usize, @@ -62,13 +64,15 @@ impl Vma { } pub fn new(mem_size: usize, mem_align: usize, mem_flags: Perms) - -> Result + -> Result { if mem_align == 0 || mem_align % VMA_MIN_MEM_ALIGN != 0 { - return Err("Memory alignment is not a multiple of 4KB"); + return Err((Errno::EINVAL, + "Memory alignment is not a multiple of 4KB").into()); } if mem_size == 0 { - return Err("Memory size must be greater than zero"); + return Err((Errno::EINVAL, + "Memory size must be greater than zero").into()); } Ok(Vma { @@ -85,7 +89,7 @@ impl Vma { } pub fn malloc_batch(vma_list: &mut [&mut Vma], mapped_data: &[u8]) - -> Result + -> Result { let mut max_align = VMA_MIN_MEM_ALIGN; let mut total_size = 0; @@ -96,11 +100,13 @@ pub fn malloc_batch(vma_list: &mut [&mut Vma], mapped_data: &[u8]) if vma.file_is_mapped { if vma.mem_addr < mem_begin || vma.mem_addr + vma.mem_size > mem_end { - return Err("Impossible memory layout for the VMA"); + return Err((Errno::EINVAL, + "Impossible memory layout for the VMA").into()); } if vma.file_offset > mapped_data.len() || vma.file_offset + vma.file_size > mapped_data.len() { - return Err("Impossible to load data from file"); + return Err((Errno::EINVAL, + "Impossible to load data from file").into()); } } @@ -134,7 +140,7 @@ pub fn malloc_batch(vma_list: &mut [&mut Vma], mapped_data: &[u8]) } pub fn mprotect_batch(vma_list: &[&Vma]) - -> Result<(), &'static str> + -> Result<(), Error> { for vma in vma_list.into_iter() { // If don't need to change memory permissions @@ -153,7 +159,7 @@ pub fn mprotect_batch(vma_list: &[&Vma]) trts_mprotect(start, size, (PERM_R | PERM_W | PERM_X) as uint64_t) }; if (status != sgx_status_t::SGX_SUCCESS) { - return Err("trts_mprotect failed"); + return Err((Errno::EACCES, "trts_mprotect failed").into()); } } Ok(()) diff --git a/test/Makefile b/test/Makefile index 2d1649ac..27b57e13 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,7 +1,7 @@ CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) PROJECT_DIR := $(realpath $(CUR_DIR)/../) -TEST_SUITES := hello_world_raw spawn_and_wait4_raw getpid +TEST_SUITES := hello_world_raw spawn_and_wait4_raw getpid file_io BUILD_TEST_SUITES := $(TEST_SUITES:%=%) RUN_TEST_SUITES := $(TEST_SUITES:%=run-%) CLEAN_TEST_SUITES := $(TEST_SUITES:%=clean-%) diff --git a/test/file_io/Makefile b/test/file_io/Makefile new file mode 100644 index 00000000..593ab76d --- /dev/null +++ b/test/file_io/Makefile @@ -0,0 +1,4 @@ +include ../test_common.mk + +EXTRA_C_FLAGS := -fno-builtin +EXTRA_LINK_FLAGS := -nostdlib diff --git a/test/file_io/main.c b/test/file_io/main.c new file mode 100644 index 00000000..99acb7b3 --- /dev/null +++ b/test/file_io/main.c @@ -0,0 +1,66 @@ +#include "rusgx_stub.h" + +static char success_str_buf[] = "Success!\n"; +static unsigned long success_str_size = sizeof(success_str_buf); + +static void print_ok(void) { + __rusgx_write(1, success_str_buf, success_str_size); +} + + +static int test_write(const char* file_path) { + int write_fd = __rusgx_open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (write_fd < 0) { + return -1; + } + + char write_buf[] = "Hello World!\n"; + size_t write_len = sizeof(write_buf); + if (__rusgx_write(write_fd, write_buf, write_len) != write_len) { + return -2; + } + + if (__rusgx_close(write_fd) < 0) { + return -3; + } + + return 0; +} + +static int test_read(const char* file_path) { + int read_fd = __rusgx_open(file_path, O_RDONLY, 0); + if (read_fd < 0) { + return -1; + } + + char read_buf[256] = { 0 }; + size_t read_len; + if ((read_len = __rusgx_read(read_fd, read_buf, 256)) < 0 ) { + return -2; + } + + __rusgx_write(1, read_buf, read_len); + + if (__rusgx_close(read_fd) < 0) { + return -3; + } + + return 0; +} + +void _start(void) { + int ret = 0; + const char* file_path = "tmp.txt.protected"; + + if ((ret = test_write(file_path)) < 0) { + goto on_exit; + } + + if ((ret = test_read(file_path)) < 0) { + goto on_exit; + } + + print_ok(); +on_exit: + __rusgx_exit(ret); +} diff --git a/test/include/rusgx_stub.h b/test/include/rusgx_stub.h index 4237e170..33ee7680 100644 --- a/test/include/rusgx_stub.h +++ b/test/include/rusgx_stub.h @@ -20,12 +20,32 @@ * host syscalls provided by the default implementation of this library. */ +#define SYS_read 0 #define SYS_write 1 +#define SYS_open 2 +#define SYS_close 3 #define SYS_getpid 39 #define SYS_exit 60 #define SYS_wait4 61 #define SYS_spawn 360 +#define O_RDONLY 0x00000000U +#define O_WRONLY 0x00000001U +#define O_RDWR 0x00000002U +#define O_CREAT 0x00000040U +#define O_EXCL 0x00000080U +#define O_NOCTTY 0x00000100U +#define O_TRUNC 0x00000200U +#define O_APPEND 0x00000400U +#define O_NONBLOCK 0x00000800U +#define O_NDELAY 0x00000800U +#define O_DSYNC 0x00001000U +#define O_DIRECTORY 0x00010000U +#define O_NOFOLLOW 0x00020000U +#define O_CLOEXEC 0x00080000U +#define O_SYNC 0x00101000U + + long rusgx_syscall(int num, long arg0, long arg1, long arg2, long arg3, long arg4); #define RUSGX_SYSCALL0(num) \ @@ -41,10 +61,24 @@ long rusgx_syscall(int num, long arg0, long arg1, long arg2, long arg3, long arg #define RUSGX_SYSCALL5(num, arg0, arg1, arg2, arg3, arg4) \ rusgx_syscall((num), (long)(arg0), (long)(arg1), (long)(arg2), (long)(arg3), (long)(arg4)) + +static inline ssize_t __rusgx_read(int fd, void* buf, unsigned long size) { + return (ssize_t) RUSGX_SYSCALL3(SYS_read, fd, buf, size); +} + static inline ssize_t __rusgx_write(int fd, const void* buf, unsigned long size) { return (ssize_t) RUSGX_SYSCALL3(SYS_write, fd, buf, size); } +static inline int __rusgx_open(const void* buf, int flags, int mode) { + return (int) RUSGX_SYSCALL3(SYS_open, buf, flags, mode); +} + +static inline int __rusgx_close(int fd) { + return (int) RUSGX_SYSCALL1(SYS_close, fd); +} + + static inline unsigned int __rusgx_getpid(void) { return (unsigned int) RUSGX_SYSCALL0(SYS_getpid); } diff --git a/test/rusgx_stub/stub_impl.c b/test/rusgx_stub/stub_impl.c index fbc14412..4d764aac 100644 --- a/test/rusgx_stub/stub_impl.c +++ b/test/rusgx_stub/stub_impl.c @@ -1,5 +1,16 @@ #include "rusgx_stub.h" +static long __read(int fd, void* buf, unsigned long size) { + long ret; + __asm__ __volatile__ ( + "syscall" + : "=a" (ret) + : "0" (SYS_read), "D" (fd), "S" (buf), "d" (size) + : "cc", "rcx", "r11", "memory" + ); + return ret; +} + static long __write(int fd, const void* buf, unsigned long size) { long ret; __asm__ __volatile__ ( @@ -11,6 +22,27 @@ static long __write(int fd, const void* buf, unsigned long size) { return ret; } +static long __open(const char* path, int flags, int mode) { + long ret; + __asm__ __volatile__ ( + "syscall" + : "=a" (ret) + : "0" (SYS_open), "D" (path), "S" (flags), "d" (mode) + : "cc", "rcx", "r11", "memory" + ); + return ret; +} + +static long __close(int fd) { + long ret; + __asm__ __volatile__ ( + "syscall" + : "=a" (ret) + : "a" (SYS_close), "D" (fd) + : "cc", "rcx", "r11", "memory" ); + return ret; +} + static void __exit(int status) { __asm__ __volatile__ ( "syscall" @@ -26,9 +58,18 @@ long rusgx_syscall(int num, long arg0, long arg1, long arg2, long arg3, long arg case SYS_exit: __exit((int)arg0); break; + case SYS_read: + ret = __read((int)arg0, (void*)arg1, (unsigned long)arg2); + break; case SYS_write: ret = __write((int)arg0, (const void*)arg1, (unsigned long)arg2); break; + case SYS_open: + ret = __open((const char*)arg0, (int)arg1, (int)arg2); + break; + case SYS_close: + ret = __close((int)arg0); + break; default: break; }