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.
This commit is contained in:
Tate, Hongliang Tian 2019-08-27 12:19:33 +00:00
parent 7001b32a4a
commit d77c21f98c
19 changed files with 515 additions and 296 deletions

7
.gitignore vendored

@ -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/

25
test/Occlum.json.sh → etc/template/Occlum.json Executable file → Normal file

@ -1,8 +1,3 @@
#!/bin/bash
bin_sefs_mac=$1
lib_sefs_mac=$2
cat <<EOF
{
"vm": {
"user_space_size": "128MB"
@ -16,25 +11,14 @@ cat <<EOF
{
"target": "/",
"type": "sefs",
"source": "./sefs/root"
},
{
"target": "/bin",
"type": "sefs",
"source": "./sefs/bin",
"source": "./image",
"options": {
"integrity_only": true,
"MAC": "$bin_sefs_mac"
"integrity_only": true
}
},
{
"target": "/lib",
"type": "sefs",
"source": "./sefs/lib",
"options": {
"integrity_only": true,
"MAC": "$lib_sefs_mac"
}
"target": "/root",
"type": "sefs"
},
{
"target": "/host",
@ -47,4 +31,3 @@ cat <<EOF
}
]
}
EOF

173
src/cli/occlum Executable file

@ -0,0 +1,173 @@
#!/bin/bash
working_dir=`pwd`
this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/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 <program_name> <program_args>"
}
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

@ -0,0 +1,38 @@
#!/bin/bash
cat <<EOF
{
"vm": {
"user_space_size": "$OCCLUM_CONF_USER_SPACE_SIZE"
},
"process": {
"default_stack_size": "$OCCLUM_CONF_DEFAULT_STACK_SIZE",
"default_heap_size": "$OCCLUM_CONF_DEFAULT_HEAP_SIZE",
"default_mmap_size": "$OCCLUM_CONF_DEFAULT_MMAP_SIZE"
},
"mount": [
{
"target": "/",
"type": "sefs",
"source": ".occlum/build/mount/__ROOT",
"options": {
"integrity_only": true,
"MAC": "$OCCLUM_CONF_ROOT_FS_MAC"
}
},
{
"target": "/root",
"type": "sefs",
"source": ".occlum/run/mount/root"
},
{
"target": "/host",
"type": "hostfs",
"source": "."
},
{
"target": "/tmp",
"type": "ramfs"
}
]
}
EOF

@ -1,19 +1,32 @@
include ../sgxenv.mk
DEBUG := 1
RELEASE ?= 0
ONLY_REBUILD_BUILTIN ?= 0
LIBOS_SO := libocclum.so # Link $(LIBOS_A), $(C_OBJS) and all dependencies
LIBOS_A := libocclum_rs.a # Built from Rust code
# The final and intermediate libraries
#
# The relationships between the three Occlum libraries
# $(LIBOS_SO) > $(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)

@ -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 = {

@ -15,7 +15,7 @@ lazy_static! {
pub static ref ROOT_INODE: Arc<INode> = {
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<ConfigMount>,
) -> Result<Arc<MountFS>, Error> {
fn open_root_fs_according_to(mount_config: &Vec<ConfigMount>) -> Result<Arc<MountFS>, 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<dyn FileSystem>, 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(())

@ -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)

@ -1,22 +1,34 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/time.h>
#include <time.h>
#include <sys/syscall.h>
#include <errno.h>
#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 <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <unistd.h>
#include <sgx_eid.h>
#include <sgx_error.h>
#include <sgx_urts.h>
#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;

@ -1,33 +0,0 @@
#ifndef _PAL_H_
#define _PAL_H_
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#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_ */

@ -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

12
test/Enclave.xml Normal file

@ -0,0 +1,12 @@
<!-- Please refer to User's Guide for the explanation of each field -->
<EnclaveConfiguration>
<ProdID>0</ProdID>
<ISVSVN>0</ISVSVN>
<StackMaxSize>0x100000</StackMaxSize>
<HeapMaxSize>0x2000000</HeapMaxSize>
<TCSNum>8</TCSNum>
<TCSPolicy>1</TCSPolicy>
<DisableDebug>0</DisableDebug>
<MiscSelect>0</MiscSelect>
<MiscMask>0xFFFFFFFF</MiscMask>
</EnclaveConfiguration>

@ -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/*

33
test/Occlum.json Normal file

@ -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"
}
]
}

@ -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;
}

@ -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)

@ -1,20 +1,20 @@
#include <stdio.h>
#include <string.h>
#include "Enclave_u.h"
#include <assert.h>
#include <sys/time.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <libgen.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sgx_urts.h>
#include <sgx_error.h>
#include <sgx_eid.h>
#include "Enclave_u.h"
#include <sgx_error.h>
#include <sgx_urts.h>
#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[] = {
{