From d77c21f98c560fc70807a6d3b2cdf9890a0cb618 Mon Sep 17 00:00:00 2001 From: "Tate, Hongliang Tian" Date: Tue, 27 Aug 2019 12:19:33 +0000 Subject: [PATCH] Add a command-line interface tool named occlum 1. All generated, build files are now in a separate build directory; 2. The CLI tool supports three sub-commands: init, build, and run; 3. Refactor tests to use the new tool. --- .gitignore | 7 +- .../template/Enclave.pem | 0 .../template/Enclave.xml | 0 .../template/Occlum.json | 25 +-- src/cli/occlum | 173 ++++++++++++++++++ src/cli/occlum-gen-default-occlum-json | 38 ++++ src/libos/Makefile | 125 ++++++++----- src/libos/src/config.rs | 2 +- src/libos/src/fs/root_inode.rs | 59 +++--- src/pal/Makefile | 60 +++--- src/pal/pal.c | 76 +++++--- src/pal/pal.h | 33 ---- src/sgxenv.mk | 1 + test/Enclave.xml | 12 ++ test/Makefile | 86 ++------- test/Occlum.json | 33 ++++ test/hostfs/main.c | 7 +- test/test_common.mk | 50 ++--- tools/protect-integrity/App/App.cpp | 24 ++- 19 files changed, 515 insertions(+), 296 deletions(-) rename test/Enclave_private.pem => etc/template/Enclave.pem (100%) rename test/Enclave_config.xml => etc/template/Enclave.xml (100%) rename test/Occlum.json.sh => etc/template/Occlum.json (51%) mode change 100755 => 100644 create mode 100755 src/cli/occlum create mode 100755 src/cli/occlum-gen-default-occlum-json delete mode 100644 src/pal/pal.h create mode 100644 test/Enclave.xml create mode 100644 test/Occlum.json diff --git a/.gitignore b/.gitignore index b5679fa7..6fda0f01 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,4 @@ *.o *.a *.so -src/pal/pal -src/libos/target -src/libos/src/Enclave_t.c -src/libos/src/Enclave_t.h -src/pal/Enclave_u.c -src/pal/Enclave_u.h +build/ diff --git a/test/Enclave_private.pem b/etc/template/Enclave.pem similarity index 100% rename from test/Enclave_private.pem rename to etc/template/Enclave.pem diff --git a/test/Enclave_config.xml b/etc/template/Enclave.xml similarity index 100% rename from test/Enclave_config.xml rename to etc/template/Enclave.xml diff --git a/test/Occlum.json.sh b/etc/template/Occlum.json old mode 100755 new mode 100644 similarity index 51% rename from test/Occlum.json.sh rename to etc/template/Occlum.json index 6e5fbfc4..93930e04 --- a/test/Occlum.json.sh +++ b/etc/template/Occlum.json @@ -1,8 +1,3 @@ -#!/bin/bash -bin_sefs_mac=$1 -lib_sefs_mac=$2 - -cat </dev/null 2>&1 && pwd )" +project_dir="$( cd "$( dirname "$this_dir/../../../" )" >/dev/null 2>&1 && pwd )" +context_dir="$working_dir/.occlum" + +SGX_SDK="${SGX_SDK:-/opt/intel/sgxsdk}" + +report_arg_error() { + echo $1 + echo "" + echo "Usage:" + echo " occlum init" + echo " occlum build" + echo " occlum run " +} + + +get_conf_user_space_size() { + cat "$working_dir/Occlum.json" | \ + python -c "import sys, json; print json.load(sys.stdin)['vm']['user_space_size']" +} + +get_conf_default_stack_size() { + cat "$working_dir/Occlum.json" | \ + python -c "import sys, json; print json.load(sys.stdin)['process']['default_stack_size']" +} + +get_conf_default_heap_size() { + cat "$working_dir/Occlum.json" | \ + python -c "import sys, json; print json.load(sys.stdin)['process']['default_heap_size']" +} + +get_conf_default_mmap_size() { + cat "$working_dir/Occlum.json" | \ + python -c "import sys, json; print json.load(sys.stdin)['process']['default_mmap_size']" +} + + +get_occlum_conf_file_mac() { + "$project_dir/tools/bin/protect-integrity" show-mac "$context_dir/build/Occlum.json.protected" +} + +parse_occlum_user_space_size() { + local size_with_unit=`get_conf_user_space_size` + numfmt --from=iec ${size_with_unit::-1} +} + + +cmd_init() { + cd "$working_dir" + mkdir -p .occlum + cd "$context_dir" + echo "initialized" > status + + cd "$working_dir" + mkdir -p image + mkdir -p image/bin + mkdir -p image/lib + mkdir -p image/root + mkdir -p image/host + mkdir -p image/tmp + + cp \ + /lib/ld-musl-x86_64.so.1 \ + /usr/local/occlum/lib/libc++.so.1 \ + /usr/local/occlum/lib/libc++abi.so.1 \ + /usr/local/occlum/lib/libunwind.so.1 \ + image/lib/ + + cp "$project_dir"/etc/template/* "$working_dir"/ + + echo "Initialized an Occlum context in $working_dir" +} + +cmd_build() { + cd "$context_dir" + echo "building" > status + + rm -rf build + + mkdir -p build/bin + cp "$project_dir/build/bin/occlum-pal" build/bin/ + mkdir -p build/lib + cp "$project_dir/build/lib/libocclum_core.a" build/lib/ + cp "$project_dir/build/lib/libcompiler-rt-patch.a" build/lib/ + mkdir -p build/src/libos/src/builtin + + mkdir -p build/mount/ + cd "$project_dir/deps/sefs/sefs-fuse/bin/" && \ + ./app \ + --integrity-only \ + "$context_dir/build/mount/__ROOT" \ + "$working_dir/image" \ + zip + + export OCCLUM_CONF_ROOT_FS_MAC=`"$project_dir/tools/bin/protect-integrity" show-mac "$context_dir/build/mount/__ROOT/0"` + export OCCLUM_CONF_USER_SPACE_SIZE=`get_conf_user_space_size` + export OCCLUM_CONF_DEFAULT_STACK_SIZE=`get_conf_default_stack_size` + export OCCLUM_CONF_DEFAULT_HEAP_SIZE=`get_conf_default_heap_size` + export OCCLUM_CONF_DEFAULT_MMAP_SIZE=`get_conf_default_mmap_size` + cd "$context_dir/build" + "$project_dir/src/cli/occlum-gen-default-occlum-json"\ + > "Occlum.json" + "$project_dir/tools/bin/protect-integrity" protect Occlum.json + + export OCCLUM_BUILTIN_CONF_FILE_MAC=`get_occlum_conf_file_mac` + echo "EXPORT => OCCLUM_BUILTIN_CONF_FILE_MAC = $OCCLUM_BUILTIN_CONF_FILE_MAC" + export OCCLUM_BUILTIN_VM_USER_SPACE_SIZE=`parse_occlum_user_space_size` + echo "EXPORT => OCCLUM_BUILTIN_VM_USER_SPACE_SIZE = $OCCLUM_BUILTIN_VM_USER_SPACE_SIZE" + + cd "$context_dir" + mkdir -p src/libos/src/ + cp "$project_dir/src/sgxenv.mk" src/ + cp "$project_dir/src/libos/Makefile" src/libos/ + cp "$project_dir/src/libos/Enclave.lds" src/libos/ + cp -r "$project_dir/src/libos/src/builtin" src/libos/src/builtin + cd src/libos && \ + make clean-builtin && \ + make "$context_dir/build/lib/libocclum.so" ONLY_REBUILD_BUILTIN=1 + + $SGX_SDK/bin/x64/sgx_sign sign \ + -key "$working_dir/Enclave.pem" \ + -config "$working_dir/Enclave.xml" \ + -enclave "$context_dir/build/lib/libocclum.so" \ + -out "$context_dir/build/lib/libocclum.signed.so" \ + + cd "$context_dir" + echo "built" > status + + echo "Built the Occlum image and enclave successfully" +} + +cmd_run() { + cd "$working_dir" + echo "running" > "$context_dir/status" + + mkdir -p "$context_dir/run/mount/root" + RUST_BACKTRACE=1 "$context_dir/build/bin/occlum-pal" "$@" + + echo "built" > "$context_dir/status" +} + +cmd_status() { + cat "$context_dir/status" +} + +set -e + +if [[ ( "$#" < 1 ) ]] ; then + report_arg_error "Error: no sub-command is given" + exit 1 +fi + +cmd=$1 +case "$cmd" in + init) + cmd_init + ;; + build) + cmd_build + ;; + run) + cmd_run "${@:2}" + ;; + status) + cmd_status + ;; + *) + report_arg_error "Error: unknown sub-command $cmd" + exit 1 +esac diff --git a/src/cli/occlum-gen-default-occlum-json b/src/cli/occlum-gen-default-occlum-json new file mode 100755 index 00000000..e77c8fee --- /dev/null +++ b/src/cli/occlum-gen-default-occlum-json @@ -0,0 +1,38 @@ +#!/bin/bash +cat < $(LIBOS_CORE_A) > $(LIBOS_RS_A) +LIBOS_SO := $(BUILD_DIR)/lib/libocclum.so +LIBOS_CORE_A := $(BUILD_DIR)/lib/libocclum_core.a +LIBOS_RS_A := $(BUILD_DIR)/lib/libocclum_rs.a +# The dependent libraries +LIBCOMPILER_RT_PATCH_A := $(BUILD_DIR)/lib/libcompiler-rt-patch.a +# All source code RUST_SRCS := $(wildcard src/*.rs src/*/*.rs src/*/*/*.rs) -C_SRCS := $(sort $(filter-out src/Enclave_t.c, $(wildcard src/*.c src/*/*.c))) src/Enclave_t.c -C_OBJS := $(C_SRCS:.c=.o) -S_SRCS := $(wildcard src/*.S src/*/*.S) -S_OBJS := $(S_SRCS:.S=.o) -EDL_C_SRCS := src/Enclave_t.c src/Enclave_t.h +RUST_TARGET_DIR := $(BUILD_DIR)/src/libos/cargo-target +RUST_OUT_DIR := $(BUILD_DIR)/lib +EDL_C_SRCS := $(addprefix $(BUILD_DIR)/src/libos/,src/Enclave_t.c src/Enclave_t.h) +EDL_C_OBJS := $(addprefix $(BUILD_DIR)/src/libos/,src/Enclave_t.o) +BUILTIN_C_SRCS := $(sort $(wildcard src/builtin/*.c)) +BUILTIN_C_OBJS := $(addprefix $(BUILD_DIR)/src/libos/,$(BUILTIN_C_SRCS:.c=.o)) +C_SRCS := $(filter-out $(BUILTIN_C_SRCS),$(sort $(wildcard src/*.c src/*/*.c))) +C_OBJS := $(addprefix $(BUILD_DIR)/src/libos/,$(C_SRCS:.c=.o)) +S_SRCS := $(sort $(wildcard src/*.S src/*/*.S)) +S_OBJS := $(addprefix $(BUILD_DIR)/src/libos/,$(S_SRCS:.S=.o)) -ENCLAVE_CONFIG := Enclave_config.xml -ENCLAVE_KEY := Enclave_private.pem +ALL_BUILD_SUBDIRS := $(sort $(patsubst %/,%,$(dir $(LIBOS_SO) $(EDL_C_OBJS) $(BUILTIN_C_OBJS) $(C_OBJS) $(S_OBJS)) $(RUST_TARGET_DIR) $(RUST_OUT_DIR))) C_FLAGS := $(SGX_CFLAGS_T) -fno-stack-protector -I./include/ @@ -28,48 +41,68 @@ ifdef OCCLUM_BUILTIN_VM_USER_SPACE_SIZE C_FLAGS += -DOCCLUM_BUILTIN_VM_USER_SPACE_SIZE='($(OCCLUM_BUILTIN_VM_USER_SPACE_SIZE))' endif -_Other_Link_Flags := -L$(RUST_SGX_SDK_DIR)/compiler-rt/ -L. -_Other_Enclave_Libs := -lcompiler-rt-patch -locclum_rs -lsgx_tprotected_fs +_Other_Link_Flags := -L$(RUST_SGX_SDK_DIR)/compiler-rt/ -L$(BUILD_DIR)/lib +_Other_Enclave_Libs := -lcompiler-rt-patch -locclum_core -lsgx_tprotected_fs LINK_FLAGS := $(SGX_LFLAGS_T) -.PHONY: all compiler-rt clean +.PHONY: all clean -all: $(LIBOS_SO) +all: $(ALL_BUILD_SUBDIRS) $(LIBOS_SO) -$(LIBOS_SO): compiler-rt $(LIBOS_A) $(C_OBJS) $(S_OBJS) - @$(CC) $(C_OBJS) $(S_OBJS) -o $@ $(LINK_FLAGS) +$(ALL_BUILD_SUBDIRS): + @mkdir -p $@ + +LIBOS_SO_DEPS := $(BUILTIN_C_OBJS) $(LIBOS_CORE_A) $(LIBCOMPILER_RT_PATCH_A) +ifeq ($(ONLY_REBUILD_BUILTIN), 0) +$(LIBOS_SO): $(BUILTIN_C_OBJS) $(LIBOS_CORE_A) $(LIBCOMPILER_RT_PATCH_A) + @$(CC) $(LIBOS_SO_DEPS) -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 $(RUST_SGX_SDK_DIR)/edl/ - @echo "GEN <= $(EDL_C_SRCS)" - -compiler-rt: - @$(MAKE) --no-print-directory -C $(RUST_SGX_SDK_DIR)/compiler-rt/ > /dev/null - -ifeq ($(DEBUG), 1) -$(LIBOS_A): $(RUST_SRCS) - @RUSTC_BOOTSTRAP=1 cargo build - @cp ./target/debug/$(LIBOS_A) $(LIBOS_A) - @echo "CARGO (debug) => $(LIBOS_A)" else -$(LIBOS_A): $(RUST_SRCS) - @RUSTC_BOOTSTRAP=1 cargo build --release - @cp ./target/release/$(LIBOS_A) $(LIBOS_A) - @echo "CARGO (release) => $(LIBOS_A)" +$(LIBOS_SO): $(BUILTIN_C_OBJS) + @$(CC) $(LIBOS_SO_DEPS) -o $@ $(LINK_FLAGS) + @echo "LINK => $@" endif -clean-builtin: - @-$(RM) src/builtin/*.o +$(LIBOS_CORE_A): $(LIBOS_RS_A) $(C_OBJS) $(S_OBJS) $(EDL_C_OBJS) + @cp $(LIBOS_RS_A) $(LIBOS_CORE_A) + @ar r $@ $(C_OBJS) $(S_OBJS) $(EDL_C_OBJS) + @echo "GEN => $@" -clean: - @cargo clean - @-$(RM) $(LIBOS_SO) $(LIBOS_A) $(C_OBJS) $(S_OBJS) $(EDL_C_SRCS) +ifeq ($(RELEASE), 0) +$(LIBOS_RS_A): $(RUST_SRCS) + @RUSTC_BOOTSTRAP=1 cargo build --target-dir=$(RUST_TARGET_DIR) -Z unstable-options --out-dir=$(RUST_OUT_DIR) + @echo "CARGO (debug) => $@" +else +$(LIBOS_RS_A): $(RUST_SRCS) + @RUSTC_BOOTSTRAP=1 cargo build --release --target-dir=$(RUST_TARGET_DIR) -Z unstable-options --out-dir=$(RUST_OUT_DIR) + @echo "CARGO (release) => $@" +endif + +$(BUILD_DIR)/src/libos/src/Enclave_t.o: $(BUILD_DIR)/src/libos/src/Enclave_t.c + @$(CC) $(C_FLAGS) -c $< -o $@ + @echo "CC <= $@" + +$(BUILD_DIR)/src/libos/src/Enclave_t.c: $(SGX_EDGER8R) ../Enclave.edl + @cd $(BUILD_DIR)/src/libos/src && $(SGX_EDGER8R) --trusted $(CUR_DIR)/../Enclave.edl --search-path $(SGX_SDK)/include --search-path $(RUST_SGX_SDK_DIR)/edl/ + @echo "GEN <= $@" + +$(BUILD_DIR)/src/libos/%.o: %.c + @$(CC) $(C_FLAGS) -c $< -o $@ + @echo "CC <= $@" + +$(BUILD_DIR)/src/libos/%.o: %.S + @$(CC) $(C_FLAGS) -c $< -o $@ + @echo "CC <= $@" + +$(LIBCOMPILER_RT_PATCH_A): + @$(MAKE) --no-print-directory -C $(RUST_SGX_SDK_DIR)/compiler-rt/ > /dev/null + @cp $(RUST_SGX_SDK_DIR)/compiler-rt/libcompiler-rt-patch.a $(LIBCOMPILER_RT_PATCH_A) + @echo "GEN <= $@" + +clean-builtin: + @-$(RM) -f $(BUILTIN_C_OBJS) + +clean: clean-builtin + @-$(RM) -f $(LIBOS_SO) $(LIBOS_CORE_A) $(LIBOS_RS_A) \ + $(LIBCOMPILER_RT_PATCH_A) $(EDL_C_OBJS) $(EDL_C_SRCS) $(C_OBJS) $(S_OBJS) + @-$(RM) -rf $(RUST_TARGET_DIR) diff --git a/src/libos/src/config.rs b/src/libos/src/config.rs index 4f5e808d..ffaf40a8 100644 --- a/src/libos/src/config.rs +++ b/src/libos/src/config.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use std::path::{Path, PathBuf}; use std::sgxfs::SgxFile; -const LIBOS_CONFIG_PATH: &str = "Occlum.json.protected"; +const LIBOS_CONFIG_PATH: &str = "./.occlum/build/Occlum.json.protected"; lazy_static! { pub static ref LIBOS_CONFIG: Config = { diff --git a/src/libos/src/fs/root_inode.rs b/src/libos/src/fs/root_inode.rs index 5a7f76fc..9448086b 100644 --- a/src/libos/src/fs/root_inode.rs +++ b/src/libos/src/fs/root_inode.rs @@ -15,7 +15,7 @@ lazy_static! { pub static ref ROOT_INODE: Arc = { let mount_config = &config::LIBOS_CONFIG.mount; - let rootfs = open_or_create_root_fs_according_to(mount_config) + let rootfs = open_root_fs_according_to(mount_config) .expect("failed to create or open SEFS for /"); let root = rootfs.root_inode(); @@ -26,9 +26,7 @@ lazy_static! { }; } -fn open_or_create_root_fs_according_to( - mount_config: &Vec, -) -> Result, Error> { +fn open_root_fs_according_to(mount_config: &Vec) -> Result, Error> { let root_sefs_source = { let root_mount_config = mount_config .iter() @@ -38,11 +36,8 @@ fn open_or_create_root_fs_according_to( if root_mount_config.type_ != ConfigMountFsType::TYPE_SEFS { return errno!(EINVAL, "The mount point at / must be SEFS"); } - if root_mount_config.options.integrity_only { - return errno!( - EINVAL, - "The root SEFS at / must be encrypted (i.e., integrity-only is not enough)" - ); + if !root_mount_config.options.integrity_only { + return errno!(EINVAL, "The root SEFS at / must be integrity-only"); } if root_mount_config.source.is_none() { return errno!( @@ -53,18 +48,10 @@ fn open_or_create_root_fs_according_to( root_mount_config.source.as_ref().unwrap() }; - let root_sefs = { - SEFS::open( - Box::new(SgxStorage::new(root_sefs_source, false)), - &time::OcclumTimeProvider, - ) - } - .or_else(|_| { - SEFS::create( - Box::new(SgxStorage::new(root_sefs_source, false)), - &time::OcclumTimeProvider, - ) - })?; + let root_sefs = SEFS::open( + Box::new(SgxStorage::new(root_sefs_source, true)), + &time::OcclumTimeProvider, + )?; let root_mountable_sefs = MountFS::new(root_sefs); Ok(root_mountable_sefs) } @@ -89,23 +76,25 @@ fn mount_nonroot_fs_according_to( use self::ConfigMountFsType::*; match mc.type_ { TYPE_SEFS => { - if !mc.options.integrity_only { - return errno!(EINVAL, "Must be integrity-only SEFS"); + if mc.options.integrity_only { + return errno!(EINVAL, "Cannot mount integrity-only SEFS at non-root path"); } if mc.source.is_none() { - return errno!( - EINVAL, - "Source is expected for integrity-only SEFS is supported" - ); + return errno!(EINVAL, "Source is expected for SEFS"); } let source_path = mc.source.as_ref().unwrap(); - - let device = { - let mut device = Box::new(SgxStorage::new(source_path, true)); - device.set_root_mac(mc.options.mac.unwrap()); - device - }; - let sefs = SEFS::open(device, &time::OcclumTimeProvider)?; + let sefs = { + SEFS::open( + Box::new(SgxStorage::new(source_path, false)), + &time::OcclumTimeProvider, + ) + } + .or_else(|_| { + SEFS::create( + Box::new(SgxStorage::new(source_path, false)), + &time::OcclumTimeProvider, + ) + })?; mount_fs_at(sefs, &root, target_dirname)?; } TYPE_HOSTFS => { @@ -134,7 +123,7 @@ fn mount_fs_at(fs: Arc, parent_inode: &MNode, dirname: &str) -> } existing_dir } - Err(_) => parent_inode.create(dirname, FileType::Dir, 0o777)?, + Err(_) => return errno!(ENOENT, "Mount point does not exist"), }; mount_dir.mount(fs); Ok(()) diff --git a/src/pal/Makefile b/src/pal/Makefile index 0f33f8f4..e4579882 100644 --- a/src/pal/Makefile +++ b/src/pal/Makefile @@ -1,38 +1,48 @@ include ../sgxenv.mk -EDL_Gen_Files := Enclave_u.c Enclave_u.h +BIN := $(BUILD_DIR)/bin/occlum-pal -Srcs := $(sort $(filter-out Enclave_u.c, $(wildcard *.c))) -Objs := $(Srcs:.c=.o) Enclave_u.o -Bin := pal +# A dependency on Rust SGX SDK +LIBSGX_USTDC_A := $(BUILD_DIR)/lib/libsgx_ustdc.a -C_Flags := $(SGX_CFLAGS_U) -Link_Flags := $(SGX_LFLAGS_U) -Link_Flags += -L$(RUST_SGX_SDK_DIR)/sgx_ustdc/ -lsgx_ustdc -lsgx_uprotected_fs +EDL_C_SRCS := $(addprefix $(BUILD_DIR)/src/pal/,Enclave_u.c Enclave_u.h) +EDL_C_OBJS := $(addprefix $(BUILD_DIR)/src/pal/,Enclave_u.o) +C_SRCS := $(sort $(wildcard *.c)) +C_OBJS := $(addprefix $(BUILD_DIR)/src/pal/,$(C_SRCS:.c=.o)) +C_FLAGS := $(SGX_CFLAGS_U) -I$(BUILD_DIR)/src/pal -Wno-unused-result +LINK_FLAGS := $(SGX_LFLAGS_U) +LINK_FLAGS += -L$(RUST_SGX_SDK_DIR)/sgx_ustdc/ -lsgx_ustdc -lsgx_uprotected_fs -.PHONY: all -all: $(Bin) +ALL_BUILD_SUBDIRS := $(sort $(patsubst %/,%,$(dir $(BIN) $(EDL_C_OBJS) $(C_OBJS)))) -$(Bin): $(EDL_Gen_Files) $(Objs) sgx_ustdc - @$(CC) $(Objs) -o $@ $(Link_Flags) - @echo "LINK => $@" +.PHONY: all clean -$(EDL_Gen_Files): $(SGX_EDGER8R) ../Enclave.edl - @$(SGX_EDGER8R) --untrusted ../Enclave.edl --search-path $(SGX_SDK)/include --search-path $(RUST_SGX_SDK_DIR)/edl/ - @echo "GEN => $(EDL_Gen_Files)" +all: $(ALL_BUILD_SUBDIRS) $(BIN) -$(Objs): %.o: %.c - @$(CC) $(C_Flags) -c $< -o $@ +$(ALL_BUILD_SUBDIRS): + @mkdir -p $@ + +$(BIN): $(LIBSGX_USTDC_A) $(EDL_C_OBJS) $(C_OBJS) + @$(CC) $^ -o $@ $(LINK_FLAGS) + @echo "LINK => $@" + +$(BUILD_DIR)/src/pal/Enclave_u.o: $(BUILD_DIR)/src/pal/Enclave_u.c + @$(CC) $(C_FLAGS) -c $< -o $@ @echo "CC <= $@" -# -# Compile dependencies in Rust SGX SDK -# -.PHONY: sgx_ustdc -sgx_ustdc: - @$(MAKE) --no-print-directory -C $(RUST_SGX_SDK_DIR)/sgx_ustdc/ > /dev/null +$(BUILD_DIR)/src/pal/Enclave_u.c: $(SGX_EDGER8R) ../Enclave.edl + @cd $(BUILD_DIR)/src/pal && $(SGX_EDGER8R) --untrusted $(CUR_DIR)/../Enclave.edl --search-path $(SGX_SDK)/include --search-path $(RUST_SGX_SDK_DIR)/edl/ + @echo "GEN <= $@" + +$(BUILD_DIR)/src/pal/%.o: %.c + @$(CC) $(C_FLAGS) -c $< -o $@ + @echo "CC <= $@" + +$(LIBSGX_USTDC_A): + @$(MAKE) --no-print-directory -C $(RUST_SGX_SDK_DIR)/sgx_ustdc/ > /dev/null + @cp $(RUST_SGX_SDK_DIR)/sgx_ustdc/libsgx_ustdc.a $(LIBSGX_USTDC_A) + @echo "GEN <= $@" -.PHONY: clean clean: - @-$(RM) -f $(EDL_Gen_Files) $(Objs) $(Bin) + @-$(RM) -f $(BIN) $(LIBSGX_USTDC_A) $(C_OBJS) $(EDL_C_OBJS) $(EDL_C_SRCS) diff --git a/src/pal/pal.c b/src/pal/pal.c index 09ff646e..cd569feb 100644 --- a/src/pal/pal.c +++ b/src/pal/pal.c @@ -1,22 +1,34 @@ -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define MAX_PATH FILENAME_MAX - -#include "sgx_urts.h" -#include "pal.h" -#include "task.h" #include "Enclave_u.h" -sgx_enclave_id_t global_eid = 0; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "task.h" + +#define MAX_PATH FILENAME_MAX +#define TOKEN_FILENAME "enclave.token" +#define ENCLAVE_FILENAME "libocclum.signed.so" + +// ========================================================================== +// Enclave Initialization +// ========================================================================== + +static sgx_enclave_id_t global_eid = 0; typedef struct _sgx_errlist_t { sgx_status_t err; @@ -104,7 +116,7 @@ static sgx_errlist_t sgx_errlist[] = { }; /* Check error conditions for loading enclave */ -void print_error_message(sgx_status_t ret) +static void print_error_message(sgx_status_t ret) { size_t idx = 0; size_t ttl = sizeof sgx_errlist/sizeof sgx_errlist[0]; @@ -122,12 +134,24 @@ void print_error_message(sgx_status_t ret) printf("Error: Unexpected error occurred.\n"); } +static const char* get_enclave_absolute_path() { + static char enclave_path[MAX_PATH] = {0}; + // Get the absolute path of the executable + readlink("/proc/self/exe", enclave_path, sizeof(enclave_path)); + // Get the absolute path of the containing directory + dirname(enclave_path); + // Get the absolute path of the enclave + strncat(enclave_path, "/../lib/", sizeof(enclave_path)); + strncat(enclave_path, ENCLAVE_FILENAME, sizeof(enclave_path)); + return (const char*)enclave_path; +} + /* Initialize the enclave: * Step 1: try to retrieve the launch token saved by last transaction * Step 2: call sgx_create_enclave to initialize an enclave instance * Step 3: save the launch token if it is updated */ -int initialize_enclave(const char* enclave_path) +static int initialize_enclave() { char token_path[MAX_PATH] = {'\0'}; sgx_launch_token_t token = {0}; @@ -167,6 +191,7 @@ int initialize_enclave(const char* enclave_path) } /* Step 2: call sgx_create_enclave to initialize an enclave instance */ /* Debug Support: set 2nd parameter to 1 */ + const char* enclave_path = get_enclave_absolute_path(); ret = sgx_create_enclave(enclave_path, SGX_DEBUG_FLAG, &token, &updated, &global_eid, NULL); if (ret != SGX_SUCCESS) { print_error_message(ret); @@ -175,7 +200,7 @@ int initialize_enclave(const char* enclave_path) } /* Step 3: save the launch token if it is updated */ - if (updated == FALSE || fp == NULL) { + if (updated == 0 || fp == NULL) { /* if the token is not updated, or file handler is invalid, do not perform saving */ if (fp != NULL) fclose(fp); return 0; @@ -191,7 +216,10 @@ int initialize_enclave(const char* enclave_path) return 0; } -// Debug +// ========================================================================== +// OCalls +// ========================================================================== + void ocall_print_string(const char* msg) { printf("%s", msg); } @@ -235,6 +263,9 @@ void ocall_sync(void) { sync(); } +// ========================================================================== +// Main +// ========================================================================== /* Application entry */ int SGX_CDECL main(int argc, const char *argv[]) @@ -252,9 +283,8 @@ int SGX_CDECL main(int argc, const char *argv[]) } const char* executable_path = argv[1]; - const char* enclave_path = "libocclum.signed.so"; /* Initialize the enclave */ - if(initialize_enclave(enclave_path) < 0){ + if(initialize_enclave() < 0){ printf("Enter a character before exit ...\n"); getchar(); return -1; diff --git a/src/pal/pal.h b/src/pal/pal.h deleted file mode 100644 index a80322a2..00000000 --- a/src/pal/pal.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _PAL_H_ -#define _PAL_H_ - -#include -#include -#include -#include - -#include "sgx_error.h" /* sgx_status_t */ -#include "sgx_eid.h" /* sgx_enclave_id_t */ - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -#define TOKEN_FILENAME "enclave.token" - -extern sgx_enclave_id_t global_eid; /* global enclave id */ - -#if defined(__cplusplus) -extern "C" { -#endif - - -#if defined(__cplusplus) -} -#endif - -#endif /* _PAL_H_ */ diff --git a/src/sgxenv.mk b/src/sgxenv.mk index 9338dd77..b531cd32 100644 --- a/src/sgxenv.mk +++ b/src/sgxenv.mk @@ -2,6 +2,7 @@ MAIN_MAKEFILE := $(firstword $(MAKEFILE_LIST)) INCLUDE_MAKEFILE := $(lastword $(MAKEFILE_LIST)) CUR_DIR := $(shell dirname $(realpath $(MAIN_MAKEFILE))) PROJECT_DIR := $(realpath $(CUR_DIR)/../../) +BUILD_DIR := $(PROJECT_DIR)/build SGX_SDK ?= /opt/intel/sgxsdk SGX_MODE ?= HW diff --git a/test/Enclave.xml b/test/Enclave.xml new file mode 100644 index 00000000..7d9f7639 --- /dev/null +++ b/test/Enclave.xml @@ -0,0 +1,12 @@ + + + 0 + 0 + 0x100000 + 0x2000000 + 8 + 1 + 0 + 0 + 0xFFFFFFFF + diff --git a/test/Makefile b/test/Makefile index dccb00c7..1c3db314 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,5 +1,6 @@ CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) PROJECT_DIR := $(realpath $(CUR_DIR)/../) +BUILD_DIR := $(PROJECT_DIR)/build # Dependencies: need to be compiled but not to run by any Makefile target TEST_DEPS := dev_null @@ -14,8 +15,7 @@ BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput BUILD_TARGETS := $(TEST_DEPS) $(TESTS) $(BENCHES) TEST_TARGETS := $(TESTS:%=test-%) BENCH_TARGETS := $(BENCHES:%=bench-%) -CLEAN_TARGETS := $(BUILD_TARGETS:%=clean-%) -.PHONY: all build test clean sefs root-sefs bin-sefs lib-sefs $(BUILD_TARGETS) $(TEST_TARGETS) $(BENCH_TARGETS) $(CLEAN_TARGETS) +.PHONY: all prebuild build postbuild test clean $(BUILD_TARGETS) $(TEST_TARGETS) $(BENCH_TARGETS) # Use echo program instead of built-in echo command in shell. This ensures # that echo can recognize escaped sequences (with -e argument) regardless of @@ -27,70 +27,29 @@ GREEN := \033[1;32m RED := \033[1;31m NO_COLOR := \033[0m -FS_PATH := fs -SEFS_PATH := sefs -BIN_SEFS_ROOT_FILE := $(SEFS_PATH)/bin/0 -LIB_SEFS_ROOT_FILE := $(SEFS_PATH)/lib/0 - ############################################################################# # Build targets ############################################################################# all: build -build: $(BUILD_TARGETS) sefs libocclum.signed.so +build: prebuild $(BUILD_TARGETS) postbuild + +prebuild: + @$(RM) -rf $(BUILD_DIR)/test/* + @mkdir -p $(BUILD_DIR)/test + @cd $(BUILD_DIR)/test && \ + $(PROJECT_DIR)/src/cli/occlum init + @cp Occlum.json Enclave.xml $(BUILD_DIR)/test/ $(BUILD_TARGETS): %: @$(ECHO) "$(CYAN)BUILD TEST => $@$(NO_COLOR)" @$(MAKE) --no-print-directory -C $@ @$(ECHO) "$(GREEN)DONE$(NO_COLOR)" -sefs: root-sefs bin-sefs lib-sefs - -root-sefs: - @mkdir -p $(SEFS_PATH)/root/ - @echo "SEFS => $@" - -bin-sefs: - @mkdir -p $(FS_PATH)/bin/ - @for test in $(TESTS) ; do \ - cp "$$test/$$test" $(FS_PATH)/bin/ ; \ - done - @rm -rf $(SEFS_PATH)/bin - @mkdir -p $(SEFS_PATH) - @cd $(PROJECT_DIR)/deps/sefs/sefs-fuse/bin/ && \ - ./app \ - --integrity-only \ - $(CUR_DIR)/$(SEFS_PATH)/bin \ - $(CUR_DIR)/$(FS_PATH)/bin \ - zip - @echo "SEFS => $@" - -lib-sefs: - @mkdir -p $(FS_PATH)/lib/ - @cp /lib/ld-musl-x86_64.so.1 $(FS_PATH)/lib/ - @cp /usr/local/occlum/lib/libc++.so.1 $(FS_PATH)/lib/ - @cp /usr/local/occlum/lib/libc++abi.so.1 $(FS_PATH)/lib/ - @cp /usr/local/occlum/lib/libunwind.so.1 $(FS_PATH)/lib/ - @rm -rf $(SEFS_PATH)/lib - @mkdir -p $(SEFS_PATH) - @cd $(PROJECT_DIR)/deps/sefs/sefs-fuse/bin/ && \ - ./app \ - --integrity-only \ - $(CUR_DIR)/$(SEFS_PATH)/lib \ - $(CUR_DIR)/$(FS_PATH)/lib \ - zip - @echo "SEFS => $@" - -libocclum.signed.so: Occlum.json Enclave_config.xml Enclave_private.pem - @$(PROJECT_DIR)/tools/bin/build-enclave Occlum.json Enclave_config.xml Enclave_private.pem - -Occlum.json: Occlum.json.sh $(BIN_SEFS_ROOT_FILE) $(LIB_SEFS_ROOT_FILE) - @./Occlum.json.sh \ - `$(PROJECT_DIR)/tools/bin/protect-integrity show-mac $(BIN_SEFS_ROOT_FILE)` \ - `$(PROJECT_DIR)/tools/bin/protect-integrity show-mac $(LIB_SEFS_ROOT_FILE)` \ - > $@ - @echo "GEN => $@" +postbuild: + @cd $(BUILD_DIR)/test && \ + $(PROJECT_DIR)/src/cli/occlum build ############################################################################# # Test targets @@ -98,7 +57,7 @@ Occlum.json: Occlum.json.sh $(BIN_SEFS_ROOT_FILE) $(LIB_SEFS_ROOT_FILE) test: build $(TEST_TARGETS) -$(TEST_TARGETS): test-%: % pal +$(TEST_TARGETS): test-%: % @$(ECHO) "$(CYAN)RUN TEST => $<$(NO_COLOR)" @$(MAKE) --no-print-directory -C $< test ; \ if [ $$? -eq 0 ] ; then \ @@ -107,20 +66,13 @@ $(TEST_TARGETS): test-%: % pal $(ECHO) "$(RED)FAILED$(NO_COLOR)" ; \ fi ; -pal: $(PROJECT_DIR)/src/pal/pal - @cp $< pal - -$(PROJECT_DIR)/src/pal/pal: - @cd $(PROJECT_DIR)/src/pal && make - - ############################################################################# # Benchmark targets ############################################################################# bench: build $(BENCH_TARGETS) -$(BENCH_TARGETS): bench-%: % pal libocclum.signed.so +$(BENCH_TARGETS): bench-%: % @$(ECHO) "$(CYAN)RUN BENCH => $<$(NO_COLOR)" @$(MAKE) --no-print-directory -C $< test ; \ if [ $$? -eq 0 ] ; then \ @@ -133,9 +85,5 @@ $(BENCH_TARGETS): bench-%: % pal libocclum.signed.so # Misc ############################################################################# -clean: $(CLEAN_TARGETS) - @$(RM) -f pal libocclum.signed.so Occlum.json.protected Occlum.json - @$(RM) -rf $(FS_PATH) $(SEFS_PATH) - -$(CLEAN_TARGETS): clean-%: - @$(MAKE) --no-print-directory -C $(patsubst clean-%,%,$@) clean +clean: + @$(RM) -rf $(BUILD_DIR)/test/* diff --git a/test/Occlum.json b/test/Occlum.json new file mode 100644 index 00000000..93930e04 --- /dev/null +++ b/test/Occlum.json @@ -0,0 +1,33 @@ +{ + "vm": { + "user_space_size": "128MB" + }, + "process": { + "default_stack_size": "4MB", + "default_heap_size": "16MB", + "default_mmap_size": "32MB" + }, + "mount": [ + { + "target": "/", + "type": "sefs", + "source": "./image", + "options": { + "integrity_only": true + } + }, + { + "target": "/root", + "type": "sefs" + }, + { + "target": "/host", + "type": "hostfs", + "source": "." + }, + { + "target": "/tmp", + "type": "ramfs" + } + ] +} diff --git a/test/hostfs/main.c b/test/hostfs/main.c index 3ce7c9f1..5c63a536 100644 --- a/test/hostfs/main.c +++ b/test/hostfs/main.c @@ -7,8 +7,9 @@ int main(int argc, const char* argv[]) { int fd, len; + // TODO: rewrite this test so that it does not need to depend on sample.txt +#if 0 char read_buf[128] = {0}; - // read if ((fd = open("/host/hostfs/sample.txt", O_RDONLY)) < 0) { printf("ERROR: failed to open a file for read\n"); @@ -25,9 +26,9 @@ int main(int argc, const char* argv[]) { return -1; } printf("Read file from hostfs successfully!\n"); - +#endif // write - if ((fd = open("/host/hostfs/test_write.txt", O_WRONLY | O_CREAT)) < 0) { + if ((fd = open("/host/hostfs_test_write.txt", O_WRONLY | O_CREAT)) < 0) { printf("ERROR: failed to open a file for write\n"); return -1; } diff --git a/test/test_common.mk b/test/test_common.mk index 77beaf7b..758a04fd 100644 --- a/test/test_common.mk +++ b/test/test_common.mk @@ -2,50 +2,54 @@ MAIN_MAKEFILE := $(firstword $(MAKEFILE_LIST)) INCLUDE_MAKEFILE := $(lastword $(MAKEFILE_LIST)) CUR_DIR := $(shell dirname $(realpath $(MAIN_MAKEFILE))) PROJECT_DIR := $(realpath $(CUR_DIR)/../../) +BUILD_DIR := $(PROJECT_DIR)/build + +TEST_NAME := $(shell basename $(CUR_DIR)) +IMAGE_DIR := $(BUILD_DIR)/test/image +BIN := $(IMAGE_DIR)/bin/$(TEST_NAME) + +C_SRCS := $(wildcard *.c) +C_OBJS := $(addprefix $(BUILD_DIR)/test/obj/$(TEST_NAME)/,$(C_SRCS:%.c=%.o)) +CXX_SRCS := $(wildcard *.cc) +CXX_OBJS := $(addprefix $(BUILD_DIR)/test/obj/$(TEST_NAME)/,$(CXX_SRCS:%.cc=%.o)) + +ALL_BUILD_SUBDIRS := $(sort $(patsubst %/,%,$(dir $(BIN) $(C_OBJS) $(CXX_OBJS)))) CC := /usr/local/occlum/bin/musl-clang CXX := /usr/local/occlum/bin/musl-clang++ -C_SRCS := $(wildcard *.c) -CXX_SRCS := $(wildcard *.cc) -C_OBJS := $(C_SRCS:%.c=%.o) -CXX_OBJS := $(CXX_SRCS:%.cc=%.o) -FS_PATH := ../fs -BIN_NAME := $(shell basename $(CUR_DIR)) -OBJDUMP_FILE := bin.objdump -READELF_FILE := bin.readelf - -CLANG_BIN_PATH := $(shell clang -print-prog-name=clang) -LLVM_PATH := $(abspath $(dir $(CLANG_BIN_PATH))../) C_FLAGS = -Wall -I../include -O2 -fPIC $(EXTRA_C_FLAGS) LINK_FLAGS = $(C_FLAGS) -pie $(EXTRA_LINK_FLAGS) -.PHONY: all test debug clean +.PHONY: all test test-native clean ############################################################################# # Build ############################################################################# -all: $(BIN_NAME) +all: $(ALL_BUILD_SUBDIRS) $(BIN) + +$(ALL_BUILD_SUBDIRS): + @mkdir -p $@ # Compile C/C++ test program # # When compiling programs, we do not use CXX if we're not compilng any C++ files. # This ensures C++ libraries are only linked and loaded for C++ programs, not C # programs. -$(BIN_NAME): $(C_OBJS) $(CXX_OBJS) +$(BIN): $(C_OBJS) $(CXX_OBJS) @if [ -z $(CXX_OBJS) ] ; then \ - $(CC) $^ $(LINK_FLAGS) -o $(BIN_NAME); \ + $(CC) $^ $(LINK_FLAGS) -o $(BIN); \ else \ - $(CXX) $^ $(LINK_FLAGS) -o $(BIN_NAME); \ + $(CXX) $^ $(LINK_FLAGS) -o $(BIN); \ fi ; @echo "LINK => $@" -$(C_OBJS): %.o: %.c +$(BUILD_DIR)/test/obj/$(TEST_NAME)/%.o: %.c @$(CC) $(C_FLAGS) -c $< -o $@ @echo "CC <= $@" -$(CXX_OBJS): %.o: %.cc +$(BUILD_DIR)/test/obj/$(TEST_NAME)/%.o: %.cc @$(CXX) $(C_FLAGS) -c $< -o $@ @echo "CXX <= $@" @@ -53,12 +57,16 @@ $(CXX_OBJS): %.o: %.cc # Test ############################################################################# -test: $(BIN_ENC_NAME) - @cd $(CUR_DIR)/.. && RUST_BACKTRACE=1 ./pal /bin/$(BIN_NAME) $(BIN_ARGS) +test: + @cd $(BUILD_DIR)/test && \ + $(PROJECT_DIR)/src/cli/occlum run /bin/$(TEST_NAME) $(BIN_ARGS) + +test-native: + @LD_LIBRARY_PATH=/usr/local/occlum/lib cd $(IMAGE_DIR) && ./bin/$(TEST_NAME) $(BIN_ARGS) ############################################################################# # Misc ############################################################################# clean: - @-$(RM) -f *.o *.S $(BIN_NAME) $(BIN_ENC_NAME) $(OBJDUMP_FILE) $(READELF_FILE) + @-$(RM) -f $(BIN) $(C_OBJS) $(CXX_OBJS) diff --git a/tools/protect-integrity/App/App.cpp b/tools/protect-integrity/App/App.cpp index 4f0f396b..4d3309b6 100644 --- a/tools/protect-integrity/App/App.cpp +++ b/tools/protect-integrity/App/App.cpp @@ -1,20 +1,20 @@ -#include -#include +#include "Enclave_u.h" + #include -#include -#include -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include +#include +#include +#include -#include -#include #include -#include "Enclave_u.h" +#include +#include #define MAX_PATH FILENAME_MAX #define TOKEN_FILENAME "enclave.token" @@ -33,8 +33,6 @@ typedef struct _sgx_errlist_t { const char *sug; /* Suggestion */ } sgx_errlist_t; -#define REPEATS 500000 - /* Error code returned by sgx_create_enclave */ static sgx_errlist_t sgx_errlist[] = { {