Add open, read, write and close
This commit is contained in:
		
							parent
							
								
									757d3f2f4d
								
							
						
					
					
						commit
						a66c55f95f
					
				| @ -1,34 +1,46 @@ | |||||||
| use xmas_elf::{ElfFile, program, P64}; | use prelude::*; | ||||||
| use xmas_elf::sections; | 
 | ||||||
|  | use xmas_elf::{sections, ElfFile, program, P64}; | ||||||
| use xmas_elf::symbol_table::{Entry64, DynEntry64}; | use xmas_elf::symbol_table::{Entry64, DynEntry64}; | ||||||
| use xmas_elf::program::{ProgramHeader}; | use xmas_elf::program::{ProgramHeader}; | ||||||
| use xmas_elf::sections::{Rela}; | use xmas_elf::sections::{Rela}; | ||||||
| use xmas_elf::symbol_table::Entry; | 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:"); |     println!("Program headers:"); | ||||||
|     let ph_iter = elf_file.program_iter(); |     let ph_iter = elf_file.program_iter(); | ||||||
|     for sect in ph_iter { |     for sect in ph_iter { | ||||||
|         program::sanity_check(sect, &elf_file)?; |         program::sanity_check(sect, &elf_file) | ||||||
|  |             .map_err(|e| (Errno::ENOEXEC, | ||||||
|  |                           "Sanity check for program header failed"))?; | ||||||
|         println!("\t{:?}", sect.get_type()); |         println!("\t{:?}", sect.get_type()); | ||||||
|     } |     } | ||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn print_sections(elf_file: &ElfFile) -> Result<(), &'static str> { | pub fn print_sections(elf_file: &ElfFile) -> Result<(), Error> { | ||||||
|     println!("Sections:"); |     println!("Sections:"); | ||||||
|     let mut sect_iter = elf_file.section_iter(); |     let mut sect_iter = elf_file.section_iter(); | ||||||
|     sect_iter.next(); // Skip the first, dummy section
 |     sect_iter.next(); // Skip the first, dummy section
 | ||||||
