Load and run a Hello World program
This commit is contained in:
parent
1428cff243
commit
7671dbf470
5
.gitmodules
vendored
5
.gitmodules
vendored
@ -1,4 +1,7 @@
|
|||||||
[submodule "deps/rust-sgx-sdk"]
|
[submodule "deps/rust-sgx-sdk"]
|
||||||
path = deps/rust-sgx-sdk
|
path = deps/rust-sgx-sdk
|
||||||
url = https://github.com/baidu/rust-sgx-sdk
|
url = https://github.com/baidu/rust-sgx-sdk
|
||||||
branch = rust-stable
|
branch = master
|
||||||
|
[submodule "deps/sgx_protect_file"]
|
||||||
|
path = deps/sgx_protect_file
|
||||||
|
url = https://github.com/tatetian/sgx_protect_file
|
||||||
|
3
Makefile
3
Makefile
@ -5,7 +5,8 @@ all: build_src build_test
|
|||||||
init:
|
init:
|
||||||
git submodule init
|
git submodule init
|
||||||
git submodule update
|
git submodule update
|
||||||
cd deps/rust-sgx-sdk && git apply ../rust-sgx-sdk.patch
|
#cd deps/rust-sgx-sdk && git apply ../rust-sgx-sdk.patch
|
||||||
|
cd deps/sgx_protect_file && make
|
||||||
|
|
||||||
build_src:
|
build_src:
|
||||||
@$(MAKE) --no-print-directory -C src
|
@$(MAKE) --no-print-directory -C src
|
||||||
|
@ -6,7 +6,7 @@ Rusgx is a single-address-space library OS for Intel SGX. It is written in Rust
|
|||||||
|
|
||||||
### Prerequisite
|
### Prerequisite
|
||||||
|
|
||||||
Rusgx depends on [Rust SGX SDK](https://github.com/baidu/rust-sgx-sdk/). So, make sure Rust SGX SDk can be built properly. We have tested with Rust SGX SDK 1.0, Rust 1.26.0 and Intel SGX SDK 2.1 on Ubuntu 16.04.
|
Rusgx depends on [Rust SGX SDK](https://github.com/baidu/rust-sgx-sdk/). So, make sure Rust SGX SDk can be built properly. We have tested with Rust SGX SDK 1.1, Rust nightly-2018-08-25 and Intel SGX SDK 2.2 on Ubuntu 16.04.
|
||||||
|
|
||||||
### Compile
|
### Compile
|
||||||
|
|
||||||
|
2
deps/rust-sgx-sdk
vendored
2
deps/rust-sgx-sdk
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 32fa6b14326fcf8390891a4c5c86b755fc29d24f
|
Subproject commit f26dcd8f5fce88780c83a7c54b774e6e9d36aa23
|
46
deps/rust-sgx-sdk.patch
vendored
46
deps/rust-sgx-sdk.patch
vendored
@ -1,46 +0,0 @@
|
|||||||
diff --git a/sgx_tstd/src/lib.rs b/sgx_tstd/src/lib.rs
|
|
||||||
index 33ee1f2..7f3dab8 100644
|
|
||||||
--- a/sgx_tstd/src/lib.rs
|
|
||||||
+++ b/sgx_tstd/src/lib.rs
|
|
||||||
@@ -222,6 +222,11 @@ pub mod untrusted;
|
|
||||||
mod sys_common;
|
|
||||||
mod sys;
|
|
||||||
|
|
||||||
+// @tatetian
|
|
||||||
+// Export some internals of sys so that libos can use them directly
|
|
||||||
+pub use sys::fs::libc as libc_fs;
|
|
||||||
+pub use sys::fd::libc as libc_io;
|
|
||||||
+
|
|
||||||
// Private support modules
|
|
||||||
mod panicking;
|
|
||||||
mod cpuid;
|
|
||||||
diff --git a/sgx_tstd/src/sys/fd.rs b/sgx_tstd/src/sys/fd.rs
|
|
||||||
index 3fa46d9..28daa9b 100644
|
|
||||||
--- a/sgx_tstd/src/sys/fd.rs
|
|
||||||
+++ b/sgx_tstd/src/sys/fd.rs
|
|
||||||
@@ -209,7 +209,9 @@ impl Drop for FileDesc {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-mod libc {
|
|
||||||
+// @tatetian
|
|
||||||
+// Make this public so that the libos can use it directly
|
|
||||||
+pub mod libc {
|
|
||||||
use sgx_types::sgx_status_t;
|
|
||||||
use io;
|
|
||||||
pub use sgx_trts::libc::*;
|
|
||||||
diff --git a/sgx_tstd/src/sys/fs.rs b/sgx_tstd/src/sys/fs.rs
|
|
||||||
index a611f39..cc54c31 100644
|
|
||||||
--- a/sgx_tstd/src/sys/fs.rs
|
|
||||||
+++ b/sgx_tstd/src/sys/fs.rs
|
|
||||||
@@ -455,7 +455,9 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
|
||||||
Ok(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
-mod libc {
|
|
||||||
+// @tatetian
|
|
||||||
+// Make this public so that the libos can use it directly
|
|
||||||
+pub mod libc {
|
|
||||||
use sgx_types::sgx_status_t;
|
|
||||||
use io;
|
|
||||||
use core::ptr;
|
|
1
deps/sgx_protect_file
vendored
Submodule
1
deps/sgx_protect_file
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 3c9a9f063dacf5ef98971e64338d315e107a9083
|
@ -5,13 +5,15 @@ enclave {
|
|||||||
from "sgx_tstd.edl" import *;
|
from "sgx_tstd.edl" import *;
|
||||||
from "sgx_net.edl" import *;
|
from "sgx_net.edl" import *;
|
||||||
from "sgx_time.edl" import *;
|
from "sgx_time.edl" import *;
|
||||||
|
from "sgx_tprotected_fs.edl" import *;
|
||||||
|
|
||||||
trusted {
|
trusted {
|
||||||
/* define ECALLs here. */
|
/* define ECALLs here. */
|
||||||
public int libos_boot(void);
|
public int libos_boot([in, string] const char* executable_path);
|
||||||
|
public int libos_run(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
untrusted {
|
untrusted {
|
||||||
|
void ocall_print_string([in, string] const char* msg);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
79
src/libos/Cargo.lock
generated
79
src/libos/Cargo.lock
generated
@ -1,16 +1,28 @@
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "Rusgx"
|
name = "Rusgx"
|
||||||
version = "1.0.0"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"sgx_tstd 1.0.0",
|
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"sgx_types 1.0.0",
|
"sgx_trts 1.0.1",
|
||||||
|
"sgx_tstd 1.0.1",
|
||||||
|
"sgx_types 1.0.1",
|
||||||
|
"xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sgx_alloc"
|
name = "sgx_alloc"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"sgx_trts 1.0.0",
|
"sgx_trts 1.0.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -19,39 +31,68 @@ version = "0.1.0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sgx_tprotected_fs"
|
name = "sgx_tprotected_fs"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"sgx_trts 1.0.0",
|
"sgx_trts 1.0.1",
|
||||||
"sgx_types 1.0.0",
|
"sgx_types 1.0.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sgx_trts"
|
name = "sgx_trts"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"sgx_types 1.0.0",
|
"sgx_types 1.0.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sgx_tstd"
|
name = "sgx_tstd"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"sgx_alloc 1.0.0",
|
"sgx_alloc 1.0.1",
|
||||||
"sgx_build_helper 0.1.0",
|
"sgx_build_helper 0.1.0",
|
||||||
"sgx_tprotected_fs 1.0.0",
|
"sgx_tprotected_fs 1.0.1",
|
||||||
"sgx_trts 1.0.0",
|
"sgx_trts 1.0.1",
|
||||||
"sgx_types 1.0.0",
|
"sgx_types 1.0.1",
|
||||||
"sgx_unwind 0.0.0",
|
"sgx_unwind 0.0.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sgx_types"
|
name = "sgx_types"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sgx_unwind"
|
name = "sgx_unwind"
|
||||||
version = "0.0.0"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"sgx_trts 1.0.0",
|
"sgx_trts 1.0.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xmas-elf"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"zero 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zero"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7"
|
||||||
|
"checksum spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "37b5646825922b96b5d7d676b5bb3458a54498e96ed7b0ce09dc43a07038fea4"
|
||||||
|
"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051"
|
||||||
|
"checksum xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22678df5df766e8d1e5d609da69f0c3132d794edf6ab5e75e7abcd2270d4cf58"
|
||||||
|
"checksum zero 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f1bc8a6b2005884962297587045002d8cfb8dcec9db332f4ca216ddc5de82c5"
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "Rusgx"
|
name = "Rusgx"
|
||||||
version = "1.0.0"
|
version = "0.0.1"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "rusgx"
|
name = "libos"
|
||||||
crate-type = ["staticlib"]
|
crate-type = ["staticlib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
xmas-elf = "0.6"
|
||||||
|
lazy_static = { version = "1.1.0", features = ["spin_no_std"] } # Implies nightly
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
|
||||||
[target.'cfg(not(target_env = "sgx"))'.dependencies]
|
[target.'cfg(not(target_env = "sgx"))'.dependencies]
|
||||||
sgx_types = { path = "../../deps/rust-sgx-sdk/sgx_types" }
|
sgx_types = { path = "../../deps/rust-sgx-sdk/sgx_types" }
|
||||||
sgx_tstd = { path = "../../deps/rust-sgx-sdk/sgx_tstd" }
|
sgx_tstd = { path = "../../deps/rust-sgx-sdk/sgx_tstd", features = ["backtrace"] }
|
||||||
|
sgx_trts = { path = "../../deps/rust-sgx-sdk/sgx_trts" }
|
||||||
|
@ -1,14 +1,63 @@
|
|||||||
LIB_NAME := librusgx.a
|
include ../sgxenv.mk
|
||||||
SRCS := $(wildcard src/*.rs)
|
|
||||||
|
|
||||||
.PHONY: all clean
|
DEBUG=1
|
||||||
|
|
||||||
all: $(LIB_NAME)
|
LIBOS_ENCLAVE := librusgx.signed.so
|
||||||
|
LIBOS_SO := librusgx.so # Link $(LIBOS_A), $(C_OBJS) and all dependencies
|
||||||
|
LIBOS_A := liblibos.a # Built from Rust code
|
||||||
|
|
||||||
$(LIB_NAME): $(SRCS)
|
RUST_SRCS := $(wildcard src/*.rs)
|
||||||
|
C_SRCS := $(sort $(filter-out src/Enclave_t.c, $(wildcard src/*.c))) src/Enclave_t.c
|
||||||
|
C_OBJS := $(C_SRCS:.c=.o)
|
||||||
|
S_SRCS := $(wildcard src/*.S)
|
||||||
|
S_OBJS := $(S_SRCS:.S=.o)
|
||||||
|
EDL_C_SRCS := src/Enclave_t.c src/Enclave_t.h
|
||||||
|
|
||||||
|
ENCLAVE_CONFIG := Enclave_config.xml
|
||||||
|
ENCLAVE_KEY := Enclave_private.pem
|
||||||
|
|
||||||
|
C_FLAGS := $(SGX_CFLAGS_T) -fno-stack-protector
|
||||||
|
_Other_Link_Flags := -L../../deps/rust-sgx-sdk/compiler-rt/ -L.
|
||||||
|
_Other_Enclave_Libs := -lcompiler-rt-patch -llibos -lsgx_tprotected_fs
|
||||||
|
LINK_FLAGS := $(SGX_LFLAGS_T)
|
||||||
|
|
||||||
|
.PHONY: all compiler-rt clean
|
||||||
|
|
||||||
|
all: $(LIBOS_ENCLAVE)
|
||||||
|
|
||||||
|
$(LIBOS_ENCLAVE): $(LIBOS_SO)
|
||||||
|
@$(SGX_ENCLAVE_SIGNER) sign -key $(ENCLAVE_KEY) -enclave $^ -out $@ -config $(ENCLAVE_CONFIG)
|
||||||
|
@echo "SIGN => $@"
|
||||||
|
|
||||||
|
$(LIBOS_SO): compiler-rt $(LIBOS_A) $(C_OBJS) $(S_OBJS)
|
||||||
|
@$(CC) $(C_OBJS) $(S_OBJS) -o $@ $(LINK_FLAGS)
|
||||||
|
@echo "LINK => $@"
|
||||||
|
|
||||||
|
$(C_OBJS): %.o: %.c
|
||||||
|
@$(CC) $(C_FLAGS) -c $< -o $@
|
||||||
|
@echo "CC <= $@"
|
||||||
|
|
||||||
|
$(S_OBJS): %.o: %.S
|
||||||
|
@$(CC) $(C_FLAGS) -c $< -o $@
|
||||||
|
@echo "CC <= $@"
|
||||||
|
|
||||||
|
$(EDL_C_SRCS): $(SGX_EDGER8R) ../Enclave.edl
|
||||||
|
@cd src/ && $(SGX_EDGER8R) --trusted ../../Enclave.edl --search-path $(SGX_SDK)/include --search-path ../../../deps/rust-sgx-sdk/edl/
|
||||||
|
@echo "GEN => $(EDL_C_SRCS)"
|
||||||
|
|
||||||
|
compiler-rt:
|
||||||
|
@$(MAKE) --no-print-directory -C ../../deps/rust-sgx-sdk/compiler-rt/ 2> /dev/null
|
||||||
|
|
||||||
|
ifeq ($(DEBUG), 1)
|
||||||
|
$(LIBOS_A): $(RUST_SRCS)
|
||||||
|
RUSTC_BOOTSTRAP=1 cargo build
|
||||||
|
cp ./target/debug/$(LIBOS_A) $(LIBOS_A)
|
||||||
|
else
|
||||||
|
$(LIBOS_A): $(RUST_SRCS)
|
||||||
RUSTC_BOOTSTRAP=1 cargo build --release
|
RUSTC_BOOTSTRAP=1 cargo build --release
|
||||||
cp ./target/release/$(LIB_NAME) $(LIB_NAME)
|
cp ./target/release/$(LIBOS_A) $(LIBOS_A)
|
||||||
|
endif
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@cargo clean
|
@cargo clean
|
||||||
@-$(RM) $(LIB_NAME)
|
@-$(RM) $(LIBOS_ENCLAVE) $(LIBOS_SO) $(LIBOS_A) $(C_OBJS) $(S_OBJS) $(EDL_C_SRCS)
|
||||||
|
126
src/libos/src/elf_helper.rs
Normal file
126
src/libos/src/elf_helper.rs
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
use xmas_elf::{ElfFile, program, P64};
|
||||||
|
use xmas_elf::sections;
|
||||||
|
use xmas_elf::symbol_table::{Entry64, DynEntry64};
|
||||||
|
use xmas_elf::program::{ProgramHeader};
|
||||||
|
use xmas_elf::sections::{Rela};
|
||||||
|
use xmas_elf::symbol_table::Entry;
|
||||||
|
|
||||||
|
pub fn print_program_headers(elf_file: &ElfFile) -> Result<(), &'static str> {
|
||||||
|
println!("Program headers:");
|
||||||
|
let ph_iter = elf_file.program_iter();
|
||||||
|
for sect in ph_iter {
|
||||||
|
program::sanity_check(sect, &elf_file)?;
|
||||||
|
println!("\t{:?}", sect.get_type());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_sections(elf_file: &ElfFile) -> Result<(), &'static str> {
|
||||||
|
println!("Sections:");
|
||||||
|
let mut sect_iter = elf_file.section_iter();
|
||||||
|
sect_iter.next(); // Skip the first, dummy section
|
||||||
|
for sect in sect_iter {
|
||||||
|
sections::sanity_check(sect, &elf_file)?;
|
||||||
|
println!("\t{}\n{:?}", sect.get_name(&elf_file)?, sect);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_pltrel_section(elf_file: &ElfFile) -> Result<(), &'static str> {
|
||||||
|
let rela_entries = get_pltrel_entries(elf_file)?;
|
||||||
|
let dynsym_entries = get_dynsym_entries(elf_file)?;
|
||||||
|
|
||||||
|
println!(".plt.rela section:");
|
||||||
|
for entry in rela_entries {
|
||||||
|
println!("\toffset: {}, symbol index: {}, type: {}, addend: {}",
|
||||||
|
entry.get_offset(),
|
||||||
|
entry.get_symbol_table_index(),
|
||||||
|
entry.get_type(),
|
||||||
|
entry.get_addend());
|
||||||
|
|
||||||
|
let symidx = entry.get_symbol_table_index() as usize;
|
||||||
|
let dynsym_entry = &dynsym_entries[symidx];
|
||||||
|
println!("\t\t{} = {:?}",
|
||||||
|
dynsym_entry.get_name(&elf_file)?, dynsym_entry);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_data_program_header<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>)
|
||||||
|
-> Result<ProgramHeader<'a>, &'static str>
|
||||||
|
{
|
||||||
|
let mut ph_iter = elf_file.program_iter();
|
||||||
|
ph_iter.find(|&ph| ph.get_type() == Ok(program::Type::Load) &&
|
||||||
|
!ph.flags().is_execute() &&
|
||||||
|
ph.flags().is_write() &&
|
||||||
|
ph.flags().is_read())
|
||||||
|
.ok_or("Cannot find .data in the program header of ELF")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_code_program_header<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>)
|
||||||
|
-> Result<ProgramHeader<'a>, &'static str>
|
||||||
|
{
|
||||||
|
let mut ph_iter = elf_file.program_iter();
|
||||||
|
ph_iter.find(|&ph| ph.get_type() == Ok(program::Type::Load) &&
|
||||||
|
ph.flags().is_execute() &&
|
||||||
|
!ph.flags().is_write() &&
|
||||||
|
ph.flags().is_read())
|
||||||
|
.ok_or("Cannot find .text in the program header of ELF")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_start_address<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>)
|
||||||
|
-> Result<usize, &'static str>
|
||||||
|
{
|
||||||
|
let sym_entries = get_sym_entries(elf_file)?;
|
||||||
|
|
||||||
|
for sym_entry in sym_entries {
|
||||||
|
let sym_str = sym_entry.get_name(elf_file)?;
|
||||||
|
if sym_str == "_start" {
|
||||||
|
return Ok(sym_entry.value() as usize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err("Cannot find _start symbol")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_sym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>)
|
||||||
|
-> Result<&'a [Entry64], &'static str>
|
||||||
|
{
|
||||||
|
elf_file.find_section_by_name(".symtab")
|
||||||
|
.and_then(|symtab_section| {
|
||||||
|
symtab_section.get_data(&elf_file).ok()
|
||||||
|
}).and_then(|symbol_table| {
|
||||||
|
match symbol_table {
|
||||||
|
sections::SectionData::SymbolTable64(entries) => Some(entries),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}).ok_or("Cannot find or load .dynsym section")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_pltrel_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>)
|
||||||
|
-> Result<&'a [Rela<P64>], &'static str>
|
||||||
|
{
|
||||||
|
elf_file.find_section_by_name(".rela.plt")
|
||||||
|
.and_then(|plt_rela_section| {
|
||||||
|
plt_rela_section.get_data(&elf_file).ok()
|
||||||
|
}).and_then(|rela_table| {
|
||||||
|
match rela_table {
|
||||||
|
sections::SectionData::Rela64(entries) => Some(entries),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}).ok_or("Cannot find or load .rela.plt section")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_dynsym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>)
|
||||||
|
-> Result<&'a [DynEntry64], &'static str>
|
||||||
|
{
|
||||||
|
elf_file.find_section_by_name(".dynsym")
|
||||||
|
.and_then(|dynamic_section| {
|
||||||
|
dynamic_section.get_data(&elf_file).ok()
|
||||||
|
}).and_then(|dynamic_table| {
|
||||||
|
match dynamic_table {
|
||||||
|
sections::SectionData::DynSymbolTable64(entries) => Some(entries),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}).ok_or("Cannot find or load .dynsym section")
|
||||||
|
}
|
@ -1,24 +1,67 @@
|
|||||||
#![crate_name = "rusgx"]
|
#![allow(unused)]
|
||||||
|
|
||||||
|
#![crate_name = "libos"]
|
||||||
#![crate_type = "staticlib"]
|
#![crate_type = "staticlib"]
|
||||||
|
|
||||||
#![cfg_attr(not(target_env = "sgx"), no_std)]
|
#![cfg_attr(not(target_env = "sgx"), no_std)]
|
||||||
#![cfg_attr(target_env = "sgx", feature(rustc_private))]
|
#![cfg_attr(target_env = "sgx", feature(rustc_private))]
|
||||||
|
#![feature(allocator_api)]
|
||||||
|
#![feature(integer_atomics)]
|
||||||
|
|
||||||
extern crate sgx_types;
|
extern crate sgx_types;
|
||||||
#[cfg(not(target_env = "sgx"))]
|
#[cfg(not(target_env = "sgx"))]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate sgx_tstd as std;
|
extern crate sgx_tstd as std;
|
||||||
use sgx_types::*;
|
extern crate sgx_trts;
|
||||||
|
extern crate xmas_elf;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate lazy_static;
|
||||||
|
|
||||||
extern "C" {
|
use std::ffi::CStr; // a borrowed C string
|
||||||
pub fn main() -> c_int;
|
use std::backtrace::{self, PrintFormat};
|
||||||
|
use std::panic;
|
||||||
|
|
||||||
|
use sgx_types::*;
|
||||||
|
use sgx_trts::libc;
|
||||||
|
|
||||||
|
mod vma;
|
||||||
|
mod process;
|
||||||
|
mod syscall;
|
||||||
|
mod elf_helper;
|
||||||
|
mod mm;
|
||||||
|
|
||||||
|
use process::spawn_process;
|
||||||
|
use process::run_task;
|
||||||
|
|
||||||
|
/// Export system calls
|
||||||
|
pub use syscall::{rusgx_write};
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn libos_boot(path_buf: *const i8) -> i32 {
|
||||||
|
let path_str = unsafe {
|
||||||
|
CStr::from_ptr(path_buf).to_string_lossy().into_owned()
|
||||||
|
};
|
||||||
|
println!("LibOS boots: {}", path_str);
|
||||||
|
|
||||||
|
let _ = backtrace::enable_backtrace("librusgx.signed.so", PrintFormat::Short);
|
||||||
|
panic::catch_unwind(||{
|
||||||
|
backtrace::__rust_begin_short_backtrace(||{
|
||||||
|
let _ = spawn_process(&path_str);
|
||||||
|
})
|
||||||
|
}).ok();
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn libos_boot() -> sgx_status_t {
|
pub extern "C" fn libos_run() -> i32 {
|
||||||
println!("{}", "LibOS boots");
|
let _ = backtrace::enable_backtrace("librusgx.signed.so", PrintFormat::Short);
|
||||||
unsafe { main(); }
|
panic::catch_unwind(||{
|
||||||
sgx_status_t::SGX_SUCCESS
|
backtrace::__rust_begin_short_backtrace(||{
|
||||||
|
let _ = run_task();
|
||||||
|
})
|
||||||
|
}).ok();
|
||||||
|
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod syscall;
|
|
||||||
|
84
src/libos/src/mm.rs
Normal file
84
src/libos/src/mm.rs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
use sgx_types::{c_void, c_int, size_t};
|
||||||
|
use sgx_trts::libc;
|
||||||
|
use std::mem;
|
||||||
|
use std::marker::Send;
|
||||||
|
use std::marker::Sync;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct MemObj {
|
||||||
|
mem_ptr: *mut c_void,
|
||||||
|
mem_size: usize,
|
||||||
|
mem_align: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemObj {
|
||||||
|
pub fn new(mem_size: usize, mem_align: usize)
|
||||||
|
-> Result<Self, &'static str>
|
||||||
|
{
|
||||||
|
if mem_size == 0 || !is_power_of_two(mem_align) ||
|
||||||
|
mem_align % mem::size_of::<*const c_void>() != 0 {
|
||||||
|
return Err("Invalid argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mem_ptr = unsafe { aligned_malloc(mem_size, mem_align) };
|
||||||
|
if mem_ptr == (0 as *mut c_void) {
|
||||||
|
return Err("Out of memory");
|
||||||
|
};
|
||||||
|
unsafe { memset(mem_ptr, 0 as c_int, mem_size as size_t) };
|
||||||
|
|
||||||
|
Ok(MemObj {
|
||||||
|
mem_ptr: mem_ptr,
|
||||||
|
mem_size: mem_size,
|
||||||
|
mem_align: mem_align,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_addr(&self) -> usize {
|
||||||
|
self.mem_ptr as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for MemObj {
|
||||||
|
fn default() -> Self {
|
||||||
|
MemObj {
|
||||||
|
mem_ptr: 0 as *mut c_void,
|
||||||
|
mem_size: 0,
|
||||||
|
mem_align: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for MemObj {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.mem_ptr != (0 as *mut c_void) {
|
||||||
|
unsafe { free(self.mem_ptr); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for MemObj {}
|
||||||
|
unsafe impl Sync for MemObj {}
|
||||||
|
|
||||||
|
|
||||||
|
fn is_power_of_two(x: usize) -> bool {
|
||||||
|
return (x != 0) && ((x & (x - 1)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn aligned_malloc(mem_size: usize, mem_align: usize) -> *mut c_void {
|
||||||
|
let mut mem_ptr = ::core::ptr::null_mut();
|
||||||
|
let ret = libc::posix_memalign(&mut mem_ptr, mem_align, mem_size);
|
||||||
|
if ret == 0 {
|
||||||
|
mem_ptr
|
||||||
|
} else {
|
||||||
|
0 as *mut c_void
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn free(mem_ptr: *mut c_void) {
|
||||||
|
libc::free(mem_ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[link(name = "sgx_tstdc")]
|
||||||
|
extern {
|
||||||
|
pub fn memset(p: *mut c_void, c: c_int, n: size_t) -> *mut c_void;
|
||||||
|
}
|
182
src/libos/src/process.rs
Normal file
182
src/libos/src/process.rs
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
use std;
|
||||||
|
use std::vec::Vec;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::sgxfs::SgxFile;
|
||||||
|
use std::io;
|
||||||
|
use std::io::{Read};
|
||||||
|
|
||||||
|
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;
|
||||||
|
use std::sync::SgxMutex;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
|
||||||
|
//static next_pid : AtomicU32 = AtomicU32::new(42);
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref process_table: SgxMutex<HashMap<u32, Arc<SgxMutex<Process>>>> = {
|
||||||
|
SgxMutex::new(HashMap::new())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn_process<P: AsRef<Path>>(elf_path: &P) -> Result<(), &'static str> {
|
||||||
|
let elf_buf = open_elf(elf_path).unwrap();
|
||||||
|
let elf_file = ElfFile::new(&elf_buf).unwrap();
|
||||||
|
header::sanity_check(&elf_file).unwrap();
|
||||||
|
/*
|
||||||
|
elf_helper::print_program_headers(&elf_file)?;
|
||||||
|
elf_helper::print_sections(&elf_file)?;
|
||||||
|
elf_helper::print_pltrel_section(&elf_file)?;
|
||||||
|
*/
|
||||||
|
let new_process = Process::new(&elf_file)?;
|
||||||
|
println!("new_process: {:#x?}", &new_process);
|
||||||
|
let new_task = Task::from(&new_process);
|
||||||
|
|
||||||
|
process_table.lock().unwrap()
|
||||||
|
.insert(0, Arc::new(SgxMutex::new(new_process)));
|
||||||
|
new_task_queue.lock().unwrap()
|
||||||
|
.push_back(new_task);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_task() -> Result<(), &'static str> {
|
||||||
|
if let Some(new_task) = new_task_queue.lock().unwrap().pop_front() {
|
||||||
|
println!("Run task: {:#x?}", &new_task);
|
||||||
|
println!("do_run_task() begin: {}", do_run_task as *const () as usize);
|
||||||
|
unsafe { do_run_task(&new_task as *const Task); }
|
||||||
|
println!("do_run_task() end");
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn open_elf<P: AsRef<Path>>(path: &P) -> io::Result<Vec<u8>> {
|
||||||
|
let key : sgx_key_128bit_t = [0 as uint8_t; 16];
|
||||||
|
let mut elf_file = SgxFile::open_ex(path, &key)?;
|
||||||
|
|
||||||
|
let mut elf_buf = Vec::<u8>::new();
|
||||||
|
elf_file.read_to_end(&mut elf_buf);
|
||||||
|
Ok(elf_buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Process {
|
||||||
|
pub code_vma: Vma,
|
||||||
|
pub data_vma: Vma,
|
||||||
|
pub stack_vma: Vma,
|
||||||
|
pub program_base_addr: usize,
|
||||||
|
pub program_entry_addr: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Process {
|
||||||
|
pub fn new(elf_file: &ElfFile) -> Result<Process, &'static str> {
|
||||||
|
let mut new_process : Process = Default::default();
|
||||||
|
new_process.create_process_image(elf_file)?;
|
||||||
|
new_process.link_syscalls(elf_file)?;
|
||||||
|
new_process.mprotect()?;
|
||||||
|
Ok(new_process)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_process_image(self: &mut Process, elf_file: &ElfFile)
|
||||||
|
-> Result<(), &'static str>
|
||||||
|
{
|
||||||
|
let code_ph = elf_helper::get_code_program_header(elf_file)?;
|
||||||
|
let data_ph = elf_helper::get_data_program_header(elf_file)?;
|
||||||
|
|
||||||
|
self.code_vma = Vma::from_program_header(&code_ph)?;
|
||||||
|
self.data_vma = Vma::from_program_header(&data_ph)?;
|
||||||
|
self.stack_vma = Vma::new(8 * 1024, 4096,
|
||||||
|
vma::Perms(vma::PERM_R | vma::PERM_W))?;
|
||||||
|
|
||||||
|
self.program_base_addr = self.alloc_mem_for_vmas(elf_file)?;
|
||||||
|
self.program_entry_addr = self.program_base_addr +
|
||||||
|
elf_helper::get_start_address(elf_file)?;
|
||||||
|
if !self.code_vma.contains(self.program_entry_addr) {
|
||||||
|
return Err("Entry address is out of the code segment");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn alloc_mem_for_vmas(self: &mut Process, elf_file: &ElfFile)
|
||||||
|
-> Result<usize, &'static str>
|
||||||
|
{
|
||||||
|
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)?;
|
||||||
|
|
||||||
|
Ok(base_addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn link_syscalls(self: &mut Process, elf_file: &ElfFile)
|
||||||
|
-> Result<(), &'static str>
|
||||||
|
{
|
||||||
|
let syscall_addr = rusgx_syscall as *const () as usize;
|
||||||
|
|
||||||
|
let rela_entries = elf_helper::get_pltrel_entries(&elf_file)?;
|
||||||
|
let dynsym_entries = elf_helper::get_dynsym_entries(&elf_file)?;
|
||||||
|
for rela_entry in rela_entries {
|
||||||
|
let dynsym_idx = rela_entry.get_symbol_table_index() as usize;
|
||||||
|
let dynsym_entry = &dynsym_entries[dynsym_idx];
|
||||||
|
let dynsym_str = dynsym_entry.get_name(&elf_file)?;
|
||||||
|
|
||||||
|
if dynsym_str == "rusgx_syscall" {
|
||||||
|
let rela_addr = self.program_base_addr + rela_entry.get_offset() as usize;
|
||||||
|
unsafe {
|
||||||
|
std::ptr::write_unaligned(rela_addr as *mut usize, syscall_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mprotect(self: &mut Process) -> Result<(), &'static str> {
|
||||||
|
let vma_list = vec![&self.code_vma, &self.data_vma, &self.stack_vma];
|
||||||
|
vma::mprotect_batch(&vma_list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Task {
|
||||||
|
pub pid: u32,
|
||||||
|
pub exit_code: u32,
|
||||||
|
pub syscall_stack_addr: usize,
|
||||||
|
pub user_stack_addr: usize,
|
||||||
|
pub user_entry_addr: usize,
|
||||||
|
pub fs_base_addr: usize,
|
||||||
|
pub saved_state: usize, // struct jmpbuf*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a Process> for Task {
|
||||||
|
fn from(process: &'a Process) -> Task {
|
||||||
|
Task {
|
||||||
|
pid: 1234,
|
||||||
|
user_stack_addr: process.stack_vma.mem_end - 16,
|
||||||
|
user_entry_addr: process.program_entry_addr,
|
||||||
|
fs_base_addr: 0,
|
||||||
|
.. Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref new_task_queue: Arc<SgxMutex<VecDeque<Task>>> = {
|
||||||
|
Arc::new(SgxMutex::new(VecDeque::new()))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
extern {
|
||||||
|
fn do_run_task(task: *const Task) -> i32;
|
||||||
|
fn rusgx_syscall(num: i32, arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64) -> i64;
|
||||||
|
}
|
19
src/libos/src/syscall.h
Normal file
19
src/libos/src/syscall.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef __RUSGX_SYSCALL_H__
|
||||||
|
#define __RUSGX_SYSCALL_H__
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#define SYS_exit 60
|
||||||
|
#define SYS_write 1
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern ssize_t rusgx_write(int fd, const void* buf, size_t size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __RUSGX_SYSCALL_H__ */
|
@ -1,10 +1,11 @@
|
|||||||
use sgx_types::*;
|
use sgx_types::*;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sys_open(path: * const c_char, flags: c_int, mode: c_int) -> c_int {
|
pub unsafe extern "C" fn sys_open(path: * const c_char, flags: c_int, mode: c_int) -> c_int {
|
||||||
fs::open64(path, flags, mode)
|
fs::open64(path, flags, mode)
|
||||||
@ -19,8 +20,11 @@ pub unsafe extern "C" fn sys_close(fd: c_int) -> c_int {
|
|||||||
pub unsafe extern "C" fn sys_read(fd: c_int, buf: * mut c_void, size: size_t) -> ssize_t {
|
pub unsafe extern "C" fn sys_read(fd: c_int, buf: * mut c_void, size: size_t) -> ssize_t {
|
||||||
io::read(fd, buf, size)
|
io::read(fd, buf, size)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sys_write(fd: c_int, buf: * const c_void, size: size_t) -> ssize_t {
|
pub extern fn rusgx_write(fd: c_int, buf: * const c_void, size: size_t) -> ssize_t {
|
||||||
io::write(fd, buf, size)
|
println!("Hello World!");
|
||||||
|
size as ssize_t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
src/libos/src/syscall_entry.c
Normal file
20
src/libos/src/syscall_entry.c
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include "syscall.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long arg4) {
|
||||||
|
long ret = 0;
|
||||||
|
|
||||||
|
switch (num) {
|
||||||
|
case SYS_exit:
|
||||||
|
do_exit_task((int)arg0);
|
||||||
|
break;
|
||||||
|
case SYS_write:
|
||||||
|
ret = (long) rusgx_write((int)arg0, (const void*)arg1, (size_t)arg2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
17
src/libos/src/syscall_entry_x86-64.S
Normal file
17
src/libos/src/syscall_entry_x86-64.S
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#define __ASSEMBLY__
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
.file "syscall_entry_x86-64.S"
|
||||||
|
.global rusgx_syscall
|
||||||
|
.type rusgx_syscall, @function
|
||||||
|
rusgx_syscall:
|
||||||
|
push %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
|
||||||
|
movq %gs:(TD_TASK_OFFSET), %rax
|
||||||
|
movq TASK_SYSCALL_STACK_OFFSET(%rax), %rsp
|
||||||
|
call dispatch_syscall
|
||||||
|
|
||||||
|
movq %rbp, %rsp
|
||||||
|
popq %rbp
|
||||||
|
ret
|
44
src/libos/src/task.c
Normal file
44
src/libos/src/task.c
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
extern void __run_task(uint64_t entry_point, uint64_t stack_top);
|
||||||
|
|
||||||
|
extern uint64_t __get_stack_guard(void);
|
||||||
|
extern void __set_stack_guard(uint64_t new_val);
|
||||||
|
|
||||||
|
static uint64_t get_syscall_stack(struct Task* this_task) {
|
||||||
|
#define LARGE_ENOUGH_GAP 4096
|
||||||
|
char libos_stack_var = 0;
|
||||||
|
uint64_t libos_stack = ((uint64_t) &libos_stack_var) - LARGE_ENOUGH_GAP;
|
||||||
|
libos_stack &= ~0x0FUL; // stack must be 16-byte aligned
|
||||||
|
return libos_stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SET_CURRENT_TASK(task) \
|
||||||
|
long stack_guard = __get_stack_guard(); \
|
||||||
|
__set_current_task(task);
|
||||||
|
|
||||||
|
#define RESET_CURRENT_TASK() \
|
||||||
|
__set_stack_guard(stack_guard);
|
||||||
|
|
||||||
|
|
||||||
|
int do_run_task(struct Task* task) {
|
||||||
|
jmp_buf libos_state = {0};
|
||||||
|
task->saved_state = &libos_state;
|
||||||
|
task->syscall_stack_addr = get_syscall_stack(task);
|
||||||
|
|
||||||
|
SET_CURRENT_TASK(task);
|
||||||
|
|
||||||
|
int second = setjmp(libos_state);
|
||||||
|
if (!second) {
|
||||||
|
__run_task(task->user_entry_addr, task->user_stack_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// From rusgx_exit
|
||||||
|
RESET_CURRENT_TASK();
|
||||||
|
return task->exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_exit_task(int exitcode) {
|
||||||
|
jmp_buf* jb = __get_current_task()->saved_state;
|
||||||
|
longjmp(*jb, 1);
|
||||||
|
}
|
46
src/libos/src/task.h
Normal file
46
src/libos/src/task.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#ifndef __RUSGX_TASK_H__
|
||||||
|
#define __RUSGX_TASK_H__
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
// See Struct Task in process.rs
|
||||||
|
struct Task {
|
||||||
|
uint32_t pid;
|
||||||
|
int32_t exit_code;
|
||||||
|
uint64_t syscall_stack_addr;
|
||||||
|
uint64_t user_stack_addr;
|
||||||
|
uint64_t user_entry_addr;
|
||||||
|
uint64_t fs_base_addr;
|
||||||
|
jmp_buf* saved_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
void __set_current_task(struct Task* task);
|
||||||
|
struct Task* __get_current_task(void);
|
||||||
|
|
||||||
|
int do_run_task(struct Task* task);
|
||||||
|
void do_exit_task(int exitcode);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* __ASSEMBLY__ */
|
||||||
|
|
||||||
|
/* See /<path-to-linux-sgx>/common/inc/internal/thread_data.h */
|
||||||
|
#define TD_STACKGUARD_OFFSET (8 * 5)
|
||||||
|
/* Override the field for stack guard */
|
||||||
|
#define TD_TASK_OFFSET TD_STACKGUARD_OFFSET
|
||||||
|
|
||||||
|
#define TASK_SYSCALL_STACK_OFFSET (8 * 1)
|
||||||
|
|
||||||
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
||||||
|
#endif /* __RUSGX_TASK_H__ */
|
34
src/libos/src/task_x86-64.S
Normal file
34
src/libos/src/task_x86-64.S
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#define __ASSEMBLY__
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
.file "task_x86-64.S"
|
||||||
|
|
||||||
|
.global __set_current_task
|
||||||
|
.type __set_current_task, @function
|
||||||
|
__set_current_task:
|
||||||
|
movq %rdi, %gs:(TD_TASK_OFFSET)
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global __get_current_task
|
||||||
|
.type __get_current_task, @function
|
||||||
|
__get_current_task:
|
||||||
|
movq %gs:(TD_TASK_OFFSET), %rax
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global __get_stack_guard
|
||||||
|
.type __get_stack_guard, @function
|
||||||
|
__get_stack_guard:
|
||||||
|
movq %gs:(TD_TASK_OFFSET), %rax
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global __set_stack_guard
|
||||||
|
.type __set_stack_guard, @function
|
||||||
|
__set_stack_guard:
|
||||||
|
mov %rdi, %gs:(TD_TASK_OFFSET)
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global __run_task
|
||||||
|
.type __run_task, @function
|
||||||
|
__run_task:
|
||||||
|
mov %rsi, %rsp
|
||||||
|
jmp *%rdi
|
192
src/libos/src/vma.rs
Normal file
192
src/libos/src/vma.rs
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
/// Virtuam Memory Area (VMA)
|
||||||
|
|
||||||
|
use xmas_elf::program;
|
||||||
|
use xmas_elf::program::{ProgramHeader};
|
||||||
|
use std;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use mm::MemObj;
|
||||||
|
use sgx_types::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Vma {
|
||||||
|
/// Basic info
|
||||||
|
pub mem_size: usize,
|
||||||
|
pub mem_align: usize,
|
||||||
|
pub mem_flags: Perms,
|
||||||
|
|
||||||
|
/// File mapping
|
||||||
|
pub file_is_mapped: bool,
|
||||||
|
pub mem_addr: usize,
|
||||||
|
pub file_offset: usize,
|
||||||
|
pub file_size: usize,
|
||||||
|
|
||||||
|
/// Memory allocation
|
||||||
|
pub mem_begin: usize,
|
||||||
|
pub mem_end: usize,
|
||||||
|
underlying: Arc<MemObj>,
|
||||||
|
}
|
||||||
|
|
||||||
|
const VMA_MIN_MEM_ALIGN: usize = (4 * 1024);
|
||||||
|
|
||||||
|
impl Vma {
|
||||||
|
pub fn from_program_header<'a>(ph: &ProgramHeader<'a>)
|
||||||
|
-> Result<Vma, &'static str>
|
||||||
|
{
|
||||||
|
let ph64 = match ph {
|
||||||
|
ProgramHeader::Ph32(ph) => {
|
||||||
|
return Err("Not support 32-bit ELF")
|
||||||
|
}
|
||||||
|
ProgramHeader::Ph64(ph64) => {
|
||||||
|
ph64
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if ph64.align > 1 && ((ph64.offset % ph64.align) !=
|
||||||
|
(ph64.virtual_addr % ph64.align)) {
|
||||||
|
return Err("Memory address and file offset is not equal, per modulo");
|
||||||
|
}
|
||||||
|
if ph64.mem_size < ph64.file_size {
|
||||||
|
return Err("Memory size must be greater than file size");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut new_vma = Vma::new(ph64.mem_size as usize,
|
||||||
|
ph64.align as usize,
|
||||||
|
Perms::from(&ph64.flags))?;
|
||||||
|
|
||||||
|
new_vma.mem_addr = ph64.virtual_addr as usize;
|
||||||
|
new_vma.file_is_mapped = true;
|
||||||
|
new_vma.file_offset = ph64.offset as usize;
|
||||||
|
new_vma.file_size = ph64.file_size as usize;
|
||||||
|
|
||||||
|
Ok(new_vma)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(mem_size: usize, mem_align: usize, mem_flags: Perms)
|
||||||
|
-> Result<Self, &'static str>
|
||||||
|
{
|
||||||
|
if mem_align == 0 || mem_align % VMA_MIN_MEM_ALIGN != 0 {
|
||||||
|
return Err("Memory alignment is not a multiple of 4KB");
|
||||||
|
}
|
||||||
|
if mem_size == 0 {
|
||||||
|
return Err("Memory size must be greater than zero");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Vma {
|
||||||
|
mem_size: mem_size,
|
||||||
|
mem_align: mem_align,
|
||||||
|
mem_flags: mem_flags,
|
||||||
|
.. Default::default()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contains(&self, mem_addr: usize) -> bool {
|
||||||
|
self.mem_begin <= mem_addr && mem_addr <= self.mem_end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn malloc_batch(vma_list: &mut [&mut Vma], mapped_data: &[u8])
|
||||||
|
-> Result<usize, &'static str>
|
||||||
|
{
|
||||||
|
let mut max_align = VMA_MIN_MEM_ALIGN;
|
||||||
|
let mut total_size = 0;
|
||||||
|
for vma in vma_list.into_iter() {
|
||||||
|
let mem_begin = round_up(total_size, vma.mem_align);
|
||||||
|
let mem_end = mem_begin + round_up(vma.mem_size, vma.mem_align);
|
||||||
|
|
||||||
|
if vma.file_is_mapped {
|
||||||
|
if vma.mem_addr < mem_begin ||
|
||||||
|
vma.mem_addr + vma.mem_size > mem_end {
|
||||||
|
return Err("Impossible memory layout for the VMA");
|
||||||
|
}
|
||||||
|
if vma.file_offset > mapped_data.len() ||
|
||||||
|
vma.file_offset + vma.file_size > mapped_data.len() {
|
||||||
|
return Err("Impossible to load data from file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
total_size = mem_end;
|
||||||
|
if vma.mem_align > max_align {
|
||||||
|
max_align = vma.mem_align;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let memobj = Arc::new(MemObj::new(total_size, max_align)?);
|
||||||
|
let program_base_addr = memobj.get_addr();
|
||||||
|
let mut mem_cur = program_base_addr;
|
||||||
|
for vma in vma_list.into_iter() {
|
||||||
|
vma.mem_begin = round_up(mem_cur, vma.mem_align);
|
||||||
|
vma.mem_end = vma.mem_begin + round_up(vma.mem_size, vma.mem_align);
|
||||||
|
vma.mem_addr += program_base_addr;
|
||||||
|
vma.underlying = memobj.clone();
|
||||||
|
|
||||||
|
if vma.file_is_mapped {
|
||||||
|
let mut vma_data = unsafe {
|
||||||
|
std::slice::from_raw_parts_mut(vma.mem_addr as *mut u8, vma.file_size)
|
||||||
|
};
|
||||||
|
vma_data.copy_from_slice(&mapped_data[vma.file_offset..
|
||||||
|
vma.file_offset + vma.file_size]);
|
||||||
|
}
|
||||||
|
|
||||||
|
mem_cur = vma.mem_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(program_base_addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mprotect_batch(vma_list: &[&Vma])
|
||||||
|
-> Result<(), &'static str>
|
||||||
|
{
|
||||||
|
for vma in vma_list.into_iter() {
|
||||||
|
let start = vma.mem_begin as size_t;
|
||||||
|
let size = (vma.mem_end - vma.mem_begin) as size_t;
|
||||||
|
let perms = vma.mem_flags.0 as uint64_t;
|
||||||
|
let status = unsafe {
|
||||||
|
trts_mprotect(start, size, perms)
|
||||||
|
};
|
||||||
|
if (status != sgx_status_t::SGX_SUCCESS) {
|
||||||
|
return Err("trts_mprotect failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Default)]
|
||||||
|
pub struct Perms(pub u32);
|
||||||
|
|
||||||
|
pub const PERM_R: u32 = 0x1;
|
||||||
|
pub const PERM_W: u32 = 0x2;
|
||||||
|
pub const PERM_X: u32 = 0x4;
|
||||||
|
|
||||||
|
impl Perms {
|
||||||
|
pub fn is_execute(&self) -> bool {
|
||||||
|
self.0 & PERM_X == PERM_X
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_write(&self) -> bool {
|
||||||
|
self.0 & PERM_W == PERM_W
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_read(&self) -> bool {
|
||||||
|
self.0 & PERM_R == PERM_R
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a program::Flags> for Perms {
|
||||||
|
fn from(flags: &'a program::Flags) -> Self {
|
||||||
|
let mut val = 0;
|
||||||
|
if flags.is_execute() { val |= PERM_X; }
|
||||||
|
if flags.is_read() { val |= PERM_R; }
|
||||||
|
if flags.is_write() { val |= PERM_W; }
|
||||||
|
Perms(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn round_up(addr: usize, align: usize) -> usize {
|
||||||
|
(addr + (align - 1)) / align * align
|
||||||
|
}
|
||||||
|
|
||||||
|
#[link(name = "sgx_trts")]
|
||||||
|
extern {
|
||||||
|
pub fn trts_mprotect(start: size_t, size: size_t, perms: uint64_t) -> sgx_status_t;
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
include ../../buildenv.mk
|
include ../sgxenv.mk
|
||||||
|
|
||||||
EDL_Gen_Files := Enclave_u.c Enclave_u.h
|
EDL_Gen_Files := Enclave_u.c Enclave_u.h
|
||||||
|
|
||||||
@ -8,7 +8,7 @@ Bin := pal
|
|||||||
|
|
||||||
C_Flags := $(SGX_CFLAGS_U)
|
C_Flags := $(SGX_CFLAGS_U)
|
||||||
Link_Flags := $(SGX_LFLAGS_U)
|
Link_Flags := $(SGX_LFLAGS_U)
|
||||||
Link_Flags += -L../../deps/rust-sgx-sdk/sgx_ustdc/ -lsgx_ustdc
|
Link_Flags += -L../../deps/rust-sgx-sdk/sgx_ustdc/ -lsgx_ustdc -lsgx_uprotected_fs
|
||||||
|
|
||||||
|
|
||||||
all: $(Bin)
|
all: $(Bin)
|
||||||
|
@ -187,6 +187,11 @@ int initialize_enclave(const char* enclave_path)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
void ocall_print_string(const char* msg) {
|
||||||
|
printf("%s", msg);
|
||||||
|
}
|
||||||
|
|
||||||
/* Application entry */
|
/* Application entry */
|
||||||
int SGX_CDECL main(int argc, char *argv[])
|
int SGX_CDECL main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -197,11 +202,12 @@ int SGX_CDECL main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
printf("ERROR: The expected number of arguments is 1, but given %d\n\n", argc - 1);
|
printf("ERROR: The expected number of arguments is 1, but given %d\n\n", argc - 1);
|
||||||
printf("Usage: pal <path_to_enclave>\n");
|
printf("Usage: pal <path_to_executable>\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
const char* enclave_path = argv[1];
|
const char* executable_path = argv[1];
|
||||||
|
|
||||||
|
const char* enclave_path = "librusgx.signed.so";
|
||||||
/* Initialize the enclave */
|
/* Initialize the enclave */
|
||||||
if(initialize_enclave(enclave_path) < 0){
|
if(initialize_enclave(enclave_path) < 0){
|
||||||
printf("Enter a character before exit ...\n");
|
printf("Enter a character before exit ...\n");
|
||||||
@ -209,8 +215,13 @@ int SGX_CDECL main(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sgx_ret = libos_boot(global_eid, &exitcode);
|
sgx_ret = libos_boot(global_eid, &exitcode, executable_path);
|
||||||
|
if(sgx_ret != SGX_SUCCESS) {
|
||||||
|
print_error_message(sgx_ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sgx_ret = libos_run(global_eid, &exitcode);
|
||||||
if(sgx_ret != SGX_SUCCESS) {
|
if(sgx_ret != SGX_SUCCESS) {
|
||||||
print_error_message(sgx_ret);
|
print_error_message(sgx_ret);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -69,11 +69,31 @@ endif
|
|||||||
#
|
#
|
||||||
SGX_CFLAGS_T := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector
|
SGX_CFLAGS_T := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector
|
||||||
SGX_CFLAGS_T += -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport -I$(SGX_SDK)/include/epid
|
SGX_CFLAGS_T += -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport -I$(SGX_SDK)/include/epid
|
||||||
# Before use this linker flag, the user should define $(Other_Enclave_Libs),
|
# Before use this linker flag, the user should define $(_Other_Enclave_Libs),
|
||||||
# which lists all libraries that are to be part of the enclave.
|
# and $(_Other_Link_Flags)
|
||||||
SGX_LFLAGS_T = $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) $(Other_Link_Flags) \
|
#
|
||||||
|
# Linker arguments:
|
||||||
|
# --no-undefined: Report unresolved symbols.
|
||||||
|
# --whole-archive <libs> --no-whole-archive: Force including all object files
|
||||||
|
# in the libraries <libs>. Normally, only required object files are included
|
||||||
|
# by the linker.
|
||||||
|
# --start-group <libs> --end-group: Link libraries <libs>, resolve any circular
|
||||||
|
# dependencies between them.
|
||||||
|
# -Bstatic: Do not link against shared libraries.
|
||||||
|
# -Bsymbolic: Bind references to global symbols to the definition within this
|
||||||
|
# shared library.
|
||||||
|
# -pie: Create a position independent executable
|
||||||
|
# --defsym=<symbol>=<value>: Define a symbol with the specified value
|
||||||
|
# --gc-sections: Enable link-time garbage collection, i.e., eliminating unused
|
||||||
|
# sections. See -ffunction-sections and -fdata-section of GCC.
|
||||||
|
#
|
||||||
|
# GCC arguments:
|
||||||
|
# --nostdlib: Do not use system startup files or libraries when linking. Thus,
|
||||||
|
# only the libaries that are explictly specified on the command line are
|
||||||
|
# linked.
|
||||||
|
SGX_LFLAGS_T = $(SGX_COMMON_CFLAGS) -nostdlib -L$(SGX_LIBRARY_PATH) $(_Other_Link_Flags) \
|
||||||
-Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \
|
-Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \
|
||||||
-Wl,--start-group -lsgx_tstdc -lsgx_tstdcxx -l$(Crypto_Library_Name) $(Other_Enclave_Libs) -Wl,--end-group \
|
-Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) $(_Other_Enclave_Libs) -Wl,--end-group \
|
||||||
-Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \
|
-Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \
|
||||||
-Wl,-pie,-eenclave_entry -Wl,--export-dynamic \
|
-Wl,-pie,-eenclave_entry -Wl,--export-dynamic \
|
||||||
-Wl,--defsym,__ImageBase=0 \
|
-Wl,--defsym,__ImageBase=0 \
|
@ -1,67 +1,19 @@
|
|||||||
include ../buildenv.mk
|
.PHONY: all build_rusgx_stub build_src clean test
|
||||||
|
|
||||||
EDL_Gen_Files := Enclave_t.c Enclave_t.h
|
all: build_rusgx_stub build_src
|
||||||
|
|
||||||
Enclave_Config := Enclave_config.xml
|
build_src: build_rusgx_stub
|
||||||
Enclave_Key := Enclave_private.pem
|
@$(MAKE) -C src
|
||||||
|
|
||||||
Test_Srcs := $(sort $(filter-out Enclave_t.c, $(wildcard *.c)))
|
build_rusgx_stub:
|
||||||
Test_Targets := $(Test_Srcs:%.c=test-%)
|
@$(MAKE) -C rusgx_stub
|
||||||
Test_Objs := $(Test_Srcs:.c=.o) Enclave_t.o
|
|
||||||
Test_Enclaves := $(Test_Srcs:.c=.so)
|
|
||||||
Test_Signed_Enclaves := $(Test_Srcs:.c=.signed.so)
|
|
||||||
|
|
||||||
C_Flags := $(SGX_CFLAGS_T)
|
test: all
|
||||||
|
@$(MAKE) -C src test
|
||||||
|
|
||||||
|
test-without-rusgx: all
|
||||||
|
@$(MAKE) -C src test-without-rusgx
|
||||||
|
|
||||||
Other_Link_Flags := -L../deps/rust-sgx-sdk/compiler-rt/ -L../src/libos/
|
|
||||||
Other_Enclave_Libs := -lcompiler-rt-patch -lrusgx
|
|
||||||
Link_Flags := $(SGX_LFLAGS_T)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
all: build
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.PHONY: build
|
|
||||||
build: compiler-rt $(Test_Signed_Enclaves)
|
|
||||||
|
|
||||||
|
|
||||||
$(Test_Signed_Enclaves): %.signed.so: %.so
|
|
||||||
@$(SGX_ENCLAVE_SIGNER) sign -key $(Enclave_Key) -enclave $^ -out $@ -config $(Enclave_Config)
|
|
||||||
@echo "SIGN => $@"
|
|
||||||
|
|
||||||
$(Test_Enclaves): %.so: %.o Enclave_t.o
|
|
||||||
$(CC) $^ -o $@ $(Link_Flags)
|
|
||||||
@echo "LINK => $@"
|
|
||||||
|
|
||||||
$(Test_Objs): %.o: %.c
|
|
||||||
@$(CC) $(C_Flags) -c $< -o $@
|
|
||||||
@echo "CC <= $@"
|
|
||||||
|
|
||||||
$(EDL_Gen_Files): $(SGX_EDGER8R) ../src/Enclave.edl
|
|
||||||
@$(SGX_EDGER8R) --trusted ../src/Enclave.edl --search-path $(SGX_SDK)/include --search-path ../deps/rust-sgx-sdk/edl/
|
|
||||||
@echo "GEN => $(EDL_Gen_Files)"
|
|
||||||
|
|
||||||
|
|
||||||
.PHONY: compiler-rt
|
|
||||||
compiler-rt:
|
|
||||||
@$(MAKE) --no-print-directory -C ../deps/rust-sgx-sdk/compiler-rt/ 2> /dev/null
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Run tests
|
|
||||||
#
|
|
||||||
.PHONY: test
|
|
||||||
test: $(Test_Targets)
|
|
||||||
|
|
||||||
.PHONY: (Test_Targets)
|
|
||||||
$(Test_Targets): test-%: %.signed.so
|
|
||||||
./../src/pal/pal $^
|
|
||||||
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
clean:
|
clean:
|
||||||
@-$(RM) $(Test_Signed_Enclaves) $(Test_Enclaves) $(Test_Objs) $(EDL_Gen_Files)
|
@$(MAKE) -C rusgx_stub clean
|
||||||
|
@$(MAKE) -C src clean
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
int main() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
extern long long sys_write(int fd, const char* buf, unsigned long long size);
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
char msg[] = "Hello, World!\n";
|
|
||||||
sys_write(1, msg, sizeof(msg));
|
|
||||||
return 0;
|
|
||||||
}
|
|
36
test/include/rusgx_stub.h
Normal file
36
test/include/rusgx_stub.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef __RUSGX_STUB__
|
||||||
|
#define __RUSGX_STUB__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stub for Rusgx syscalls
|
||||||
|
*
|
||||||
|
* Executables built with Rusgx's toolchain are dynamically linked with this
|
||||||
|
* stub library. This stub library serves two purposes:
|
||||||
|
*
|
||||||
|
* 1) Enable Rusgx's syscalls. Since this library is dynamically linked with
|
||||||
|
* executables, the compile-time linker generates proper dynamic linking
|
||||||
|
* information. Using this information, the program loader of Rusgx can do
|
||||||
|
* runtime relocation so that user programs can make syscalls to the library
|
||||||
|
* OS.
|
||||||
|
*
|
||||||
|
* 2) Run without Rusgx. When not running upon Rusgx, the executables can use the
|
||||||
|
* host syscalls provided by the default implementation of this library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SYS_exit 60
|
||||||
|
#define SYS_write 1
|
||||||
|
|
||||||
|
long rusgx_syscall(int num, long arg0, long arg1, long arg2, long arg3, long arg4);
|
||||||
|
|
||||||
|
static inline ssize_t __rusgx_write(int fd, const void* buf, unsigned long size) {
|
||||||
|
return (ssize_t) rusgx_syscall(SYS_write, (long)fd, (long)buf, (long)size, (long)0, (long)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __rusgx_exit(int status) {
|
||||||
|
rusgx_syscall(SYS_exit, (long)status, (long)0, (long)0, (long)0, (long)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __RUSGX_STUB__ */
|
23
test/rusgx_stub/Makefile
Normal file
23
test/rusgx_stub/Makefile
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
C_SRCS := $(wildcard *.c)
|
||||||
|
S_FILES := $(C_SRCS:%.c=%.S)
|
||||||
|
C_OBJS := $(C_SRCS:%.c=%.o)
|
||||||
|
LIB_NAME := librusgx_stub.so
|
||||||
|
|
||||||
|
C_FLAGS := -Wall -fno-builtin -fno-stack-protector -fverbose-asm -fpic -I../include
|
||||||
|
C_FLAGS += -O0
|
||||||
|
LINK_FLAGS := -nostdlib
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
|
all: $(LIB_NAME)
|
||||||
|
|
||||||
|
$(LIB_NAME): $(C_OBJS)
|
||||||
|
$(CC) $^ $(LINK_FLAGS) -shared -o $(LIB_NAME)
|
||||||
|
|
||||||
|
$(C_OBJS): %.o: %.S
|
||||||
|
$(CC) $(C_FLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
$(S_FILES): %.S: %.c
|
||||||
|
$(CC) $(C_FLAGS) -S $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) -f *.o *.S $(LIB_NAME)
|
36
test/rusgx_stub/stub_impl.c
Normal file
36
test/rusgx_stub/stub_impl.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include "rusgx_stub.h"
|
||||||
|
|
||||||
|
static long __write(int fd, const void* buf, unsigned long size) {
|
||||||
|
long ret;
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
"syscall"
|
||||||
|
: "=a" (ret)
|
||||||
|
: "0" (SYS_write), "D" (fd), "S" (buf), "d" (size)
|
||||||
|
: "cc", "rcx", "r11", "memory"
|
||||||
|
);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit(int status) {
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
"syscall"
|
||||||
|
:
|
||||||
|
: "a" (SYS_exit), "D" (status)
|
||||||
|
: "cc", "rcx", "r11", "memory" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long rusgx_syscall(int num, long arg0, long arg1, long arg2, long arg3, long arg4) {
|
||||||
|
long ret = 0;
|
||||||
|
switch (num) {
|
||||||
|
case SYS_exit:
|
||||||
|
__exit((int)arg0);
|
||||||
|
break;
|
||||||
|
case SYS_write:
|
||||||
|
ret = __write((int)arg0, (const void*)arg1, (unsigned long)arg2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
67
test/src/Makefile
Normal file
67
test/src/Makefile
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
PROJECT_DIR := $(realpath $(CUR_DIR)/../../)
|
||||||
|
|
||||||
|
C_SRCS := $(wildcard *.c)
|
||||||
|
S_FILES := $(C_SRCS:%.c=%.S)
|
||||||
|
C_OBJS := $(C_SRCS:%.c=%.o)
|
||||||
|
BIN_NAME := bin
|
||||||
|
BIN_ENC_NAME := bin.encrypted
|
||||||
|
OBJDUMP_FILE := bin.objdump
|
||||||
|
READELF_FILE := bin.readelf
|
||||||
|
|
||||||
|
C_FLAGS := -Wall -fno-builtin -fno-stack-protector -fverbose-asm -fpic
|
||||||
|
C_FLAGS += -I../include -L../rusgx_stub -lrusgx_stub
|
||||||
|
C_FLAGS += -O0
|
||||||
|
LINK_FLAGS := -pie -nostdlib -L../rusgx_stub -lrusgx_stub
|
||||||
|
|
||||||
|
.PHONY: all clean test test-without-rusgx
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# Build
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
all: $(BIN_NAME) $(OBJDUMP_FILE) $(READELF_FILE)
|
||||||
|
|
||||||
|
$(OBJDUMP_FILE): $(BIN_NAME)
|
||||||
|
objdump -d $(BIN_NAME) > $(OBJDUMP_FILE)
|
||||||
|
|
||||||
|
$(READELF_FILE): $(BIN_NAME)
|
||||||
|
readelf -a -d $(BIN_NAME) > $(READELF_FILE)
|
||||||
|
|
||||||
|
$(BIN_NAME): $(C_OBJS)
|
||||||
|
$(CC) $^ $(LINK_FLAGS) -o $(BIN_NAME)
|
||||||
|
|
||||||
|
$(C_OBJS): %.o: %.S
|
||||||
|
$(CC) $(C_FLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
$(S_FILES): %.S: %.c
|
||||||
|
$(CC) $(C_FLAGS) -S $< -o $@
|
||||||
|
# ./override_ds_with_fs.sh $@
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# Test
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
test: pal librusgx.signed.so $(BIN_ENC_NAME)
|
||||||
|
RUST_BACKTRACE=1 ./pal ./bin.encrypted
|
||||||
|
|
||||||
|
pal:
|
||||||
|
cp $(PROJECT_DIR)/src/pal/pal pal
|
||||||
|
|
||||||
|
librusgx.signed.so:
|
||||||
|
cp $(PROJECT_DIR)/src/libos/librusgx.signed.so librusgx.signed.so
|
||||||
|
|
||||||
|
$(BIN_ENC_NAME): $(BIN_NAME)
|
||||||
|
$(RM) -f $(BIN_ENC_NAME)
|
||||||
|
cd $(PROJECT_DIR)/deps/sgx_protect_file/ && \
|
||||||
|
./sgx_protect_file encrypt -i $(CUR_DIR)/$(BIN_NAME) -o $(CUR_DIR)/$(BIN_ENC_NAME) -k 123
|
||||||
|
|
||||||
|
test-without-rusgx: $(BIN_ENC_NAME)
|
||||||
|
LD_LIBRARY_PATH=../rusgx_stub/ ./$(BIN_NAME)
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# Misc
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) -f *.o *.S $(BIN_NAME) $(BIN_ENC_NAME) $(OBJDUMP_FILE) $(READELF_FILE) pal librusgx.signed.so
|
9
test/src/main.c
Normal file
9
test/src/main.c
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include "rusgx_stub.h"
|
||||||
|
|
||||||
|
char str_buf[] = "Hello World!\n";
|
||||||
|
unsigned long str_size = sizeof(str_buf);
|
||||||
|
|
||||||
|
void _start(void) {
|
||||||
|
__rusgx_write(1, str_buf, str_size);
|
||||||
|
__rusgx_exit(0);
|
||||||
|
}
|
13
test/src/override_ds_with_fs.sh
Executable file
13
test/src/override_ds_with_fs.sh
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
echo "ERROR: the number of given arguments is incorrect!"
|
||||||
|
echo
|
||||||
|
echo "./use_fs <assembly_file>"
|
||||||
|
exit -1
|
||||||
|
fi
|
||||||
|
|
||||||
|
S_FILE=$1
|
||||||
|
sed -i \
|
||||||
|
-e 's/str_size@GOTPCREL/%fs:&/g' \
|
||||||
|
-e 's/str_buf@GOTPCREL/%fs:&/g' \
|
||||||
|
${S_FILE}
|
Loading…
Reference in New Issue
Block a user