diff --git a/tools/Makefile b/tools/Makefile index f3fd4454..3ace6881 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -7,9 +7,8 @@ all: @mkdir -p ../$(BUILD_DIR)/bin/ @ln -s -f ../../tools/occlum_build.mk ../$(BUILD_DIR)/bin/occlum_build.mk @ln -s -f ../../tools/occlum ../$(BUILD_DIR)/bin/occlum - @ln -s -f ../../tools/occlum-gen-default-occlum-json ../$(BUILD_DIR)/bin/occlum-gen-default-occlum-json @$(MAKE) --no-print-directory -C protect-integrity - @$(MAKE) --no-print-directory -C gen_enclave_conf + @$(MAKE) --no-print-directory -C gen_internal_conf format: @$(MAKE) --no-print-directory -C protect-integrity format @@ -19,4 +18,4 @@ format-check: clean: @$(MAKE) --no-print-directory -C protect-integrity clean - @$(MAKE) --no-print-directory -C gen_enclave_conf clean + @$(MAKE) --no-print-directory -C gen_internal_conf clean diff --git a/tools/gen_enclave_conf/src/main.rs b/tools/gen_enclave_conf/src/main.rs deleted file mode 100644 index ac8a1637..00000000 --- a/tools/gen_enclave_conf/src/main.rs +++ /dev/null @@ -1,196 +0,0 @@ -extern crate clap; -extern crate env_logger; -extern crate log; -extern crate regex; -extern crate serde; -extern crate serde_derive; -extern crate serde_xml_rs; - -use clap::{App, Arg}; -use log::debug; -use serde_derive::{Deserialize, Serialize}; -use std::fs::File; -use std::io::Write; -use std::path::Path; - -fn main() { - env_logger::init(); - - let matches = App::new("gen_enclave_conf") - .version("0.1.0") - .arg( - Arg::with_name("input") - .short("i") - .long("input") - .required(true) - .validator(|f| match Path::new(&f).exists() { - true => Ok(()), - false => { - let err_message = String::from(f) + " is not exist"; - Err(err_message) - } - }) - .takes_value(true), - ) - .arg( - Arg::with_name("output") - .short("o") - .long("output") - .required(true) - .validator(|f| match File::create(f) { - Ok(_e) => Ok(()), - Err(e) => Err(e.to_string()), - }) - .takes_value(true), - ) - .get_matches(); - - let occlum_config_file_path = matches.value_of("input").unwrap(); - debug!( - "Occlum config (json) file name {:?}", - occlum_config_file_path - ); - - let enclave_config_file_path = matches.value_of("output").unwrap(); - debug!( - "Enclave config (xml) file name {:?}", - enclave_config_file_path - ); - - // Read the occlum configuration file - let occlum_config_file = - File::open(occlum_config_file_path).expect("The Occlum configuration file does not exist"); - let occlum_config: OcclumConfiguration = serde_json::from_reader(occlum_config_file) - .expect("It is not a valid Occlum configuration file."); - debug!("The occlum config is:{:?}", occlum_config); - - // get the kernel stack size - let stack_max_size = parse_memory_size(&occlum_config.resource_limits.kernel_space_stack_size); - if stack_max_size.is_err() { - println!( - "The kernel_space_stack_size \"{}\" is not correct.", - occlum_config.resource_limits.kernel_space_stack_size - ); - return; - } - - // get the kernel heap size - let heap_max_size = parse_memory_size(&occlum_config.resource_limits.kernel_space_heap_size); - if heap_max_size.is_err() { - println!( - "The kernel_space_heap_size \"{}\" is not correct.", - occlum_config.resource_limits.kernel_space_heap_size - ); - return; - } - - // get the user space size - let user_space_size = parse_memory_size(&occlum_config.resource_limits.user_space_size); - if user_space_size.is_err() { - println!( - "The user_space_size \"{}\" is not correct.", - occlum_config.resource_limits.user_space_size - ); - return; - } - - let sgx_enclave_configuration = EnclaveConfiguration { - ProdID: occlum_config.metadata.product_id, - ISVSVN: occlum_config.metadata.version_number, - StackMaxSize: stack_max_size.unwrap() as u64, - HeapMaxSize: heap_max_size.unwrap() as u64, - TCSNum: occlum_config.resource_limits.max_num_of_threads, - TCSPolicy: 1, - DisableDebug: match occlum_config.metadata.debuggable { - true => 0, - false => 1, - }, - MiscSelect: "0".to_string(), - MiscMask: "0xFFFFFFFF".to_string(), - ReservedMemMaxSize: user_space_size.unwrap() as u64, - ReservedMemMinSize: user_space_size.unwrap() as u64, - ReservedMemInitSize: user_space_size.unwrap() as u64, - ReservedMemExecutable: 1, - }; - - // Generate the enclave configuration - let enclave_config = serde_xml_rs::to_string(&sgx_enclave_configuration).unwrap(); - debug!("The enclave config:{:?}", enclave_config); - - // Update the output file - let mut enclave_config_file = File::create(enclave_config_file_path) - .expect("Could not open the target Enclave configuration file."); - enclave_config_file - .write_all(enclave_config.as_bytes()) - .expect("Failed to update the Enclave configuration file."); -} - -fn parse_memory_size(mem_str: &str) -> Result { - const UNIT2FACTOR: [(&str, usize); 5] = [ - ("KB", 1024), - ("MB", 1024 * 1024), - ("GB", 1024 * 1024 * 1024), - ("TB", 1024 * 1024 * 1024 * 1024), - ("B", 1), - ]; - - // Extract the unit part of the memory size - let mem_str = mem_str.trim(); - let (mem_unit, unit_factor) = UNIT2FACTOR - .iter() - .position(|(mem_unit, _)| mem_str.ends_with(mem_unit)) - .ok_or_else(|| "No unit") - .map(|unit_i| &UNIT2FACTOR[unit_i])?; - - // Extract the value part of the memory size - let mem_val = match mem_str[0..mem_str.len() - mem_unit.len()] - .trim() - .parse::() - { - Err(_) => { - return Err("No number"); - } - Ok(mem_val) => mem_val, - }; - - Ok(mem_val * unit_factor) -} - -#[derive(Debug, PartialEq, Deserialize)] -struct OcclumConfiguration { - metadata: OcclumMetadata, - resource_limits: OcclumResourceLimits, -} - -#[derive(Debug, PartialEq, Deserialize)] -struct OcclumMetadata { - product_id: u32, - version_number: u32, - debuggable: bool, -} - -#[derive(Debug, PartialEq, Deserialize)] -struct OcclumResourceLimits { - max_num_of_threads: u32, - kernel_space_heap_size: String, - kernel_space_stack_size: String, - user_space_size: String, -} - -#[allow(non_snake_case)] -#[derive(Debug, PartialEq, Serialize)] -struct EnclaveConfiguration { - ProdID: u32, - ISVSVN: u32, - StackMaxSize: u64, - HeapMaxSize: u64, - TCSNum: u32, - TCSPolicy: u32, - DisableDebug: u32, - MiscSelect: String, - MiscMask: String, - ReservedMemMaxSize: u64, - ReservedMemMinSize: u64, - ReservedMemInitSize: u64, - ReservedMemExecutable: u32, -} diff --git a/tools/gen_enclave_conf/.gitignore b/tools/gen_internal_conf/.gitignore similarity index 100% rename from tools/gen_enclave_conf/.gitignore rename to tools/gen_internal_conf/.gitignore diff --git a/tools/gen_enclave_conf/Cargo.lock b/tools/gen_internal_conf/Cargo.lock similarity index 99% rename from tools/gen_enclave_conf/Cargo.lock rename to tools/gen_internal_conf/Cargo.lock index 1798e9cd..57fad33b 100644 --- a/tools/gen_enclave_conf/Cargo.lock +++ b/tools/gen_internal_conf/Cargo.lock @@ -70,8 +70,8 @@ dependencies = [ ] [[package]] -name = "gen_enclave_conf" -version = "0.1.0" +name = "gen_internal_conf" +version = "0.2.0" dependencies = [ "clap", "env_logger", diff --git a/tools/gen_enclave_conf/Cargo.toml b/tools/gen_internal_conf/Cargo.toml similarity index 84% rename from tools/gen_enclave_conf/Cargo.toml rename to tools/gen_internal_conf/Cargo.toml index 087f08b0..c30e564b 100644 --- a/tools/gen_enclave_conf/Cargo.toml +++ b/tools/gen_internal_conf/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "gen_enclave_conf" -version = "0.1.0" +name = "gen_internal_conf" +version = "0.2.0" authors = ["zongmin.gu "] edition = "2018" diff --git a/tools/gen_enclave_conf/Makefile b/tools/gen_internal_conf/Makefile similarity index 80% rename from tools/gen_enclave_conf/Makefile rename to tools/gen_internal_conf/Makefile index ad120838..6d70fc61 100644 --- a/tools/gen_enclave_conf/Makefile +++ b/tools/gen_internal_conf/Makefile @@ -3,17 +3,17 @@ include ../../src/sgxenv.mk SRC_FILES := $(shell find . -type f -name '*.rs') Cargo.toml RUST_TARGET_DIR := $(BUILD_DIR)/internal/tools/genconf/cargo-target RUST_OUT_DIR := $(BUILD_DIR)/bin -TARGET_BINARY := $(RUST_OUT_DIR)/gen_enclave_conf +TARGET_BINARY := $(RUST_OUT_DIR)/gen_internal_conf .PHONY: all clean all: $(SRC_FILES) ifeq ($(OCCLUM_RELEASE_BUILD), 1) @RUSTC_BOOTSTRAP=1 cargo build --release --target-dir=$(RUST_TARGET_DIR) -Z unstable-options --out-dir=$(RUST_OUT_DIR) - @echo "CARGO (release) => gen_enclave_conf" + @echo "CARGO (release) => gen_internal_conf" else @RUSTC_BOOTSTRAP=1 cargo build --target-dir=$(RUST_TARGET_DIR) -Z unstable-options --out-dir=$(RUST_OUT_DIR) - @echo "CARGO (debug) => gen_enclave_conf" + @echo "CARGO (debug) => gen_internal_conf" endif clean: diff --git a/tools/gen_internal_conf/src/main.rs b/tools/gen_internal_conf/src/main.rs new file mode 100644 index 00000000..13692f8d --- /dev/null +++ b/tools/gen_internal_conf/src/main.rs @@ -0,0 +1,351 @@ +extern crate clap; +extern crate env_logger; +extern crate log; +extern crate regex; +extern crate serde; +extern crate serde_derive; +extern crate serde_xml_rs; + +use clap::{App, Arg}; +use log::debug; +use serde_derive::{Deserialize, Serialize}; +use serde_json::json; +use std::fs::File; +use std::io::Write; +use std::path::Path; + +// This is not really used anymore. +// Just keep it here in case we need it in the future. +const OCCLUM_INSTANCE_DIR: &str = "."; + +fn main() { + env_logger::init(); + + let matches = App::new("gen_internal_conf") + .version("0.2.0") + // Input: JSON file which users may change + .arg( + Arg::with_name("user_json") + .long("user_json") + .value_name("input: user_json") + .required(true) + .validator(|f| match Path::new(&f).exists() { + true => Ok(()), + false => { + let err_message = String::from(f) + " is not exist"; + Err(err_message) + } + }) + .takes_value(true), + ) + // Input: Secure Occlum FS image MAC + .arg( + Arg::with_name("fs_mac") + .long("fs_mac") + .value_name("input: fs_mac") + .required(true) + .takes_value(true), + ) + // Output: XML file used by Intel SGX SDK + .arg( + Arg::with_name("sdk_xml") + .long("sdk_xml") + .value_name("output: sdk_xml") + .required(true) + .validator(|f| match File::create(f) { + Ok(_e) => Ok(()), + Err(e) => Err(e.to_string()), + }) + .takes_value(true), + ) + // Output: JSON file used by libOS and users shouldn't touch + .arg( + Arg::with_name("sys_json") + .long("sys_json") + .value_name("output: sys_json") + .required(true) + .validator(|f| match File::create(f) { + Ok(_) => Ok(()), + Err(e) => Err(e.to_string()), + }) + .takes_value(true), + ) + .get_matches(); + + let occlum_config_file_path = matches.value_of("user_json").unwrap(); + debug!( + "Occlum config (json) file name {:?}", + occlum_config_file_path + ); + + let occlum_conf_root_fs_mac = matches.value_of("fs_mac").unwrap(); + debug!( + "Occlum config root FS MAC {:?}", + occlum_conf_root_fs_mac + ); + + let enclave_config_file_path = matches.value_of("sdk_xml").unwrap(); + debug!( + "Enclave config (xml) file name {:?}", + enclave_config_file_path + ); + + let occlum_internal_json_file_path = matches.value_of("sys_json").unwrap(); + debug!( + "Genereated Occlum internal config (json) file name {:?}", + occlum_internal_json_file_path + ); + + // Read the occlum configuration file + let occlum_config_file = + File::open(occlum_config_file_path).expect("The Occlum configuration file does not exist"); + let occlum_config: OcclumConfiguration = serde_json::from_reader(occlum_config_file) + .expect("It is not a valid Occlum configuration file."); + debug!("The occlum config is:{:?}", occlum_config); + + // get the kernel stack size + let stack_max_size = parse_memory_size(&occlum_config.resource_limits.kernel_space_stack_size); + if stack_max_size.is_err() { + println!( + "The kernel_space_stack_size \"{}\" is not correct.", + occlum_config.resource_limits.kernel_space_stack_size + ); + return; + } + + // get the kernel heap size + let heap_max_size = parse_memory_size(&occlum_config.resource_limits.kernel_space_heap_size); + if heap_max_size.is_err() { + println!( + "The kernel_space_heap_size \"{}\" is not correct.", + occlum_config.resource_limits.kernel_space_heap_size + ); + return; + } + + // get the user space size + let user_space_size = parse_memory_size(&occlum_config.resource_limits.user_space_size); + if user_space_size.is_err() { + println!( + "The user_space_size \"{}\" is not correct.", + occlum_config.resource_limits.user_space_size + ); + return; + } + + // Generate the enclave configuration + let sgx_enclave_configuration = EnclaveConfiguration { + ProdID: occlum_config.metadata.product_id, + ISVSVN: occlum_config.metadata.version_number, + StackMaxSize: stack_max_size.unwrap() as u64, + StackMinSize: stack_max_size.unwrap() as u64, // just use the same size as max size + HeapMaxSize: heap_max_size.unwrap() as u64, + HeapMinSize: heap_max_size.unwrap() as u64, // just use the same size as max size + TCSNum: occlum_config.resource_limits.max_num_of_threads, + TCSPolicy: 1, + DisableDebug: match occlum_config.metadata.debuggable { + true => 0, + false => 1, + }, + MiscSelect: "0".to_string(), + MiscMask: "0xFFFFFFFF".to_string(), + ReservedMemMaxSize: user_space_size.unwrap() as u64, + ReservedMemMinSize: user_space_size.unwrap() as u64, + ReservedMemInitSize: user_space_size.unwrap() as u64, + ReservedMemExecutable: 1, + }; + + let enclave_config = serde_xml_rs::to_string(&sgx_enclave_configuration).unwrap(); + debug!("The enclave config:{:?}", enclave_config); + + // Generate internal Occlum.json - "sys_json" + let internal_occlum_json_config = InternalOcclumJson { + resource_limits: InternalResourceLimits { + user_space_size: occlum_config.resource_limits.user_space_size.to_string(), + }, + process: OcclumProcess { + default_stack_size: occlum_config.process.default_stack_size, + default_heap_size: occlum_config.process.default_heap_size, + default_mmap_size: occlum_config.process.default_mmap_size, + }, + entry_points: occlum_config.entry_points, + env: occlum_config.env, + mount: gen_mount_config(occlum_conf_root_fs_mac.to_string()), + }; + let internal_occlum_json_str = + serde_json::to_string_pretty(&internal_occlum_json_config).unwrap(); + debug!("The internal Occlum.json config:\n{:?}", internal_occlum_json_str); + + // Update the output file + let mut enclave_config_file = File::create(enclave_config_file_path) + .expect("Could not open the target Enclave configuration file."); + enclave_config_file + .write_all(enclave_config.as_bytes()) + .expect("Failed to update the Enclave configuration file."); + + let mut internal_occlum_json = File::create(occlum_internal_json_file_path) + .expect("Could not open the internal Occlum.json file."); + internal_occlum_json + .write_all(internal_occlum_json_str.as_bytes()) + .expect("Failed to update the internal Occlum.json file."); +} + +fn parse_memory_size(mem_str: &str) -> Result { + const UNIT2FACTOR: [(&str, usize); 5] = [ + ("KB", 1024), + ("MB", 1024 * 1024), + ("GB", 1024 * 1024 * 1024), + ("TB", 1024 * 1024 * 1024 * 1024), + ("B", 1), + ]; + + // Extract the unit part of the memory size + let mem_str = mem_str.trim(); + let (mem_unit, unit_factor) = UNIT2FACTOR + .iter() + .position(|(mem_unit, _)| mem_str.ends_with(mem_unit)) + .ok_or_else(|| "No unit") + .map(|unit_i| &UNIT2FACTOR[unit_i])?; + + // Extract the value part of the memory size + let mem_val = match mem_str[0..mem_str.len() - mem_unit.len()] + .trim() + .parse::() + { + Err(_) => { + return Err("No number"); + } + Ok(mem_val) => mem_val, + }; + + Ok(mem_val * unit_factor) +} + +fn gen_mount_config(occlum_conf_root_fs_mac: String) -> serde_json::Value { + let mut internal_mount_config: serde_json::Value = json!({ + "mount": [ + { + "target": "/", + "type": "unionfs", + "options": { + "layers": [ + { + "target": "/", + "type": "sefs", + "source": "", + "options": { + "integrity_only": true, + "MAC": "" + } + }, + { + "target": "/", + "type": "sefs", + "source": "" + } + ] + } + }, + { + "target": "/host", + "type": "hostfs", + "source": "." + }, + { + "target": "/tmp", + "type": "sefs", + "source": "", + "options": { + "temporary": true + } + } + ] + }); + + let unionfs_base_source_path = format!("{}{}", OCCLUM_INSTANCE_DIR, "/build/mount/__ROOT"); + let unionfs_run_source_path = format!("{}{}", OCCLUM_INSTANCE_DIR, "/run/mount/__ROOT"); + let tmp_run_source_path = format!("{}{}", OCCLUM_INSTANCE_DIR, "/run/mount/tmp"); + + *internal_mount_config + .pointer_mut("/mount/0/options/layers/0/source") + .unwrap() = serde_json::Value::String(unionfs_base_source_path); + *internal_mount_config + .pointer_mut("/mount/0/options/layers/0/options/MAC") + .unwrap() = serde_json::Value::String(occlum_conf_root_fs_mac); + *internal_mount_config + .pointer_mut("/mount/0/options/layers/1/source") + .unwrap() = serde_json::Value::String(unionfs_run_source_path); + *internal_mount_config + .pointer_mut("/mount/2/source") + .unwrap() = serde_json::Value::String(tmp_run_source_path); + + debug!("internal Occlum.json mount config:\n{:?}", internal_mount_config); + + internal_mount_config["mount"].to_owned() +} + +#[derive(Debug, PartialEq, Deserialize)] +struct OcclumConfiguration { + resource_limits: OcclumResourceLimits, + process: OcclumProcess, + entry_points: serde_json::Value, + env: serde_json::Value, + metadata: OcclumMetadata, + mount: serde_json::Value, +} + +#[derive(Debug, PartialEq, Deserialize)] +struct OcclumResourceLimits { + max_num_of_threads: u32, + kernel_space_heap_size: String, + kernel_space_stack_size: String, + user_space_size: String, +} + +#[derive(Debug, PartialEq, Deserialize, Serialize)] +struct OcclumProcess { + default_stack_size: String, + default_heap_size: String, + default_mmap_size: String, +} + +#[derive(Debug, PartialEq, Deserialize)] +struct OcclumMetadata { + product_id: u32, + version_number: u32, + debuggable: bool, +} + +#[allow(non_snake_case)] +#[derive(Debug, PartialEq, Serialize)] +struct EnclaveConfiguration { + ProdID: u32, + ISVSVN: u32, + StackMaxSize: u64, + StackMinSize: u64, + HeapMaxSize: u64, + HeapMinSize: u64, + TCSNum: u32, + TCSPolicy: u32, + DisableDebug: u32, + MiscSelect: String, + MiscMask: String, + ReservedMemMaxSize: u64, + ReservedMemMinSize: u64, + ReservedMemInitSize: u64, + ReservedMemExecutable: u32, +} + +#[derive(Debug, PartialEq, Serialize)] +struct InternalResourceLimits { + user_space_size: String, +} + +#[derive(Debug, PartialEq, Serialize)] +struct InternalOcclumJson { + resource_limits: InternalResourceLimits, + process: OcclumProcess, + entry_points: serde_json::Value, + env: serde_json::Value, + mount: serde_json::Value, +} diff --git a/tools/installer/rpm/occlum-filelist b/tools/installer/rpm/occlum-filelist index 4d11528d..6cda047c 100644 --- a/tools/installer/rpm/occlum-filelist +++ b/tools/installer/rpm/occlum-filelist @@ -1,4 +1,4 @@ -/opt/occlum/build/bin/gen_enclave_conf +/opt/occlum/build/bin/gen_internal_conf /opt/occlum/build/bin/occlum-gen-default-occlum-json /opt/occlum/build/bin/occlum-protect-integrity /opt/occlum/build/bin/sefs-cli diff --git a/tools/occlum-gen-default-occlum-json b/tools/occlum-gen-default-occlum-json deleted file mode 100755 index 789062aa..00000000 --- a/tools/occlum-gen-default-occlum-json +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -OCCLUM_INSTANCE_DIR="." - -cat < 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 $(instance_dir)/build/lib && \ cp "$(occlum_dir)/build/lib/$(libos_lib).$(occlum_version)" . && ln -sf "$(libos_lib).$(occlum_version)" "libocclum-libos.so.$(major_ver)" && \ ln -sf "libocclum-libos.so.$(major_ver)" libocclum-libos.so ; \ @@ -101,16 +64,10 @@ $(instance_dir)/build/Occlum.json.protected: $(instance_dir)/build/Occlum.json @cd "$(instance_dir)/build" ; \ LD_LIBRARY_PATH="$(SGX_SDK)/sdk_libs" "$(occlum_dir)/build/bin/occlum-protect-integrity" protect Occlum.json ; +$(instance_dir)/build/Enclave.xml: $(instance_dir)/build/Occlum.json: $(SECURE_IMAGE) $(JSON_CONF) | $(instance_dir)/build/lib - @export OCCLUM_CONF_ROOT_FS_MAC=`$(get_conf_root_fs_mac)` ; \ - 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)` ; \ - export OCCLUM_CONF_ENV="`$(get_conf_env)`" ; \ - export OCCLUM_CONF_ENTRY_POINTS=`$(get_conf_entry_points)` ; \ - cd "$(instance_dir)/build" ; \ - "$(occlum_dir)/build/bin/occlum-gen-default-occlum-json" > "Occlum.json" + @$(occlum_dir)/build/bin/gen_internal_conf --user_json "$(instance_dir)/Occlum.json" --fs_mac `$(get_conf_root_fs_mac)` \ + --sdk_xml "$(instance_dir)/build/Enclave.xml" --sys_json $(instance_dir)/build/Occlum.json $(BIN_LINKS): $(instance_dir)/build/bin/%: $(occlum_dir)/build/bin/% | $(instance_dir)/build/bin @ln -sf $< $@