Support passing user's envs for runtime boot case
This commit is contained in:
parent
d864542c34
commit
ac5d385747
@ -25,6 +25,8 @@ The second parameter `rootfs_config` needs to be set as NULL.
|
||||
But for runtime booting pre-generated UnionFS image, The first parameter `key_ptr` is must to have, the second parameter `rootfs_config` needs have valid members.
|
||||
```
|
||||
struct user_rootfs_config {
|
||||
// length of the struct
|
||||
len: usize,
|
||||
// UnionFS type rootfs upper layer, read-write layer
|
||||
upper_layer_path: *const i8,
|
||||
// UnionFS type rootfs lower layer, read-only layer
|
||||
@ -34,11 +36,18 @@ struct user_rootfs_config {
|
||||
hostfs_source: *const i8,
|
||||
// HostFS target path, default value is "/host"
|
||||
hostfs_target: *const i8,
|
||||
// An array of pointers to null-terminated strings
|
||||
// and must be terminated by a null pointer
|
||||
envp: *const *const i8,
|
||||
}
|
||||
```
|
||||
|
||||
In this demo, parameters values are provided as below.
|
||||
|
||||
* **len**
|
||||
The length of the struct which should be the value of `size_of(user_rootfs_config)`.
|
||||
It is helpful for possible future extension.
|
||||
|
||||
* **rootfs_key**
|
||||
The key to encrypt/decrypt the rootfs, here it is `"c7-32-b3-ed-44-df-ec-7b-25-2d-9a-32-38-8d-58-61".
|
||||
|
||||
@ -54,6 +63,10 @@ The entry point of the rootfs. In his case, it is `"/bin"`.
|
||||
* **hostfs_source**
|
||||
It is set to be `/tmp` in this case.
|
||||
|
||||
* **envp**
|
||||
An array of pointers to null-terminated strings and must be terminated by a null pointer.
|
||||
For example, set it to the address of ["TEST=1234", "TEST2=4567", NULL].
|
||||
|
||||
In this example customized init, the above parameters are declared in the source [`main.rs`](./init/src/main.rs). In real case, they could be acquired by LA/RA or by modifying the PAL api `pal_run_init_process`.
|
||||
|
||||
### Build a boot template Occlum instance
|
||||
@ -71,5 +84,7 @@ After running the script, runtime boot BASH could be done as below even if the d
|
||||
# occlum run /bin/occlum_bash_test.sh
|
||||
```
|
||||
|
||||
|
||||
|
||||
Also, the runtime environment passed by **envp** could be verified by
|
||||
```
|
||||
# occlum run /bin/busybox env
|
||||
```
|
||||
|
@ -9,15 +9,11 @@ use std::error::Error;
|
||||
use std::fs::File;
|
||||
use std::io::{ErrorKind, Read};
|
||||
|
||||
use std::mem::size_of;
|
||||
use std::ffi::CString;
|
||||
use std::env;
|
||||
|
||||
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
println!("{:?}", args);
|
||||
|
||||
// TODO: Get the rootfs key and other parameters through RA/LA or PAL
|
||||
let rootfs_key = b"c7-32-b3-ed-44-df-ec-7b-25-2d-9a-32-38-8d-58-61";
|
||||
let rootfs_upper_layer = "../gen_rootfs_instance/mnt_unionfs/upper";
|
||||
@ -53,12 +49,21 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
CString::new(rootfs_lower_layer).expect("CString::new failed");
|
||||
let entry_point = CString::new(rootfs_entry).expect("CString::new failed");
|
||||
let hostfs_source = CString::new("/tmp").expect("CString::new failed");
|
||||
|
||||
// Example envs. must end with null
|
||||
let env1 = CString::new("TEST=1234").unwrap();
|
||||
let env2 = CString::new("OCCLUM=NO").unwrap();
|
||||
let env3 = CString::new("TEST2=5678").unwrap();
|
||||
let envp = [env1.as_ptr(), env2.as_ptr(), env3.as_ptr(), std::ptr::null()];
|
||||
|
||||
let rootfs_config: user_rootfs_config = user_rootfs_config {
|
||||
len: size_of::<user_rootfs_config>(),
|
||||
upper_layer_path: upper_layer_path.as_ptr(),
|
||||
lower_layer_path: lower_layer_path.as_ptr(),
|
||||
entry_point: entry_point.as_ptr(),
|
||||
hostfs_source: hostfs_source.as_ptr(),
|
||||
hostfs_target: std::ptr::null()
|
||||
hostfs_target: std::ptr::null(),
|
||||
envp: envp.as_ptr()
|
||||
};
|
||||
|
||||
let ret = unsafe { syscall(
|
||||
@ -80,6 +85,8 @@ type sgx_key_128bit_t = [u8; 16];
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
struct user_rootfs_config {
|
||||
// length of the struct
|
||||
len: usize,
|
||||
// UnionFS type rootfs upper layer, read-write layer
|
||||
upper_layer_path: *const i8,
|
||||
// UnionFS type rootfs lower layer, read-only layer
|
||||
@ -89,6 +96,9 @@ struct user_rootfs_config {
|
||||
hostfs_source: *const i8,
|
||||
// HostFS target path, default value is "/host"
|
||||
hostfs_target: *const i8,
|
||||
// An array of pointers to null-terminated strings
|
||||
// and must be terminated by a null pointer
|
||||
envp: *const *const i8,
|
||||
}
|
||||
|
||||
fn load_key(key_path: &str) -> Result<String, Box<dyn Error>> {
|
||||
|
@ -22,6 +22,12 @@ lazy_static! {
|
||||
};
|
||||
}
|
||||
|
||||
// Envs merged from default envs and possible envs passed by syscall do_mount_rootfs
|
||||
lazy_static! {
|
||||
pub static ref TRUSTED_ENVS: RwLock<Vec<CString>> =
|
||||
RwLock::new(LIBOS_CONFIG.env.default.clone());
|
||||
}
|
||||
|
||||
pub fn load_config(config_path: &str, expected_mac: &sgx_aes_gcm_128bit_tag_t) -> Result<Config> {
|
||||
let mut config_file = {
|
||||
let config_file = SgxFile::open_integrity_only(config_path).map_err(|e| errno!(e))?;
|
||||
|
@ -390,8 +390,10 @@ fn merge_env(env: *const *const c_char) -> Result<Vec<CString>> {
|
||||
helper: HashMap::new(),
|
||||
};
|
||||
|
||||
let config_env_trusted = crate::config::TRUSTED_ENVS.read().unwrap();
|
||||
|
||||
// Use inner struct to parse env default
|
||||
for (idx, val) in config::LIBOS_CONFIG.env.default.iter().enumerate() {
|
||||
for (idx, val) in config_env_trusted.iter().enumerate() {
|
||||
env_default.content.push(CString::new(val.clone())?);
|
||||
let kv: Vec<&str> = val.to_str().unwrap().splitn(2, '=').collect(); // only split the first "="
|
||||
env_default.helper.insert(kv[0].to_string(), idx);
|
||||
|
@ -4,6 +4,7 @@ use super::procfs::ProcFS;
|
||||
use super::sefs::{SgxStorage, SgxUuidProvider};
|
||||
use super::*;
|
||||
use config::{ConfigApp, ConfigMountFsType};
|
||||
use std::mem::size_of;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::untrusted::path::PathEx;
|
||||
|
||||
@ -270,11 +271,20 @@ fn open_or_create_sefs_according_to(
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct user_rootfs_config {
|
||||
// length of the struct
|
||||
len: usize,
|
||||
// UnionFS type rootfs upper layer, read-write layer
|
||||
upper_layer_path: *const i8,
|
||||
// UnionFS type rootfs lower layer, read-only layer
|
||||
lower_layer_path: *const i8,
|
||||
entry_point: *const i8,
|
||||
// HostFS source path
|
||||
hostfs_source: *const i8,
|
||||
// HostFS target path, default value is "/host"
|
||||
hostfs_target: *const i8,
|
||||
// An array of pointers to null-terminated strings
|
||||
// and must be terminated by a null pointer
|
||||
envp: *const *const i8,
|
||||
}
|
||||
|
||||
impl user_rootfs_config {
|
||||
@ -298,7 +308,45 @@ fn to_option_pathbuf(path: *const i8) -> Result<Option<PathBuf>> {
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
fn combine_trusted_envs(envp: *const *const i8) -> Result<()> {
|
||||
let mut user_envs = from_user::clone_cstrings_safely(envp)?;
|
||||
trace!("User envs: {:?}", user_envs);
|
||||
let env_key: Vec<&str> = user_envs
|
||||
.iter()
|
||||
.map(|x| {
|
||||
let kv: Vec<&str> = x.to_str().unwrap().splitn(2, '=').collect();
|
||||
kv[0]
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut merged = config::TRUSTED_ENVS.write().unwrap();
|
||||
// First clear the default envs then do the merge again
|
||||
merged.clear();
|
||||
merged.extend_from_slice(&user_envs);
|
||||
|
||||
for (_idx, val) in config::LIBOS_CONFIG.env.default.iter().enumerate() {
|
||||
let kv: Vec<&str> = val.to_str().unwrap().splitn(2, '=').collect(); // only split the first "="
|
||||
info!("kv: {:?}", kv);
|
||||
if !env_key.contains(&kv[0]) {
|
||||
unsafe { merged.push(val.clone()) };
|
||||
}
|
||||
}
|
||||
|
||||
// trace!("Combined trusted envs: {:?}", merged);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn gen_config_app(config: &user_rootfs_config) -> Result<ConfigApp> {
|
||||
// Check config struct length for future possible extension
|
||||
if config.len != size_of::<user_rootfs_config>() {
|
||||
return_errno!(EINVAL, "User Config Struct length not match");
|
||||
}
|
||||
|
||||
// Combine the default envs and user envs if necessary
|
||||
if !config.envp.is_null() {
|
||||
combine_trusted_envs(config.envp)?;
|
||||
}
|
||||
|
||||
let upper_layer = to_option_pathbuf(config.upper_layer_path)?;
|
||||
let lower_layer = to_option_pathbuf(config.lower_layer_path)?;
|
||||
let entry_point = to_option_pathbuf(config.entry_point)?;
|
||||
|
Loading…
Reference in New Issue
Block a user