From 1a56fc4b72003fb35570f7cc615d98201d5a1bac Mon Sep 17 00:00:00 2001 From: Zhengde Zhai Date: Fri, 1 Nov 2019 05:42:38 +0000 Subject: [PATCH] Check program paths against entry points in Occlum.json --- etc/template/Occlum.json | 3 ++ src/libos/src/config.rs | 16 ++++++++- src/libos/src/entry.rs | 54 ++++++++++++++++++++++------ test/Occlum.json | 3 ++ tools/occlum | 8 ++++- tools/occlum-gen-default-occlum-json | 3 +- 6 files changed, 74 insertions(+), 13 deletions(-) diff --git a/etc/template/Occlum.json b/etc/template/Occlum.json index a7cc2c61..c263eeee 100644 --- a/etc/template/Occlum.json +++ b/etc/template/Occlum.json @@ -10,6 +10,9 @@ "env": [ "OCCLUM=yes" ], + "entry_points": [ + "/bin" + ], "mount": [ { "target": "/", diff --git a/src/libos/src/config.rs b/src/libos/src/config.rs index 260ae96a..0976aa66 100644 --- a/src/libos/src/config.rs +++ b/src/libos/src/config.rs @@ -80,6 +80,7 @@ pub struct Config { pub vm: ConfigVM, pub process: ConfigProcess, pub env: Vec, + pub entry_points: Vec, pub mount: Vec, } @@ -128,6 +129,17 @@ impl Config { } env }; + let entry_points = { + let mut entry_points = Vec::new(); + for ep in &input.entry_points { + let ep_path = Path::new(ep).to_path_buf(); + if !ep_path.is_absolute() { + return_errno!(EINVAL, "entry point must be an absolute path") + } + entry_points.push(ep_path); + } + entry_points + }; let mount = { let mut mount = Vec::new(); for input_mount in &input.mount { @@ -139,6 +151,7 @@ impl Config { vm, process, env, + entry_points, mount, }) } @@ -246,6 +259,8 @@ struct InputConfig { #[serde(default)] pub env: Vec, #[serde(default)] + pub entry_points: Vec, + #[serde(default)] pub mount: Vec, } @@ -269,7 +284,6 @@ impl Default for InputConfigVM { } } } - #[derive(Deserialize, Debug)] #[serde(deny_unknown_fields)] struct InputConfigProcess { diff --git a/src/libos/src/entry.rs b/src/libos/src/entry.rs index b46c1b49..06f832e6 100644 --- a/src/libos/src/entry.rs +++ b/src/libos/src/entry.rs @@ -2,7 +2,7 @@ use super::*; use exception::*; use process::pid_t; use std::ffi::{CStr, CString, OsString}; -use std::path::Path; +use std::path::{Path, PathBuf}; use util::mem_util::from_untrusted::*; const ENCLAVE_PATH: &'static str = ".occlum/build/lib/libocclum.signed.so"; @@ -60,15 +60,18 @@ pub extern "C" fn dummy_ecall() -> i32 { const EXIT_STATUS_INTERNAL_ERROR: i32 = 127; fn parse_arguments( - path_buf: *const c_char, + path_ptr: *const c_char, argv: *const *const c_char, -) -> Result<(String, Vec)> { - let path_string = { - let path_cstring = clone_cstring_safely(path_buf)?; - path_cstring.to_string_lossy().into_owned() +) -> Result<(PathBuf, Vec)> { + let path_buf = { + let path_cstring = clone_cstring_safely(path_ptr)?; + let path_string = path_cstring + .into_string() + .map_err(|e| errno!(EINVAL, "path contains valid utf-8 data"))?; + Path::new(&path_string).to_path_buf() }; let program_cstring = { - let program_osstr = Path::new(&path_string) + let program_osstr = path_buf .file_name() .ok_or_else(|| errno!(EINVAL, "invalid path"))?; let program_str = program_osstr @@ -79,18 +82,20 @@ fn parse_arguments( let mut args = clone_cstrings_safely(argv)?; args.insert(0, program_cstring); - Ok((path_string, args)) + Ok((path_buf, args)) } // TODO: make sure do_boot can only be called once -fn do_boot(path_str: &str, argv: &Vec) -> Result<()> { +fn do_boot(program_path: &PathBuf, argv: &Vec) -> Result<()> { // info!("boot: path: {:?}, argv: {:?}", path_str, argv); util::mpx_util::mpx_enable()?; + validate_program_path(program_path)?; + let envp = &config::LIBOS_CONFIG.env; let file_actions = Vec::new(); let parent = &process::IDLE_PROCESS; - process::do_spawn(&path_str, argv, envp, &file_actions, parent)?; + process::do_spawn(&program_path, argv, envp, &file_actions, parent)?; Ok(()) } @@ -106,3 +111,32 @@ fn do_run(host_tid: pid_t) -> Result { Ok(exit_status) } + +fn validate_program_path(target_path: &PathBuf) -> Result<()> { + if !target_path.is_absolute() { + return_errno!(EINVAL, "program path must be absolute"); + } + + // Forbid paths like /bin/../root, which may circument our prefix-based path matching + let has_parent_component = { + target_path + .components() + .any(|component| component == std::path::Component::ParentDir) + }; + if has_parent_component { + return_errno!( + EINVAL, + "program path cannot contain any parent component (i.e., \"..\")" + ); + } + + // Check whether the prefix of the program path matches one of the entry points + let is_valid_entry_point = &config::LIBOS_CONFIG + .entry_points + .iter() + .any(|valid_path_prefix| target_path.starts_with(valid_path_prefix)); + if !is_valid_entry_point { + return_errno!(EINVAL, "program path is a valid entry point"); + } + Ok(()) +} diff --git a/test/Occlum.json b/test/Occlum.json index 5e2da2bd..924b2020 100644 --- a/test/Occlum.json +++ b/test/Occlum.json @@ -11,6 +11,9 @@ "OCCLUM=yes", "TEST=true" ], + "entry_points": [ + "/bin" + ], "mount": [ { "target": "/", diff --git a/tools/occlum b/tools/occlum index 78c133a6..df6dd018 100755 --- a/tools/occlum +++ b/tools/occlum @@ -52,6 +52,11 @@ get_conf_env() { python -c "import sys, json; print json.dumps(json.load(sys.stdin)['env'])" } +get_conf_entry_points() { + cat "$working_dir/Occlum.json" | \ + python -c "import sys, json; print json.dumps(json.load(sys.stdin)['entry_points'])" +} + get_occlum_conf_file_mac() { "$occlum_dir/build/bin/occlum-protect-integrity" show-mac "$context_dir/build/Occlum.json.protected" } @@ -78,7 +83,7 @@ cmd_init() { local occlum_gcc_lib=/usr/local/occlum/x86_64-linux-musl/lib cp -t image/lib/ \ - /lib/ld-musl-x86_64.so.1 \ + /lib/ld-musl-x86_64.so.1 \ "$occlum_gcc_lib/libc.so" \ "$occlum_gcc_lib/libstdc++.so.6" \ "$occlum_gcc_lib/libgcc_s.so.1" \ @@ -121,6 +126,7 @@ cmd_build() { 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 "$context_dir/build" "$occlum_dir/build/bin/occlum-gen-default-occlum-json"\ > "Occlum.json" diff --git a/tools/occlum-gen-default-occlum-json b/tools/occlum-gen-default-occlum-json index 95fb0908..8e81b474 100755 --- a/tools/occlum-gen-default-occlum-json +++ b/tools/occlum-gen-default-occlum-json @@ -34,6 +34,7 @@ cat <