Combine two config json files as one
This commit is contained in:
parent
0fef286df2
commit
2347951743
@ -39,14 +39,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
const IMAGE_CONFIG_FILE: &str = "/etc/image_config.json";
|
||||
let image_config = load_config(IMAGE_CONFIG_FILE)?;
|
||||
|
||||
// Get the MAC of Occlum.json.protected file
|
||||
let occlum_json_mac = {
|
||||
let mut mac: sgx_aes_gcm_128bit_tag_t = Default::default();
|
||||
parse_str_to_bytes(&image_config.occlum_json_mac, &mut mac)?;
|
||||
mac
|
||||
};
|
||||
let occlum_json_mac_ptr = &occlum_json_mac as *const sgx_aes_gcm_128bit_tag_t;
|
||||
|
||||
// Get client secrets through grpc-ratls
|
||||
let server_addr = CString::new("localhost:50051").unwrap();
|
||||
let config_json = CString::new("dynamic_config.json").unwrap();
|
||||
@ -136,7 +128,10 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
// Mount the image
|
||||
const SYS_MOUNT_FS: i64 = 363;
|
||||
let ret = unsafe { syscall(SYS_MOUNT_FS, key_ptr, occlum_json_mac_ptr) };
|
||||
// User can provide valid path for runtime mount and boot
|
||||
// Otherwise, just pass null pointer to do general mount and boot
|
||||
let root_config_path: *const i8 = std::ptr::null();
|
||||
let ret = unsafe { syscall(SYS_MOUNT_FS, key_ptr, root_config_path) };
|
||||
if ret < 0 {
|
||||
return Err(Box::new(std::io::Error::last_os_error()));
|
||||
}
|
||||
@ -150,13 +145,10 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type sgx_key_128bit_t = [u8; 16];
|
||||
#[allow(non_camel_case_types)]
|
||||
type sgx_aes_gcm_128bit_tag_t = [u8; 16];
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct ImageConfig {
|
||||
occlum_json_mac: String,
|
||||
image_type: String,
|
||||
}
|
||||
|
||||
|
@ -62,14 +62,6 @@
|
||||
"target": "/host",
|
||||
"type": "hostfs",
|
||||
"source": "."
|
||||
},
|
||||
{
|
||||
"target": "/proc",
|
||||
"type": "procfs"
|
||||
},
|
||||
{
|
||||
"target": "/dev",
|
||||
"type": "devfs"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -29,14 +29,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
const IMAGE_CONFIG_FILE: &str = "/etc/image_config.json";
|
||||
let image_config = load_config(IMAGE_CONFIG_FILE)?;
|
||||
|
||||
// Get the MAC of Occlum.json.protected file
|
||||
let occlum_json_mac = {
|
||||
let mut mac: sgx_aes_gcm_128bit_tag_t = Default::default();
|
||||
parse_str_to_bytes(&image_config.occlum_json_mac, &mut mac)?;
|
||||
mac
|
||||
};
|
||||
let occlum_json_mac_ptr = &occlum_json_mac as *const sgx_aes_gcm_128bit_tag_t;
|
||||
|
||||
// Get grpc server address from environment GRPC_SERVER
|
||||
let server_addr = CString::new(
|
||||
env::var("GRPC_SERVER").unwrap_or("localhost:50051".to_string()))
|
||||
@ -99,7 +91,10 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
// Mount the image
|
||||
const SYS_MOUNT_FS: i64 = 363;
|
||||
let ret = unsafe { syscall(SYS_MOUNT_FS, key_ptr, occlum_json_mac_ptr) };
|
||||
// User can provide valid path for runtime mount and boot
|
||||
// Otherwise, just pass null pointer to do general mount and boot
|
||||
let root_config_path: *const i8 = std::ptr::null();
|
||||
let ret = unsafe { syscall(SYS_MOUNT_FS, key_ptr, root_config_path) };
|
||||
if ret < 0 {
|
||||
return Err(Box::new(std::io::Error::last_os_error()));
|
||||
}
|
||||
@ -112,13 +107,10 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type sgx_key_128bit_t = [u8; 16];
|
||||
#[allow(non_camel_case_types)]
|
||||
type sgx_aes_gcm_128bit_tag_t = [u8; 16];
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct ImageConfig {
|
||||
occlum_json_mac: String,
|
||||
image_type: String,
|
||||
}
|
||||
|
||||
|
@ -94,8 +94,7 @@ pub struct Config {
|
||||
pub resource_limits: ConfigResourceLimits,
|
||||
pub process: ConfigProcess,
|
||||
pub env: ConfigEnv,
|
||||
pub entry_points: Vec<PathBuf>,
|
||||
pub mount: Vec<ConfigMount>,
|
||||
pub app: Vec<ConfigApp>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -116,7 +115,7 @@ pub struct ConfigEnv {
|
||||
pub untrusted: HashSet<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ConfigMount {
|
||||
pub type_: ConfigMountFsType,
|
||||
pub target: PathBuf,
|
||||
@ -124,7 +123,14 @@ pub struct ConfigMount {
|
||||
pub options: ConfigMountOptions,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ConfigApp {
|
||||
pub entry_points: Vec<PathBuf>,
|
||||
pub stage: String,
|
||||
pub mount: Vec<ConfigMount>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum ConfigMountFsType {
|
||||
TYPE_SEFS,
|
||||
@ -154,12 +160,13 @@ impl ConfigMountFsType {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub struct ConfigMountOptions {
|
||||
pub mac: Option<sgx_aes_gcm_128bit_tag_t>,
|
||||
pub layers: Option<Vec<ConfigMount>>,
|
||||
pub temporary: bool,
|
||||
pub cache_size: Option<u64>,
|
||||
pub index: u32,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@ -167,32 +174,32 @@ impl Config {
|
||||
let resource_limits = ConfigResourceLimits::from_input(&input.resource_limits)?;
|
||||
let process = ConfigProcess::from_input(&input.process)?;
|
||||
let env = ConfigEnv::from_input(&input.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")
|
||||
|
||||
let app = {
|
||||
let mut app = Vec::new();
|
||||
for input_app in &input.app {
|
||||
app.push(ConfigApp::from_input(&input_app)?);
|
||||
}
|
||||
entry_points.push(ep_path);
|
||||
}
|
||||
entry_points
|
||||
};
|
||||
let mount = {
|
||||
let mut mount = Vec::new();
|
||||
for input_mount in &input.mount {
|
||||
mount.push(ConfigMount::from_input(&input_mount)?);
|
||||
}
|
||||
mount
|
||||
app
|
||||
};
|
||||
|
||||
Ok(Config {
|
||||
resource_limits,
|
||||
process,
|
||||
env,
|
||||
entry_points,
|
||||
mount,
|
||||
app,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_app_config(&self, stage: &str) -> Result<&ConfigApp> {
|
||||
let config_app = self
|
||||
.app
|
||||
.iter()
|
||||
.find(|m| m.stage.eq(stage))
|
||||
.ok_or_else(|| errno!(Errno::ENOENT, "No expected config app"))?;
|
||||
|
||||
Ok(config_app)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigResourceLimits {
|
||||
@ -224,6 +231,36 @@ impl ConfigEnv {
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigApp {
|
||||
fn from_input(input: &InputConfigApp) -> Result<ConfigApp> {
|
||||
let stage = input.stage.clone();
|
||||
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 {
|
||||
mount.push(ConfigMount::from_input(&input_mount)?);
|
||||
}
|
||||
mount
|
||||
};
|
||||
|
||||
Ok(ConfigApp {
|
||||
stage,
|
||||
entry_points,
|
||||
mount,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigMount {
|
||||
fn from_input(input: &InputConfigMount) -> Result<ConfigMount> {
|
||||
let type_ = ConfigMountFsType::from_input(input.type_.as_str())?;
|
||||
@ -277,6 +314,7 @@ impl ConfigMountOptions {
|
||||
layers,
|
||||
temporary: input.temporary,
|
||||
cache_size,
|
||||
index: input.index,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -316,9 +354,7 @@ struct InputConfig {
|
||||
#[serde(default)]
|
||||
pub env: InputConfigEnv,
|
||||
#[serde(default)]
|
||||
pub entry_points: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub mount: Vec<InputConfigMount>,
|
||||
pub app: Vec<InputConfigApp>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
@ -415,4 +451,17 @@ struct InputConfigMountOptions {
|
||||
pub temporary: bool,
|
||||
#[serde(default)]
|
||||
pub cache_size: Option<String>,
|
||||
#[serde(default)]
|
||||
pub index: u32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct InputConfigApp {
|
||||
#[serde(default)]
|
||||
pub stage: String,
|
||||
#[serde(default)]
|
||||
pub entry_points: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub mount: Vec<InputConfigMount>,
|
||||
}
|
||||
|
@ -24,8 +24,13 @@ static mut ENCLAVE_PATH: String = String::new();
|
||||
lazy_static! {
|
||||
static ref INIT_ONCE: Once = Once::new();
|
||||
static ref HAS_INIT: AtomicBool = AtomicBool::new(false);
|
||||
pub static ref ENTRY_POINTS: RwLock<Vec<PathBuf>> =
|
||||
RwLock::new(config::LIBOS_CONFIG.entry_points.clone());
|
||||
pub static ref ENTRY_POINTS: RwLock<Vec<PathBuf>> = RwLock::new(
|
||||
config::LIBOS_CONFIG
|
||||
.get_app_config("init")
|
||||
.unwrap()
|
||||
.entry_points
|
||||
.clone()
|
||||
);
|
||||
pub static ref RESOLV_CONF_STR: RwLock<Option<String>> = RwLock::new(None);
|
||||
pub static ref HOSTNAME_STR: RwLock<Option<String>> = RwLock::new(None);
|
||||
pub static ref HOSTS_STR: RwLock<Option<String>> = RwLock::new(None);
|
||||
|
@ -13,7 +13,7 @@ lazy_static! {
|
||||
}
|
||||
|
||||
pub fn do_mount_rootfs(
|
||||
user_config: &config::Config,
|
||||
user_app_config: &config::ConfigApp,
|
||||
user_key: &Option<sgx_key_128bit_t>,
|
||||
) -> Result<()> {
|
||||
debug!("mount rootfs");
|
||||
@ -21,13 +21,15 @@ pub fn do_mount_rootfs(
|
||||
if MOUNT_ONCE.is_completed() {
|
||||
return_errno!(EPERM, "rootfs cannot be mounted more than once");
|
||||
}
|
||||
let new_rootfs = open_root_fs_according_to(&user_config.mount, user_key)?;
|
||||
mount_nonroot_fs_according_to(&new_rootfs.root_inode(), &user_config.mount, user_key, true)?;
|
||||
|
||||
let mount_config = &user_app_config.mount;
|
||||
let new_rootfs = open_root_fs_according_to(mount_config, user_key)?;
|
||||
mount_nonroot_fs_according_to(&new_rootfs.root_inode(), mount_config, user_key, true)?;
|
||||
MOUNT_ONCE.call_once(|| {
|
||||
let mut rootfs = ROOT_FS.write().unwrap();
|
||||
rootfs.sync().expect("failed to sync old rootfs");
|
||||
*rootfs = new_rootfs;
|
||||
*ENTRY_POINTS.write().unwrap() = user_config.entry_points.to_owned();
|
||||
*ENTRY_POINTS.write().unwrap() = user_app_config.entry_points.to_owned();
|
||||
});
|
||||
|
||||
// Write resolv.conf file into mounted file system
|
||||
|
@ -33,7 +33,7 @@ pub use self::locks::range_lock::{
|
||||
FileRange, RangeLock, RangeLockBuilder, RangeLockList, RangeLockType, OFFSET_MAX,
|
||||
};
|
||||
pub use self::pipe::PipeType;
|
||||
pub use self::rootfs::ROOT_FS;
|
||||
pub use self::rootfs::{gen_config_app, user_rootfs_config, ROOT_FS};
|
||||
pub use self::stdio::{HostStdioFds, StdinFile, StdoutFile};
|
||||
pub use self::syscalls::*;
|
||||
pub use self::timer_file::{AsTimer, TimerCreationFlags, TimerFile};
|
||||
|
@ -3,7 +3,7 @@ use super::hostfs::HostFS;
|
||||
use super::procfs::ProcFS;
|
||||
use super::sefs::{SgxStorage, SgxUuidProvider};
|
||||
use super::*;
|
||||
use config::ConfigMountFsType;
|
||||
use config::{ConfigApp, ConfigMountFsType};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::untrusted::path::PathEx;
|
||||
|
||||
@ -13,11 +13,13 @@ use rcore_fs_sefs::dev::*;
|
||||
use rcore_fs_sefs::SEFS;
|
||||
use rcore_fs_unionfs::UnionFS;
|
||||
|
||||
use util::mem_util::from_user;
|
||||
|
||||
lazy_static! {
|
||||
/// The root of file system
|
||||
pub static ref ROOT_FS: RwLock<Arc<dyn FileSystem>> = {
|
||||
fn init_root_fs() -> Result<Arc<dyn FileSystem>> {
|
||||
let mount_config = &config::LIBOS_CONFIG.mount;
|
||||
let mount_config = &config::LIBOS_CONFIG.get_app_config("init").unwrap().mount;
|
||||
let rootfs = open_root_fs_according_to(mount_config, &None)?;
|
||||
mount_nonroot_fs_according_to(&rootfs.root_inode(), mount_config, &None, true)?;
|
||||
Ok(rootfs)
|
||||
@ -49,7 +51,7 @@ pub fn open_root_fs_according_to(
|
||||
.find(|m| {
|
||||
m.target == Path::new("/")
|
||||
&& m.type_ == ConfigMountFsType::TYPE_SEFS
|
||||
&& m.options.mac.is_some()
|
||||
&& (m.options.mac.is_some() || m.options.index == 1)
|
||||
})
|
||||
.ok_or_else(|| errno!(Errno::ENOENT, "the image SEFS in layers is not valid"))?;
|
||||
let root_image_sefs =
|
||||
@ -61,6 +63,7 @@ pub fn open_root_fs_according_to(
|
||||
m.target == Path::new("/")
|
||||
&& m.type_ == ConfigMountFsType::TYPE_SEFS
|
||||
&& m.options.mac.is_none()
|
||||
&& m.options.index == 0
|
||||
})
|
||||
.ok_or_else(|| errno!(Errno::ENOENT, "the container SEFS in layers is not valid"))?;
|
||||
let root_container_sefs =
|
||||
@ -262,3 +265,109 @@ fn open_or_create_sefs_according_to(
|
||||
};
|
||||
Ok(sefs)
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct user_rootfs_config {
|
||||
upper_layer_path: *const i8,
|
||||
lower_layer_path: *const i8,
|
||||
entry_point: *const i8,
|
||||
hostfs_source: *const i8,
|
||||
hostfs_target: *const i8,
|
||||
}
|
||||
|
||||
impl user_rootfs_config {
|
||||
pub fn from_raw_ptr(ptr: *const user_rootfs_config) -> Result<user_rootfs_config> {
|
||||
let config = unsafe { *ptr };
|
||||
Ok(config)
|
||||
}
|
||||
}
|
||||
|
||||
fn to_option_pathbuf(path: *const i8) -> Result<Option<PathBuf>> {
|
||||
let path = if path.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(PathBuf::from(
|
||||
from_user::clone_cstring_safely(path)?
|
||||
.to_string_lossy()
|
||||
.into_owned(),
|
||||
))
|
||||
};
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
pub fn gen_config_app(config: &user_rootfs_config) -> Result<ConfigApp> {
|
||||
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)?;
|
||||
let hostfs_source = to_option_pathbuf(config.hostfs_source)?;
|
||||
|
||||
let hostfs_target = if config.hostfs_target.is_null() {
|
||||
PathBuf::from("/host")
|
||||
} else {
|
||||
PathBuf::from(
|
||||
from_user::clone_cstring_safely(config.hostfs_target)?
|
||||
.to_string_lossy()
|
||||
.into_owned(),
|
||||
)
|
||||
};
|
||||
|
||||
let mut config_app = config::LIBOS_CONFIG.get_app_config("app").unwrap().clone();
|
||||
let root_mount_config = config_app
|
||||
.mount
|
||||
.iter_mut()
|
||||
.find(|m| m.target == Path::new("/") && m.type_ == ConfigMountFsType::TYPE_UNIONFS)
|
||||
.ok_or_else(|| errno!(Errno::ENOENT, "the root UnionFS is not valid"))?;
|
||||
|
||||
if upper_layer.is_some() {
|
||||
let layer_mount_configs = root_mount_config.options.layers.as_mut().unwrap();
|
||||
// image SEFS in layers
|
||||
let root_image_sefs_mount_config = layer_mount_configs
|
||||
.iter_mut()
|
||||
.find(|m| {
|
||||
m.target == Path::new("/")
|
||||
&& m.type_ == ConfigMountFsType::TYPE_SEFS
|
||||
&& (m.options.mac.is_some() || m.options.index == 1)
|
||||
})
|
||||
.ok_or_else(|| errno!(Errno::ENOENT, "the image SEFS in layers is not valid"))?;
|
||||
|
||||
root_image_sefs_mount_config.source = upper_layer;
|
||||
root_image_sefs_mount_config.options.mac = None;
|
||||
root_image_sefs_mount_config.options.index = 1;
|
||||
}
|
||||
|
||||
if lower_layer.is_some() {
|
||||
let layer_mount_configs = root_mount_config.options.layers.as_mut().unwrap();
|
||||
// container SEFS in layers
|
||||
let root_container_sefs_mount_config = layer_mount_configs
|
||||
.iter_mut()
|
||||
.find(|m| {
|
||||
m.target == Path::new("/")
|
||||
&& m.type_ == ConfigMountFsType::TYPE_SEFS
|
||||
&& m.options.mac.is_none()
|
||||
&& m.options.index == 0
|
||||
})
|
||||
.ok_or_else(|| errno!(Errno::ENOENT, "the container SEFS in layers is not valid"))?;
|
||||
|
||||
root_container_sefs_mount_config.source = lower_layer;
|
||||
}
|
||||
|
||||
if entry_point.is_some() {
|
||||
config_app.entry_points.clear();
|
||||
config_app.entry_points.push(entry_point.unwrap())
|
||||
}
|
||||
|
||||
if hostfs_source.is_some() {
|
||||
let hostfs_mount_config = config_app
|
||||
.mount
|
||||
.iter_mut()
|
||||
.find(|m| m.type_ == ConfigMountFsType::TYPE_HOSTFS)
|
||||
.ok_or_else(|| errno!(Errno::ENOENT, "the HostFS is not valid"))?;
|
||||
hostfs_mount_config.source = hostfs_source;
|
||||
hostfs_mount_config.target = hostfs_target;
|
||||
}
|
||||
|
||||
Ok(config_app)
|
||||
}
|
||||
|
@ -660,20 +660,26 @@ pub fn do_ioctl(fd: FileDesc, cmd: u32, argp: *mut u8) -> Result<isize> {
|
||||
|
||||
pub fn do_mount_rootfs(
|
||||
key_ptr: *const sgx_key_128bit_t,
|
||||
occlum_json_mac_ptr: *const sgx_aes_gcm_128bit_tag_t,
|
||||
rootfs_config: *const user_rootfs_config,
|
||||
) -> Result<isize> {
|
||||
let key = if key_ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { key_ptr.read() })
|
||||
};
|
||||
if occlum_json_mac_ptr.is_null() {
|
||||
return_errno!(EINVAL, "occlum_json_mac_ptr cannot be null");
|
||||
|
||||
// If user provided valid parameters, do runtime mount and boot
|
||||
// Otherwise, do general mount and boot
|
||||
if !rootfs_config.is_null() {
|
||||
from_user::check_ptr(rootfs_config)?;
|
||||
let rootfs_config = user_rootfs_config::from_raw_ptr(rootfs_config)?;
|
||||
let app_config = gen_config_app(&rootfs_config)?;
|
||||
debug!("user provided app config: {:?}", app_config);
|
||||
fs_ops::do_mount_rootfs(&app_config, &key)?;
|
||||
} else {
|
||||
fs_ops::do_mount_rootfs(&config::LIBOS_CONFIG.get_app_config("app").unwrap(), &key)?;
|
||||
}
|
||||
let expected_occlum_json_mac = unsafe { occlum_json_mac_ptr.read() };
|
||||
let user_config_path = unsafe { format!("{}{}", INSTANCE_DIR, "/build/Occlum.json.protected") };
|
||||
let user_config = config::load_config(&user_config_path, &expected_occlum_json_mac)?;
|
||||
fs_ops::do_mount_rootfs(&user_config, &key)?;
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,8 @@ use crate::fs::{
|
||||
do_pwritev, do_read, do_readlink, do_readlinkat, do_readv, do_rename, do_renameat, do_rmdir,
|
||||
do_sendfile, do_stat, do_statfs, do_symlink, do_symlinkat, do_sync, do_timerfd_create,
|
||||
do_timerfd_gettime, do_timerfd_settime, do_truncate, do_umask, do_umount, do_unlink,
|
||||
do_unlinkat, do_utime, do_utimensat, do_utimes, do_write, do_writev, iovec_t, utimbuf_t,
|
||||
AsTimer, File, FileDesc, FileRef, HostStdioFds, Stat, Statfs,
|
||||
do_unlinkat, do_utime, do_utimensat, do_utimes, do_write, do_writev, iovec_t,
|
||||
user_rootfs_config, utimbuf_t, AsTimer, File, FileDesc, FileRef, HostStdioFds, Stat, Statfs,
|
||||
};
|
||||
use crate::interrupt::{do_handle_interrupt, sgx_interrupt_info_t};
|
||||
use crate::ipc::{do_shmat, do_shmctl, do_shmdt, do_shmget, key_t, shmids_t};
|
||||
@ -425,7 +425,7 @@ macro_rules! process_syscall_table_with_callback {
|
||||
(SpawnMusl = 360) => do_spawn_for_musl(child_pid_ptr: *mut u32, path: *const i8, argv: *const *const i8, envp: *const *const i8, fdop_list: *const FdOp, attribute_list: *const posix_spawnattr_t),
|
||||
(HandleException = 361) => do_handle_exception(info: *mut sgx_exception_info_t, fpregs: *mut FpRegs, context: *mut CpuContext),
|
||||
(HandleInterrupt = 362) => do_handle_interrupt(info: *mut sgx_interrupt_info_t, fpregs: *mut FpRegs, context: *mut CpuContext),
|
||||
(MountRootFS = 363) => do_mount_rootfs(key_ptr: *const sgx_key_128bit_t, occlum_json_mac_ptr: *const sgx_aes_gcm_128bit_tag_t),
|
||||
(MountRootFS = 363) => do_mount_rootfs(key_ptr: *const sgx_key_128bit_t, rootfs_config: *const user_rootfs_config),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -67,8 +67,8 @@ fn main() {
|
||||
.takes_value(true),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("gen_user_conf")
|
||||
.about("Generate user image config")
|
||||
SubCommand::with_name("gen_conf")
|
||||
.about("Generate image config")
|
||||
// Input: User's Secure Occlum FS image MAC
|
||||
.arg(
|
||||
Arg::with_name("user_fs_mac")
|
||||
@ -77,11 +77,19 @@ fn main() {
|
||||
.required(true)
|
||||
.takes_value(true),
|
||||
)
|
||||
// Input: InitFS image MAC
|
||||
.arg(
|
||||
Arg::with_name("init_fs_mac")
|
||||
.long("init_fs_mac")
|
||||
.value_name("input MAC of init image fs")
|
||||
.required(true)
|
||||
.takes_value(true),
|
||||
)
|
||||
// Output: JSON file used by libOS and users shouldn't touch
|
||||
.arg(
|
||||
Arg::with_name("output_user_json")
|
||||
.long("output_user_json")
|
||||
.value_name("output user json")
|
||||
Arg::with_name("output_json")
|
||||
.long("output_json")
|
||||
.value_name("output json")
|
||||
.required(true)
|
||||
.validator(|f| match File::create(f) {
|
||||
Ok(_) => Ok(()),
|
||||
@ -102,30 +110,6 @@ fn main() {
|
||||
.takes_value(true),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("gen_sys_conf")
|
||||
.about("Generate initfs image config")
|
||||
// Input: InitFS image MAC
|
||||
.arg(
|
||||
Arg::with_name("init_fs_mac")
|
||||
.long("init_fs_mac")
|
||||
.value_name("input MAC of init image fs")
|
||||
.required(true)
|
||||
.takes_value(true),
|
||||
)
|
||||
// Output: JSON file for initfs 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();
|
||||
@ -141,14 +125,17 @@ fn main() {
|
||||
debug!("The occlum config is:{:?}", occlum_config);
|
||||
|
||||
// Match subcommand
|
||||
if let Some(sub_matches) = matches.subcommand_matches("gen_user_conf") {
|
||||
if let Some(sub_matches) = matches.subcommand_matches("gen_conf") {
|
||||
let occlum_conf_user_fs_mac = sub_matches.value_of("user_fs_mac").unwrap();
|
||||
debug!("Occlum config user FS MAC {:?}", occlum_conf_user_fs_mac);
|
||||
|
||||
let occlum_user_json_file_path = sub_matches.value_of("output_user_json").unwrap();
|
||||
let occlum_conf_init_fs_mac = sub_matches.value_of("init_fs_mac").unwrap();
|
||||
debug!("Occlum config init FS MAC {:?}", occlum_conf_init_fs_mac);
|
||||
|
||||
let occlum_json_file_path = sub_matches.value_of("output_json").unwrap();
|
||||
debug!(
|
||||
"Generated Occlum user config (json) file name {:?}",
|
||||
occlum_user_json_file_path
|
||||
"Genereated Occlum user config (json) file name {:?}",
|
||||
occlum_json_file_path
|
||||
);
|
||||
|
||||
let enclave_config_file_path = sub_matches.value_of("sdk_xml").unwrap();
|
||||
@ -273,17 +260,23 @@ fn main() {
|
||||
let enclave_config = serde_xml_rs::to_string(&sgx_enclave_configuration).unwrap();
|
||||
debug!("The enclave config:{:?}", enclave_config);
|
||||
|
||||
// Generate user Occlum.json - "output_user_json"
|
||||
let user_mount_config = {
|
||||
let user_mount_config =
|
||||
gen_user_mount_config(occlum_config.mount, occlum_conf_user_fs_mac.to_string());
|
||||
if user_mount_config.is_err() {
|
||||
println!("Mount configuration invalid: {:?}", user_mount_config);
|
||||
// Generate app config, including "init" and user app
|
||||
let app_config = {
|
||||
let app_config =
|
||||
gen_app_config(
|
||||
occlum_config.entry_points,
|
||||
occlum_config.mount,
|
||||
occlum_conf_user_fs_mac.to_string(),
|
||||
occlum_conf_init_fs_mac.to_string(),
|
||||
);
|
||||
if app_config.is_err() {
|
||||
println!("Mount configuration invalid: {:?}", app_config);
|
||||
return;
|
||||
}
|
||||
user_mount_config.unwrap()
|
||||
app_config.unwrap()
|
||||
};
|
||||
let user_occlum_json_config = InternalOcclumJson {
|
||||
|
||||
let occlum_json_config = InternalOcclumJson {
|
||||
resource_limits: InternalResourceLimits {
|
||||
user_space_size: occlum_config.resource_limits.user_space_size.to_string(),
|
||||
},
|
||||
@ -292,12 +285,12 @@ fn main() {
|
||||
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: serde_json::to_value(user_mount_config).unwrap(),
|
||||
app: app_config,
|
||||
};
|
||||
let user_occlum_json_str = serde_json::to_string_pretty(&user_occlum_json_config).unwrap();
|
||||
debug!("The user Occlum.json config:\n{:?}", user_occlum_json_str);
|
||||
|
||||
let occlum_json_str = serde_json::to_string_pretty(&occlum_json_config).unwrap();
|
||||
debug!("The Occlum.json config:\n{:?}", occlum_json_str);
|
||||
|
||||
// Update the output file
|
||||
let mut enclave_config_file = File::create(enclave_config_file_path)
|
||||
@ -306,44 +299,11 @@ fn main() {
|
||||
.write_all(enclave_config.as_bytes())
|
||||
.expect("Failed to update the Enclave configuration file.");
|
||||
|
||||
let mut user_occlum_json = File::create(occlum_user_json_file_path)
|
||||
.expect("Could not open the output user Occlum.json file.");
|
||||
user_occlum_json
|
||||
.write_all(user_occlum_json_str.as_bytes())
|
||||
.expect("Failed to update the output user Occlum.json file.");
|
||||
} else if let Some(sub_matches) = matches.subcommand_matches("gen_sys_conf") {
|
||||
let occlum_conf_init_fs_mac = sub_matches.value_of("init_fs_mac").unwrap();
|
||||
debug!("Occlum config init FS MAC {:?}", occlum_conf_init_fs_mac);
|
||||
|
||||
let occlum_sys_json_file_path = sub_matches.value_of("sys_json").unwrap();
|
||||
debug!(
|
||||
"Generated Occlum sys config (json) file name {:?}",
|
||||
occlum_sys_json_file_path
|
||||
);
|
||||
|
||||
// Generate sys Occlum.json - "sys_json"
|
||||
let sys_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: json!(["/bin"]),
|
||||
env: occlum_config.env,
|
||||
mount: gen_sys_mount_config(occlum_conf_init_fs_mac.to_string()),
|
||||
};
|
||||
|
||||
// Update the output file
|
||||
let sys_occlum_json_str = serde_json::to_string_pretty(&sys_occlum_json_config).unwrap();
|
||||
debug!("The sys Occlum.json config:\n{:?}", sys_occlum_json_str);
|
||||
let mut sys_occlum_json = File::create(occlum_sys_json_file_path)
|
||||
.expect("Could not open the output sys Occlum.json file.");
|
||||
sys_occlum_json
|
||||
.write_all(sys_occlum_json_str.as_bytes())
|
||||
.expect("Failed to update the output sys Occlum.json file.");
|
||||
let mut occlum_json = File::create(occlum_json_file_path)
|
||||
.expect("Could not open the output Occlum.json file.");
|
||||
occlum_json
|
||||
.write_all(occlum_json_str.as_bytes())
|
||||
.expect("Failed to update the output Occlum.json file.");
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
@ -402,38 +362,19 @@ fn parse_kss_conf(occlum_config: &OcclumConfiguration) -> (u32, u64, u64, u64, u
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_user_mount_config(
|
||||
fn gen_app_config(
|
||||
entry_points: serde_json::Value,
|
||||
mount_conf: Vec<OcclumMount>,
|
||||
occlum_conf_user_fs_mac: String,
|
||||
) -> Result<Vec<OcclumMount>, &'static str> {
|
||||
let mut user_mount_config = mount_conf;
|
||||
let root_mc = user_mount_config
|
||||
.iter_mut()
|
||||
.find(|m| m.target == String::from("/") && m.type_ == String::from("unionfs"))
|
||||
.ok_or("the root UnionFS is not valid")?;
|
||||
if root_mc.options.layers.is_none() {
|
||||
return Err("the root UnionFS must be given layers");
|
||||
}
|
||||
let mut root_image_sefs_mc = root_mc
|
||||
.options
|
||||
.layers
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.iter_mut()
|
||||
.find(|m| {
|
||||
m.target == String::from("/")
|
||||
&& m.type_ == String::from("sefs")
|
||||
&& m.options.mac.is_some()
|
||||
})
|
||||
.ok_or("the image SEFS in layers is not valid")?;
|
||||
root_image_sefs_mc.options.mac = Some(occlum_conf_user_fs_mac);
|
||||
|
||||
debug!("user Occlum.json mount config:\n{:?}", user_mount_config);
|
||||
Ok(user_mount_config)
|
||||
}
|
||||
|
||||
fn gen_sys_mount_config(occlum_conf_init_fs_mac: String) -> serde_json::Value {
|
||||
let mut init_fs_mount_config: serde_json::Value = json!({
|
||||
occlum_conf_init_fs_mac: String,
|
||||
) -> Result<serde_json::Value, &'static str> {
|
||||
let mut app_config: serde_json::Value = json!({
|
||||
"app": [
|
||||
{
|
||||
"stage": "init",
|
||||
"entry_points": [
|
||||
"/bin"
|
||||
],
|
||||
"mount": [
|
||||
{
|
||||
"target": "/",
|
||||
@ -465,15 +406,107 @@ fn gen_sys_mount_config(occlum_conf_init_fs_mac: String) -> serde_json::Value {
|
||||
"type": "devfs"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"stage": "app",
|
||||
"entry_points": [],
|
||||
"mount": [
|
||||
{
|
||||
"target": "/",
|
||||
"type": "unionfs",
|
||||
"options": {
|
||||
"layers": [
|
||||
{
|
||||
"target": "/",
|
||||
"type": "sefs",
|
||||
"source": "./build/mount/__ROOT",
|
||||
"options": {
|
||||
"MAC": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"target": "/",
|
||||
"type": "sefs",
|
||||
"source": "./run/mount/__ROOT"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"target": "/host",
|
||||
"type": "hostfs",
|
||||
"source": "."
|
||||
},
|
||||
{
|
||||
"target": "/proc",
|
||||
"type": "procfs"
|
||||
},
|
||||
{
|
||||
"target": "/dev",
|
||||
"type": "devfs"
|
||||
}
|
||||
]
|
||||
}]
|
||||
});
|
||||
|
||||
*init_fs_mount_config
|
||||
.pointer_mut("/mount/0/options/layers/0/options/MAC")
|
||||
// Update init root mount fs MAC
|
||||
*app_config
|
||||
.pointer_mut("/app/0/mount/0/options/layers/0/options/MAC")
|
||||
.unwrap() = serde_json::Value::String(occlum_conf_init_fs_mac);
|
||||
|
||||
debug!("initfs mount config:\n{:?}", init_fs_mount_config);
|
||||
// Update app entry points
|
||||
*app_config
|
||||
.pointer_mut("/app/1/entry_points")
|
||||
.unwrap() = entry_points;
|
||||
|
||||
init_fs_mount_config["mount"].to_owned()
|
||||
let mut mount_config = mount_conf;
|
||||
if let Some(root_mc) = mount_config
|
||||
.iter_mut()
|
||||
.find(|m| {
|
||||
m.target == String::from("/")
|
||||
&& m.type_ == String::from("unionfs")
|
||||
}) {
|
||||
debug!("User provides Root mount config:\n{:?}", root_mc);
|
||||
root_mc
|
||||
.options
|
||||
.layers
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.iter_mut()
|
||||
.find(|m| {
|
||||
m.target == String::from("/")
|
||||
&& m.type_ == String::from("sefs")
|
||||
&& m.options.mac.is_some()
|
||||
})
|
||||
.ok_or("the image SEFS in layers is not valid")?;
|
||||
|
||||
// Update app root mount
|
||||
*app_config
|
||||
.pointer_mut("/app/1/mount/0")
|
||||
.unwrap() = serde_json::to_value(root_mc).unwrap();
|
||||
}
|
||||
|
||||
// Update app root mount fs MAC
|
||||
*app_config
|
||||
.pointer_mut("/app/1/mount/0/options/layers/0/options/MAC")
|
||||
.unwrap() = serde_json::Value::String(occlum_conf_user_fs_mac);
|
||||
|
||||
// Update host mount
|
||||
if let Some(host_mc) = mount_config
|
||||
.iter_mut()
|
||||
.find(|m| {
|
||||
m.type_ == String::from("hostfs")
|
||||
}) {
|
||||
debug!("User provides host mount config:\n{:?}", host_mc);
|
||||
// Update app root mount
|
||||
*app_config
|
||||
.pointer_mut("/app/1/mount/1")
|
||||
.unwrap() = serde_json::to_value(host_mc).unwrap();
|
||||
}
|
||||
|
||||
debug!("Occlum.json mount config:\n{:?}", app_config);
|
||||
|
||||
Ok(app_config["app"].to_owned())
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
@ -598,7 +631,6 @@ struct InternalResourceLimits {
|
||||
struct InternalOcclumJson {
|
||||
resource_limits: InternalResourceLimits,
|
||||
process: OcclumProcess,
|
||||
entry_points: serde_json::Value,
|
||||
env: serde_json::Value,
|
||||
mount: serde_json::Value,
|
||||
app: serde_json::Value,
|
||||
}
|
||||
|
@ -14,14 +14,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
const IMAGE_CONFIG_FILE: &str = "/etc/image_config.json";
|
||||
let image_config = load_config(IMAGE_CONFIG_FILE)?;
|
||||
|
||||
// Get the MAC of Occlum.json.protected file
|
||||
let occlum_json_mac = {
|
||||
let mut mac: sgx_aes_gcm_128bit_tag_t = Default::default();
|
||||
parse_str_to_bytes(&image_config.occlum_json_mac, &mut mac)?;
|
||||
mac
|
||||
};
|
||||
let occlum_json_mac_ptr = &occlum_json_mac as *const sgx_aes_gcm_128bit_tag_t;
|
||||
|
||||
// Get the key of FS image if needed
|
||||
let key = match &image_config.image_type[..] {
|
||||
"encrypted" => {
|
||||
@ -42,7 +34,11 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
// Mount the image
|
||||
const SYS_MOUNT_FS: i64 = 363;
|
||||
let ret = unsafe { syscall(SYS_MOUNT_FS, key_ptr, occlum_json_mac_ptr) };
|
||||
// User can provide valid path for runtime mount and boot
|
||||
// Otherwise, just pass null pointer to do general mount and boot
|
||||
let root_config_path: *const i8 = std::ptr::null();
|
||||
let ret = unsafe { syscall(
|
||||
SYS_MOUNT_FS, key_ptr, root_config_path) };
|
||||
if ret < 0 {
|
||||
return Err(Box::new(std::io::Error::last_os_error()));
|
||||
}
|
||||
@ -52,13 +48,10 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type sgx_key_128bit_t = [u8; 16];
|
||||
#[allow(non_camel_case_types)]
|
||||
type sgx_aes_gcm_128bit_tag_t = [u8; 16];
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct ImageConfig {
|
||||
occlum_json_mac: String,
|
||||
image_type: String,
|
||||
}
|
||||
|
||||
|
@ -510,8 +510,8 @@ cmd_package() {
|
||||
$instance_base_name/build/bin \
|
||||
$instance_base_name/build/lib/libocclum-libos.signed.so \
|
||||
$instance_base_name/build/lib/libocclum-pal.so* \
|
||||
$instance_base_name/build/mount $instance_base_name/build/Occlum.json.protected \
|
||||
$instance_base_name/build/initfs $instance_base_name/build/.Occlum_sys.json.protected \
|
||||
$instance_base_name/build/initfs $instance_base_name/build/mount \
|
||||
$instance_base_name/build/.Occlum_sys.json.protected \
|
||||
$instance_base_name/initfs $instance_base_name/run \
|
||||
$instance_base_name/.__occlum_status $instance_base_name/.sgx_mode \
|
||||
"
|
||||
|
@ -68,9 +68,11 @@ $(instance_dir)/build/.Occlum_sys.json.protected: $(instance_dir)/build/.Occlum_
|
||||
@cd "$(instance_dir)/build" ; \
|
||||
LD_LIBRARY_PATH="$(SGX_SDK)/sdk_libs" "$(occlum_dir)/build/bin/occlum-protect-integrity" protect .Occlum_sys.json ;
|
||||
|
||||
$(instance_dir)/build/.Occlum_sys.json: $(INITFS_IMAGE) $(INITFS_IMAGE_MAC) $(JSON_CONF)
|
||||
@$(occlum_dir)/build/bin/gen_internal_conf --user_json "$(JSON_CONF)" gen_sys_conf \
|
||||
--init_fs_mac "`cat $(INITFS_IMAGE_MAC)`" --sys_json $(instance_dir)/build/.Occlum_sys.json
|
||||
$(instance_dir)/build/Enclave.xml:
|
||||
$(instance_dir)/build/.Occlum_sys.json: $(INITFS_IMAGE) $(INITFS_IMAGE_MAC) $(JSON_CONF) $(SECURE_IMAGE) $(SECURE_IMAGE_MAC)
|
||||
@$(occlum_dir)/build/bin/gen_internal_conf --user_json "$(JSON_CONF)" gen_conf \
|
||||
--user_fs_mac "`cat $(SECURE_IMAGE_MAC)`" --sdk_xml "$(instance_dir)/build/Enclave.xml" \
|
||||
--init_fs_mac "`cat $(INITFS_IMAGE_MAC)`" --output_json $(instance_dir)/build/.Occlum_sys.json
|
||||
|
||||
$(BIN_LINKS): $(instance_dir)/build/bin/%: $(occlum_dir)/build/bin/% | $(instance_dir)/build/bin
|
||||
@ln -sf $< $@
|
||||
@ -103,24 +105,11 @@ $(INITFS_IMAGE): $(INITFS) $(INITFS_DIRS) $(INITFS_FILES) $(IMAGE_CONFIG_JSON) $
|
||||
"$(instance_dir)/build/initfs/__ROOT" \
|
||||
"$(INITFS_IMAGE_MAC)"
|
||||
|
||||
$(IMAGE_CONFIG_JSON): $(instance_dir)/build/Occlum.json.protected
|
||||
@$(call get_occlum_file_mac, "$(instance_dir)/build/Occlum.json.protected", "$(CONF_TMP_MAC)") && \
|
||||
[ -n "$(SECURE_IMAGE_KEY)" ] && \
|
||||
jq -n --arg mac_val "`cat $(CONF_TMP_MAC)`" \
|
||||
'{image_type: "encrypted", occlum_json_mac: $$mac_val}' > $(IMAGE_CONFIG_JSON) || \
|
||||
jq -n --arg mac_val "`cat $(CONF_TMP_MAC)`" \
|
||||
'{image_type: "integrity-only", occlum_json_mac: $$mac_val}' > $(IMAGE_CONFIG_JSON)
|
||||
@rm -f "$(CONF_TMP_MAC)"
|
||||
|
||||
$(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) $(SECURE_IMAGE_MAC) $(JSON_CONF) | $(instance_dir)/build/lib
|
||||
@$(occlum_dir)/build/bin/gen_internal_conf --user_json "$(JSON_CONF)" gen_user_conf \
|
||||
--user_fs_mac "`cat $(SECURE_IMAGE_MAC)`" --sdk_xml "$(instance_dir)/build/Enclave.xml" \
|
||||
--output_user_json $(instance_dir)/build/Occlum.json
|
||||
$(IMAGE_CONFIG_JSON):
|
||||
@mkdir -p "$(instance_dir)/build/lib"
|
||||
@[ -n "$(SECURE_IMAGE_KEY)" ] && \
|
||||
jq -n '{image_type: "encrypted"}' > $(IMAGE_CONFIG_JSON) || \
|
||||
jq -n '{image_type: "integrity-only"}' > $(IMAGE_CONFIG_JSON)
|
||||
|
||||
# If image dir not exist, just use the secure Occlum FS image
|
||||
ifneq ($(wildcard $(IMAGE)/. ),)
|
||||
|
Loading…
Reference in New Issue
Block a user