|     for sect in sect_iter { |     for sect in sect_iter { | ||||||
|         sections::sanity_check(sect, &elf_file)?; |         sections::sanity_check(sect, &elf_file) | ||||||
|         println!("\t{}\n{:?}", sect.get_name(&elf_file)?, sect); |             .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(()) |     Ok(()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn print_pltrel_section(elf_file: &ElfFile) -> Result<(), &'static str> { | pub fn print_pltrel_section(elf_file: &ElfFile) -> Result<(), Error> { | ||||||
|     let rela_entries = get_pltrel_entries(elf_file)?; |     let rela_entries = get_pltrel_entries(elf_file) | ||||||
|     let dynsym_entries = get_dynsym_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:"); |     println!(".plt.rela section:"); | ||||||
|     for entry in rela_entries { |     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 symidx = entry.get_symbol_table_index() as usize; | ||||||
|         let dynsym_entry = &dynsym_entries[symidx]; |         let dynsym_entry = &dynsym_entries[symidx]; | ||||||
|         println!("\t\t{} = {:?}", |         let dynsym_name = dynsym_entry.get_name(&elf_file) | ||||||
|                  dynsym_entry.get_name(&elf_file)?, dynsym_entry); |             .map_err(|e| (Errno::ENOEXEC, | ||||||
|  |                           "Failed to get the name of a dynamic symbol"))?; | ||||||
|  |         println!("\t\t{} = {:?}", dynsym_name, dynsym_entry); | ||||||
|     } |     } | ||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn get_data_program_header<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) | pub fn get_data_program_header<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) | ||||||
|     -> Result<ProgramHeader<'a>, &'static str> |     -> Result<ProgramHeader<'a>, Error> | ||||||
| { | { | ||||||
|     let mut ph_iter = elf_file.program_iter(); |     let mut ph_iter = elf_file.program_iter(); | ||||||
|     ph_iter.find(|&ph| ph.get_type() == Ok(program::Type::Load) && |     ph_iter.find(|&ph| ph.get_type() == Ok(program::Type::Load) && | ||||||
|                         !ph.flags().is_execute() && |                         !ph.flags().is_execute() && | ||||||
|                         ph.flags().is_write() && |                         ph.flags().is_write() && | ||||||
|                         ph.flags().is_read()) |                         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>) | pub fn get_code_program_header<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) | ||||||
|     -> Result<ProgramHeader<'a>, &'static str> |     -> Result<ProgramHeader<'a>, Error> | ||||||
| { | { | ||||||
|     let mut ph_iter = elf_file.program_iter(); |     let mut ph_iter = elf_file.program_iter(); | ||||||
|     ph_iter.find(|&ph| ph.get_type() == Ok(program::Type::Load) && |     ph_iter.find(|&ph| ph.get_type() == Ok(program::Type::Load) && | ||||||
|                         ph.flags().is_execute() && |                         ph.flags().is_execute() && | ||||||
|                         !ph.flags().is_write() && |                         !ph.flags().is_write() && | ||||||
|                         ph.flags().is_read()) |                         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>) | pub fn get_start_address<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) | ||||||
|     -> Result<usize, &'static str> |     -> Result<usize, Error> | ||||||
| { | { | ||||||
|     let sym_entries = get_sym_entries(elf_file)?; |     let sym_entries = get_sym_entries(elf_file)?; | ||||||
| 
 | 
 | ||||||
|     for sym_entry in sym_entries { |     for sym_entry in sym_entries { | ||||||
|         let sym_str = sym_entry.get_name(elf_file)?; |         let sym_str = sym_entry.get_name(elf_file) | ||||||
|  |             .map_err(|e| Error::new(Errno::ENOEXEC, | ||||||
|  |                                     "Failed to get the name of a symbol"))?; | ||||||
|         if sym_str == "_start" { |         if sym_str == "_start" { | ||||||
|             return Ok(sym_entry.value() as usize) |             return Ok(sym_entry.value() as usize) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Err("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>) | 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") |     elf_file.find_section_by_name(".symtab") | ||||||
|         .and_then(|symtab_section| { |         .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), |                 sections::SectionData::SymbolTable64(entries) => Some(entries), | ||||||
|                 _ => None, |                 _ => 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>) | pub fn get_pltrel_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) | ||||||
|     -> Result<&'a [Rela<P64>], &'static str> |     -> Result<&'a [Rela<P64>], Error> | ||||||
| { | { | ||||||
|     elf_file.find_section_by_name(".rela.plt") |     elf_file.find_section_by_name(".rela.plt") | ||||||
|         .and_then(|plt_rela_section| { |         .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), |                 sections::SectionData::Rela64(entries) => Some(entries), | ||||||
|                 _ => None, |                 _ => 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>) | 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") |     elf_file.find_section_by_name(".dynsym") | ||||||
|         .and_then(|dynamic_section| { |         .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), |                 sections::SectionData::DynSymbolTable64(entries) => Some(entries), | ||||||
|                 _ => None, |                 _ => None, | ||||||
|             } |             } | ||||||
|         }).ok_or("Cannot find or load .dynsym section") |         }).ok_or_else(|| (Errno::ENOEXEC, "Failed to get .dynsym entries").into()) | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,9 +1,51 @@ | |||||||
| use std; | use prelude::*; | ||||||
| use std::fmt; | use std::{fmt, error, convert,}; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Copy, Debug, PartialEq)] | #[derive(Clone, Copy, Debug, PartialEq)] | ||||||
| enum Errno { | pub struct Error { | ||||||
|     OK = 0, |     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, |     EPERM = 1, | ||||||
|     ENOENT = 2, |     ENOENT = 2, | ||||||
|     ESRCH = 3, |     ESRCH = 3, | ||||||
| @ -44,23 +86,16 @@ enum Errno { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Errno { | impl Errno { | ||||||
|     fn as_retval(&self) -> i32 { |     pub fn as_retval(&self) -> i32 { | ||||||
|         *self as i32 |         - (*self as i32) | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Default for Errno { |  | ||||||
|     fn default() -> Errno { |  | ||||||
|         Errno::OK |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl fmt::Display for Errno { | impl fmt::Display for Errno { | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||||
|         write!(f, "{} ({})", |         write!(f, "errno = {}, \"{}\"", | ||||||
|             *self as i32, |             *self as u32, | ||||||
|             match *self { |             match *self { | ||||||
|                 Errno::OK => "Ok", |  | ||||||
|                 Errno::EPERM =>  "Operation not permitted", |                 Errno::EPERM =>  "Operation not permitted", | ||||||
|                 Errno::ENOENT => "No such file or directory", |                 Errno::ENOENT => "No such file or directory", | ||||||
|                 Errno::ESRCH => "No such process", |                 Errno::ESRCH => "No such process", | ||||||
| @ -98,7 +133,10 @@ impl fmt::Display for Errno { | |||||||
|                 Errno::EDEADLK => "Resource deadlock would occur", |                 Errno::EDEADLK => "Resource deadlock would occur", | ||||||
|                 Errno::ENAMETOOLONG => "File name too long", |                 Errno::ENAMETOOLONG => "File name too long", | ||||||
|                 Errno::ENOLCK => "No record locks available", |                 Errno::ENOLCK => "No record locks available", | ||||||
|                 _ => "Unknown", |                 _ => "Unknown error", | ||||||
|             }) |             }, | ||||||
|  |         ) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | |||||||
							
								
								
									
										177
									
								
								src/libos/src/file.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										177
									
								
								src/libos/src/file.rs
									
									
									
									
									
										Normal file
									
								
							| @ -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<usize, Error>; | ||||||
|  |     fn write(&self, buf: &[u8]) -> Result<usize, Error>; | ||||||
|  |     //pub seek(&mut self, ) -> Result<usize, Error>;
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub type FileRef = Arc<Box<File>>; | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | #[repr(C)] | ||||||
|  | pub struct SgxFile { | ||||||
|  |     inner: SgxMutex<SgxFileInner>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl SgxFile { | ||||||
|  |     pub fn new(file: Arc<SgxMutex<fs_impl::SgxFile>>, | ||||||
|  |                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<usize, Error> { | ||||||
|  |         let mut inner_guard = self.inner.lock().unwrap(); | ||||||
|  |         let inner = inner_guard.borrow_mut(); | ||||||
|  |         inner.read(buf) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn write(&self, buf: &[u8]) -> Result<usize, Error> { | ||||||
|  |         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<SgxMutex<fs_impl::SgxFile>>, | ||||||
|  |     is_readable: bool, | ||||||
|  |     is_writable: bool, | ||||||
|  |     is_append: bool, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl SgxFileInner { | ||||||
|  |     pub fn write(&mut self, buf: &[u8]) -> Result<usize, Error> { | ||||||
|  |         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<usize, Error> { | ||||||
|  |         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<usize, Error> { | ||||||
|  |         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<usize, Error> { | ||||||
|  |         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<usize, Error> { | ||||||
|  |         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<usize, Error> { | ||||||
|  |         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 {} | ||||||
							
								
								
									
										81
									
								
								src/libos/src/file_table.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										81
									
								
								src/libos/src/file_table.rs
									
									
									
									
									
										Normal file
									
								
							| @ -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<Option<FileRef>>, | ||||||
|  |     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<FileRef> { | ||||||
|  |         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<FileRef> { | ||||||
|  |         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() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										74
									
								
								src/libos/src/fs.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										74
									
								
								src/libos/src/fs.rs
									
									
									
									
									
										Normal file
									
								
							| @ -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<FileDesc, Error> { | ||||||
|  |     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<Box<File>> = 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<usize, Error> { | ||||||
|  |     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<usize, Error> { | ||||||
|  |     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")), | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -24,12 +24,16 @@ use std::panic; | |||||||
| use sgx_types::*; | use sgx_types::*; | ||||||
| use sgx_trts::libc; | 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 process; | ||||||
| mod syscall; | mod syscall; | ||||||
| mod elf_helper; | mod vma; | ||||||
| mod mm; |  | ||||||
| mod errno; |  | ||||||
| 
 | 
 | ||||||
| /// Export system calls
 | /// Export system calls
 | ||||||
| pub use syscall::*; | 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); |     let _ = backtrace::enable_backtrace("librusgx.signed.so", PrintFormat::Short); | ||||||
|     panic::catch_unwind(||{ |     panic::catch_unwind(||{ | ||||||
|         backtrace::__rust_begin_short_backtrace(||{ |         backtrace::__rust_begin_short_backtrace(||{ | ||||||
|             let mut pid = 0; |             process::do_spawn(&path_str); | ||||||
|             let _ = process::do_spawn(&mut pid, &path_str); |  | ||||||
|         }) |         }) | ||||||
|     }).ok(); |     }).ok(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,8 +1,6 @@ | |||||||
| use sgx_types::{c_void, c_int, size_t}; | use prelude::*; | ||||||
| use sgx_trts::libc; | 
 | ||||||
| use std::mem; | use std::mem; | ||||||
| use std::marker::Send; |  | ||||||
| use std::marker::Sync; |  | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug)] | #[derive(Clone, Debug)] | ||||||
| pub struct MemObj { | pub struct MemObj { | ||||||
| @ -13,16 +11,16 @@ pub struct MemObj { | |||||||
| 
 | 
 | ||||||
| impl MemObj { | impl MemObj { | ||||||
|     pub fn new(mem_size: usize, mem_align: usize) |     pub fn new(mem_size: usize, mem_align: usize) | ||||||
|         -> Result<Self, &'static str> |         -> Result<Self, Error> | ||||||
|     { |     { | ||||||
|         if mem_size == 0 || !is_power_of_two(mem_align) || |         if mem_size == 0 || !is_power_of_two(mem_align) || | ||||||
|             mem_align % mem::size_of::<*const c_void>() != 0 { |             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) }; |         let mem_ptr = unsafe { aligned_malloc(mem_size, mem_align) }; | ||||||
|         if mem_ptr == (0 as *mut c_void) { |         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) }; |         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 Send for MemObj {} | ||||||
| unsafe impl Sync for MemObj {} | unsafe impl Sync for MemObj {} | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| fn is_power_of_two(x: usize) -> bool { | fn is_power_of_two(x: usize) -> bool { | ||||||
|     return (x != 0) && ((x & (x - 1)) == 0); |     return (x != 0) && ((x & (x - 1)) == 0); | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										18
									
								
								src/libos/src/prelude.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										18
									
								
								src/libos/src/prelude.rs
									
									
									
									
									
										Normal file
									
								
							| @ -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; | ||||||
| @ -1,26 +1,20 @@ | |||||||
| use std; | use prelude::*; | ||||||
| use std::vec::Vec; | use {std, elf_helper, vma, syscall, file, file_table}; | ||||||
|  | use std::{io, mem}; | ||||||
| use std::path::Path; | use std::path::Path; | ||||||
| use std::sgxfs::SgxFile; |  | ||||||
| use std::io; |  | ||||||
| use std::io::{Read}; | 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::atomic::{AtomicU32, Ordering}; | ||||||
| use std::sync::{SgxMutex, SgxMutexGuard}; | use std::sgxfs::SgxFile; | ||||||
| use std::sync::Arc; |  | ||||||
| use std::collections::{HashMap, VecDeque}; |  | ||||||
| use std::thread; | use std::thread; | ||||||
| use std::cell::Cell; | 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! { | lazy_static! { | ||||||
|     static ref PROCESS_TABLE: SgxMutex<HashMap<u32, ProcessRef>> = { |     static ref PROCESS_TABLE: SgxMutex<HashMap<u32, ProcessRef>> = { | ||||||
|         SgxMutex::new(HashMap::new()) |         SgxMutex::new(HashMap::new()) | ||||||
| @ -51,30 +45,56 @@ fn free_pid(pid: u32) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| pub fn do_spawn<P: AsRef<Path>>(new_pid: &mut u32, elf_path: &P) -> Result<(), &'static str> { | pub fn do_spawn<P: AsRef<Path>>(elf_path: &P) -> Result<u32, Error> { | ||||||
|     let elf_buf = open_elf(elf_path).unwrap(); |     let elf_buf = open_elf(elf_path) | ||||||
|     let elf_file = ElfFile::new(&elf_buf).unwrap(); |         .map_err(|e| (e.errno, "Failed to open the ELF file"))?; | ||||||
|     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);
 |  | ||||||
| 
 | 
 | ||||||
|     enqueue_new_process(new_process.clone()); |     let elf_file = { | ||||||
|     put_into_pid_table(*new_pid, new_process); |         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<Box<File>> = Arc::new(Box::new(StdinFile::new())); | ||||||
|  |             let stdout : Arc<Box<File>> = 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 mut ret = 0; | ||||||
|     let ocall_status = unsafe { ocall_run_new_task(&mut ret) }; |     let ocall_status = unsafe { ocall_run_new_task(&mut ret) }; | ||||||
|     if ocall_status != sgx_status_t::SGX_SUCCESS || ret != 0 { |     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! { | 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> { | pub fn do_wait4(child_pid: u32) -> Result<i32, Error> { | ||||||
|     let child_process = look_up_pid_table(child_pid).ok_or("Not found")?; |     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 { |     loop { | ||||||
|         let guard = child_process.lock().unwrap(); |         let guard = child_process.lock().unwrap(); | ||||||
|         if guard.status == Status::ZOMBIE { |         if guard.status == Status::ZOMBIE { | ||||||
|             *exit_code = guard.exit_code; |             exit_code = guard.exit_code; | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         drop(guard); |         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; |     let child_pid = child_process.lock().unwrap().pid; | ||||||
|     del_from_pid_table(child_pid); |     del_from_pid_table(child_pid); | ||||||
| 
 | 
 | ||||||
|     Ok(()) |     Ok(exit_code) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn run_task() -> Result<(), &'static str> { | pub fn run_task() -> Result<(), Error> { | ||||||
|     let new_process : ProcessRef = dequeue_new_process().ok_or("No new process to run")?; |     let new_process : ProcessRef = dequeue_new_process() | ||||||
|  |         .ok_or_else(|| (Errno::EAGAIN, "No new processes to run"))?; | ||||||
|     set_current(&new_process); |     set_current(&new_process); | ||||||
| 
 | 
 | ||||||
|     let pid; |     let pid; | ||||||
| @ -171,13 +194,14 @@ pub fn run_task() -> Result<(), &'static str> { | |||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn open_elf<P: AsRef<Path>>(path: &P) -> io::Result<Vec<u8>> { | fn open_elf<P: AsRef<Path>>(path: &P) -> Result<Vec<u8>, Error> { | ||||||
|     let key : sgx_key_128bit_t = [0 as uint8_t; 16]; |     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::<u8>::new(); |     let mut elf_buf = Vec::<u8>::new(); | ||||||
|     elf_file.read_to_end(&mut elf_buf); |     elf_file.read_to_end(&mut elf_buf); | ||||||
|     drop(elf_file); | 
 | ||||||
|     Ok(elf_buf) |     Ok(elf_buf) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -194,11 +218,12 @@ pub struct Process { | |||||||
|     pub stack_vma: Vma, |     pub stack_vma: Vma, | ||||||
|     pub program_base_addr: usize, |     pub program_base_addr: usize, | ||||||
|     pub program_entry_addr: usize, |     pub program_entry_addr: usize, | ||||||
|  |     pub file_table: FileTable, | ||||||
| } | } | ||||||
| pub type ProcessRef = Arc<SgxMutex<Process>>; | pub type ProcessRef = Arc<SgxMutex<Process>>; | ||||||
| 
 | 
 | ||||||
| impl Process { | impl Process { | ||||||
|     pub fn new(elf_file: &ElfFile) -> Result<Process, &'static str> { |     pub fn new(elf_file: &ElfFile) -> Result<Process, Error> { | ||||||
|         let mut new_process : Process = Default::default(); |         let mut new_process : Process = Default::default(); | ||||||
|         new_process.create_process_image(elf_file)?; |         new_process.create_process_image(elf_file)?; | ||||||
|         new_process.link_syscalls(elf_file)?; |         new_process.link_syscalls(elf_file)?; | ||||||
| @ -217,10 +242,12 @@ impl Process { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn create_process_image(self: &mut Process, elf_file: &ElfFile) |     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 code_ph = elf_helper::get_code_program_header(elf_file) | ||||||
|         let data_ph = elf_helper::get_data_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.code_vma = Vma::from_program_header(&code_ph)?; | ||||||
|         self.data_vma = Vma::from_program_header(&data_ph)?; |         self.data_vma = Vma::from_program_header(&data_ph)?; | ||||||
| @ -231,14 +258,14 @@ impl Process { | |||||||
|         self.program_entry_addr = self.program_base_addr + |         self.program_entry_addr = self.program_base_addr + | ||||||
|             elf_helper::get_start_address(elf_file)?; |             elf_helper::get_start_address(elf_file)?; | ||||||
|         if !self.code_vma.contains(self.program_entry_addr) { |         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(()) |         Ok(()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn alloc_mem_for_vmas(self: &mut Process, elf_file: &ElfFile) |     fn alloc_mem_for_vmas(self: &mut Process, elf_file: &ElfFile) | ||||||
|         -> Result<usize, &'static str> |         -> Result<usize, Error> | ||||||
|     { |     { | ||||||
|         let mut vma_list = vec![&mut self.code_vma, &mut self.data_vma, &mut self.stack_vma]; |         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)?; |         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) |     fn link_syscalls(self: &mut Process, elf_file: &ElfFile) | ||||||
|         -> Result<(), &'static str> |         -> Result<(), Error> | ||||||
|     { |     { | ||||||
|         let syscall_addr = rusgx_syscall as *const () as usize; |         let syscall_addr = rusgx_syscall as *const () as usize; | ||||||
| 
 | 
 | ||||||
| @ -256,7 +283,9 @@ impl Process { | |||||||
|         for rela_entry in rela_entries { |         for rela_entry in rela_entries { | ||||||
|             let dynsym_idx = rela_entry.get_symbol_table_index() as usize; |             let dynsym_idx = rela_entry.get_symbol_table_index() as usize; | ||||||
|             let dynsym_entry = &dynsym_entries[dynsym_idx]; |             let dynsym_entry = &dynsym_entries[dynsym_idx]; | ||||||
|             let dynsym_str = dynsym_entry.get_name(&elf_file)?; |             let dynsym_str = dynsym_entry.get_name(elf_file) | ||||||
|  |                 .map_err(|e| Error::new(Errno::ENOEXEC, | ||||||
|  |                                         "Failed to get the name of dynamic symbol"))?; | ||||||
| 
 | 
 | ||||||
|             if dynsym_str == "rusgx_syscall" { |             if dynsym_str == "rusgx_syscall" { | ||||||
|                 let rela_addr = self.program_base_addr + rela_entry.get_offset() as usize; |                 let rela_addr = self.program_base_addr + rela_entry.get_offset() as usize; | ||||||
| @ -269,7 +298,7 @@ impl Process { | |||||||
|         Ok(()) |         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]; |         let vma_list = vec![&self.code_vma, &self.data_vma, &self.stack_vma]; | ||||||
|         vma::mprotect_batch(&vma_list) |         vma::mprotect_batch(&vma_list) | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -8,6 +8,9 @@ | |||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #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 ssize_t rusgx_write(int fd, const void* buf, size_t size); | ||||||
| extern int rusgx_spawn(int* child_pid, const char* path, | extern int rusgx_spawn(int* child_pid, const char* path, | ||||||
|                         const char** argv, |                         const char** argv, | ||||||
|  | |||||||
| @ -1,36 +1,76 @@ | |||||||
| use sgx_types::*; | use prelude::*; | ||||||
| 
 | use {std, file, file_table, fs, process}; | ||||||
| use process; |  | ||||||
| use std::ffi::CStr; // a borrowed C string
 | use std::ffi::CStr; // a borrowed C string
 | ||||||
| use std::collections::HashMap; |  | ||||||
| // Use the internal syscall wrappers from sgx_tstd
 | // Use the internal syscall wrappers from sgx_tstd
 | ||||||
| //use std::libc_fs as fs;
 | //use std::libc_fs as fs;
 | ||||||
| //use std::libc_io as io;
 | //use std::libc_io as io;
 | ||||||
| 
 | 
 | ||||||
|  | // 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] | #[no_mangle] | ||||||
| pub extern "C" fn rusgx_write(fd: c_int, buf: * const c_void, size: size_t) -> ssize_t { | 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() |         CStr::from_ptr(buf as * const i8).to_string_lossy().into_owned() | ||||||
|     }; |     }; | ||||||
|     println!("rusgx_write: {}", str_from_c); |     println!("rusgx_write: {}", str_from_c); | ||||||
|     size as ssize_t |     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] | #[no_mangle] | ||||||
| @ -46,31 +86,35 @@ pub extern "C" fn rusgx_exit(status: i32) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[no_mangle] | #[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 |     argv: *const *const c_char, envp: *const *const c_char) -> c_int | ||||||
| { | { | ||||||
|     let mut ret = 0; |     let mut ret = 0; | ||||||
|     let mut child_pid = 0; |  | ||||||
|     let path_str = unsafe { |     let path_str = unsafe { | ||||||
|         CStr::from_ptr(path as * const i8).to_string_lossy().into_owned() |         CStr::from_ptr(path as * const i8).to_string_lossy().into_owned() | ||||||
|     }; |     }; | ||||||
|     if process::do_spawn(&mut child_pid, &path_str) != Ok(()) { |     match process::do_spawn(&path_str) { | ||||||
|         ret = -1; |         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] | #[no_mangle] | ||||||
| pub extern "C" fn rusgx_wait4(child_pid: c_int, _exit_code: *mut c_int, | pub extern "C" fn rusgx_wait4(child_pid: c_int, _exit_code: *mut c_int, | ||||||
|     options: c_int/*, rusage: *mut Rusage*/) -> c_int |     options: c_int/*, rusage: *mut Rusage*/) -> c_int | ||||||
| { | { | ||||||
|     let mut exit_code = 0; |     match process::do_wait4(child_pid as u32) { | ||||||
|     process::do_wait4(child_pid as u32, &mut exit_code); |         Ok(exit_code) => unsafe { | ||||||
|     unsafe { |             *_exit_code = exit_code; | ||||||
|         *_exit_code = exit_code; |             0 | ||||||
|  |         } | ||||||
|  |         Err(e) => { | ||||||
|  |             e.errno.as_retval() | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     0 |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,6 +14,18 @@ long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long | |||||||
|         do_exit_task(); |         do_exit_task(); | ||||||
|         break; |         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: { |     case SYS_write: { | ||||||
|         DECL_SYSCALL_ARG(int, fd, arg0); |         DECL_SYSCALL_ARG(int, fd, arg0); | ||||||
|         DECL_SYSCALL_ARG(const void*, buf, arg1); |         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); |         ret = rusgx_write(fd, buf, buf_size); | ||||||
|         break; |         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: { |     case SYS_spawn: { | ||||||
|         DECL_SYSCALL_ARG(int*, child_pid, arg0); |         DECL_SYSCALL_ARG(int*, child_pid, arg0); | ||||||
|         DECL_SYSCALL_ARG(const char*, path, arg1); |         DECL_SYSCALL_ARG(const char*, path, arg1); | ||||||
|  | |||||||
| @ -1,11 +1,11 @@ | |||||||
| /// Virtuam Memory Area (VMA)
 | /// Virtuam Memory Area (VMA)
 | ||||||
|  | use prelude::*; | ||||||
|  | use {std}; | ||||||
| 
 | 
 | ||||||
| use xmas_elf::program; | use xmas_elf::program; | ||||||
| use xmas_elf::program::{ProgramHeader}; | use xmas_elf::program::{ProgramHeader}; | ||||||
| use std; | 
 | ||||||
| use std::sync::Arc; |  | ||||||
| use mm::MemObj; | use mm::MemObj; | ||||||
| use sgx_types::*; |  | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug, Default)] | #[derive(Clone, Debug, Default)] | ||||||
| #[repr(C)] | #[repr(C)] | ||||||
| @ -31,11 +31,11 @@ const VMA_MIN_MEM_ALIGN: usize = (4 * 1024); | |||||||
| 
 | 
 | ||||||
| impl Vma { | impl Vma { | ||||||
|     pub fn from_program_header<'a>(ph: &ProgramHeader<'a>) |     pub fn from_program_header<'a>(ph: &ProgramHeader<'a>) | ||||||
|         -> Result<Vma, &'static str> |         -> Result<Vma, Error> | ||||||
|     { |     { | ||||||
|         let ph64 = match ph { |         let ph64 = match ph { | ||||||
|             ProgramHeader::Ph32(ph) => { |             ProgramHeader::Ph32(ph) => { | ||||||
|                 return Err("Not support 32-bit ELF") |                 return Err((Errno::ENOEXEC, "Not support 32-bit ELF").into()) | ||||||
|             } |             } | ||||||
|             ProgramHeader::Ph64(ph64) => { |             ProgramHeader::Ph64(ph64) => { | ||||||
|                 ph64 |                 ph64 | ||||||
| @ -43,10 +43,12 @@ impl Vma { | |||||||
|         }; |         }; | ||||||
|         if ph64.align > 1 && ((ph64.offset % ph64.align) != |         if ph64.align > 1 && ((ph64.offset % ph64.align) != | ||||||
|                               (ph64.virtual_addr % ph64.align)) { |                               (ph64.virtual_addr % ph64.align)) { | ||||||
|             return Err("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 { |         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, |         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) |     pub fn new(mem_size: usize, mem_align: usize, mem_flags: Perms) | ||||||
|         -> Result<Self, &'static str> |         -> Result<Self, Error> | ||||||
|     { |     { | ||||||
|         if mem_align == 0 || mem_align % VMA_MIN_MEM_ALIGN != 0 { |         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 { |         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 { |         Ok(Vma { | ||||||
| @ -85,7 +89,7 @@ impl Vma { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn malloc_batch(vma_list: &mut [&mut Vma], mapped_data: &[u8]) | pub fn malloc_batch(vma_list: &mut [&mut Vma], mapped_data: &[u8]) | ||||||
|     -> Result<usize, &'static str> |     -> Result<usize, Error> | ||||||
| { | { | ||||||
|     let mut max_align = VMA_MIN_MEM_ALIGN; |     let mut max_align = VMA_MIN_MEM_ALIGN; | ||||||
|     let mut total_size = 0; |     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.file_is_mapped { | ||||||
|             if vma.mem_addr < mem_begin || |             if vma.mem_addr < mem_begin || | ||||||
|                 vma.mem_addr + vma.mem_size > mem_end { |                 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() || |             if vma.file_offset > mapped_data.len() || | ||||||
|                 vma.file_offset + vma.file_size > 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]) | pub fn mprotect_batch(vma_list: &[&Vma]) | ||||||
|     -> Result<(), &'static str> |     -> Result<(), Error> | ||||||
| { | { | ||||||
|     for vma in vma_list.into_iter() { |     for vma in vma_list.into_iter() { | ||||||
|         // If don't need to change memory permissions
 |         // 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) |             trts_mprotect(start, size, (PERM_R | PERM_W | PERM_X) as uint64_t) | ||||||
|         }; |         }; | ||||||
|         if (status != sgx_status_t::SGX_SUCCESS) { |         if (status != sgx_status_t::SGX_SUCCESS) { | ||||||
|             return Err("trts_mprotect failed"); |             return Err((Errno::EACCES, "trts_mprotect failed").into()); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     Ok(()) |     Ok(()) | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) | CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) | ||||||
| PROJECT_DIR := $(realpath $(CUR_DIR)/../) | 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:%=%) | BUILD_TEST_SUITES := $(TEST_SUITES:%=%) | ||||||
| RUN_TEST_SUITES := $(TEST_SUITES:%=run-%) | RUN_TEST_SUITES := $(TEST_SUITES:%=run-%) | ||||||
| CLEAN_TEST_SUITES := $(TEST_SUITES:%=clean-%) | CLEAN_TEST_SUITES := $(TEST_SUITES:%=clean-%) | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								test/file_io/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										4
									
								
								test/file_io/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | |||||||
|  | include ../test_common.mk | ||||||
|  | 
 | ||||||
|  | EXTRA_C_FLAGS := -fno-builtin | ||||||
|  | EXTRA_LINK_FLAGS := -nostdlib | ||||||
							
								
								
									
										66
									
								
								test/file_io/main.c
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										66
									
								
								test/file_io/main.c
									
									
									
									
									
										Normal file
									
								
							| @ -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); | ||||||
|  | } | ||||||
| @ -20,12 +20,32 @@ | |||||||
|  *  host syscalls provided by the default implementation of this library. |  *  host syscalls provided by the default implementation of this library. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #define SYS_read    0 | ||||||
| #define SYS_write   1 | #define SYS_write   1 | ||||||
|  | #define SYS_open    2 | ||||||
|  | #define SYS_close   3 | ||||||
| #define SYS_getpid  39 | #define SYS_getpid  39 | ||||||
| #define SYS_exit    60 | #define SYS_exit    60 | ||||||
| #define SYS_wait4   61 | #define SYS_wait4   61 | ||||||
| #define SYS_spawn   360 | #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); | long rusgx_syscall(int num, long arg0, long arg1, long arg2, long arg3, long arg4); | ||||||
| 
 | 
 | ||||||
| #define RUSGX_SYSCALL0(num) \ | #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) \ | #define RUSGX_SYSCALL5(num, arg0, arg1, arg2, arg3, arg4) \ | ||||||
|     rusgx_syscall((num), (long)(arg0), (long)(arg1), (long)(arg2), (long)(arg3), (long)(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) { | static inline ssize_t __rusgx_write(int fd, const void* buf, unsigned long size) { | ||||||
|     return (ssize_t) RUSGX_SYSCALL3(SYS_write, fd, buf, 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) { | static inline unsigned int __rusgx_getpid(void) { | ||||||
|     return (unsigned int) RUSGX_SYSCALL0(SYS_getpid); |     return (unsigned int) RUSGX_SYSCALL0(SYS_getpid); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,16 @@ | |||||||
| #include "rusgx_stub.h" | #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) { | static long __write(int fd, const void* buf, unsigned long size) { | ||||||
|     long ret; |     long ret; | ||||||
|     __asm__ __volatile__ ( |     __asm__ __volatile__ ( | ||||||
| @ -11,6 +22,27 @@ static long __write(int fd, const void* buf, unsigned long size) { | |||||||
|     return ret; |     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) { | static void __exit(int status) { | ||||||
|     __asm__ __volatile__ ( |     __asm__ __volatile__ ( | ||||||
|         "syscall" |         "syscall" | ||||||
| @ -26,9 +58,18 @@ long rusgx_syscall(int num, long arg0, long arg1, long arg2, long arg3, long arg | |||||||
|     case SYS_exit: |     case SYS_exit: | ||||||
|         __exit((int)arg0); |         __exit((int)arg0); | ||||||
|         break; |         break; | ||||||
|  |     case SYS_read: | ||||||
|  |         ret = __read((int)arg0, (void*)arg1, (unsigned long)arg2); | ||||||
|  |         break; | ||||||
|     case SYS_write: |     case SYS_write: | ||||||
|         ret = __write((int)arg0, (const void*)arg1, (unsigned long)arg2); |         ret = __write((int)arg0, (const void*)arg1, (unsigned long)arg2); | ||||||
|         break; |         break; | ||||||
|  |     case SYS_open: | ||||||
|  |         ret = __open((const char*)arg0, (int)arg1, (int)arg2); | ||||||
|  |         break; | ||||||
|  |     case SYS_close: | ||||||
|  |         ret = __close((int)arg0); | ||||||
|  |         break; | ||||||
|     default: |     default: | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user