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();
|
|
||||||
/*
|
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_program_headers(&elf_file)?;
|
||||||
elf_helper::print_sections(&elf_file)?;
|
elf_helper::print_sections(&elf_file)?;
|
||||||
elf_helper::print_pltrel_section(&elf_file)?;
|
elf_helper::print_pltrel_section(&elf_file)?;
|
||||||
*/
|
*/
|
||||||
let new_process = Process::new(&elf_file)?;
|
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 new_process = {
|
||||||
put_into_pid_table(*new_pid, 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
|
0
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
e.errno.as_retval()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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