Enable UnionFS

This commit is contained in:
LI Qing 2020-05-07 07:07:42 +00:00
parent 55eaae8810
commit 572873d9a4
14 changed files with 186 additions and 99 deletions

1
.gitmodules vendored

@ -9,6 +9,7 @@
[submodule "deps/sefs"]
path = deps/sefs
url = https://github.com/occlum/sefs.git
branch = unionfs
[submodule "deps/serde-sgx"]
path = deps/serde-sgx
url = https://github.com/occlum/serde-sgx

@ -35,10 +35,10 @@ submodule: githooks
@# Enclaves used by tools are running in simulation mode by default to run faster.
@rm -rf build build_sim
@$(MAKE) SGX_MODE=SIM --no-print-directory -C tools
@$(MAKE) --no-print-directory -C deps/sefs/sefs-fuse clean
@$(MAKE) SGX_MODE=SIM --no-print-directory -C deps/sefs/sefs-fuse
@cp deps/sefs/sefs-fuse/bin/sefs-fuse build/bin
@cp deps/sefs/sefs-fuse/lib/libsefs-fuse.signed.so build/lib
@$(MAKE) --no-print-directory -C deps/sefs/sefs-cli clean
@$(MAKE) SGX_MODE=SIM --no-print-directory -C deps/sefs/sefs-cli
@cp deps/sefs/sefs-cli/bin/sefs-cli build/bin
@cp deps/sefs/sefs-cli/lib/libsefs-cli.signed.so build/lib
src:
@$(MAKE) --no-print-directory -C src

@ -125,6 +125,11 @@ Occlum can be configured easily via a config file named `Occlum.json`, which is
// Limitation: configuring mount points by modifying this config file is not
// supported at the moment. The default configuration is shown below.
"mount": [
{
"target": "/",
"type": "unionfs",
"options": {
"layers": [
{
"target": "/",
"type": "sefs",
@ -134,8 +139,11 @@ Occlum can be configured easily via a config file named `Occlum.json`, which is
}
},
{
"target": "/root",
"target": "/",
"type": "sefs"
}
]
}
},
{
"target": "/host",

2
deps/sefs vendored

@ -1 +1 @@
Subproject commit 2420622f050efda627ccebcff6e86a71dcf405f5
Subproject commit fcb81443be49344e26fc1017534f1a6eec397d49

@ -27,6 +27,11 @@
"debuggable": true
},
"mount": [
{
"target": "/",
"type": "unionfs",
"options": {
"layers": [
{
"target": "/",
"type": "sefs",
@ -36,8 +41,11 @@
}
},
{
"target": "/root",
"target": "/",
"type": "sefs"
}
]
}
},
{
"target": "/host",

67
src/libos/Cargo.lock generated

@ -13,6 +13,7 @@ dependencies = [
"rcore-fs-mountfs",
"rcore-fs-ramfs",
"rcore-fs-sefs",
"rcore-fs-unionfs",
"ringbuf",
"serde",
"serde_json",
@ -54,9 +55,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.52"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d"
checksum = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518"
[[package]]
name = "cfg-if"
@ -141,9 +142,9 @@ checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
[[package]]
name = "fnv"
version = "1.0.6"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "fuchsia-cprng"
@ -182,15 +183,15 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.69"
version = "0.2.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005"
checksum = "bd7d4bd64732af4bf3a67f367c27df8520ad7e230c5817b8ff485864d80242b9"
[[package]]
name = "log"
version = "0.4.8"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
dependencies = [
"cfg-if",
]
@ -206,11 +207,11 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.12"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319"
checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12"
dependencies = [
"unicode-xid 0.2.0",
"unicode-xid 0.2.1",
]
[[package]]
@ -224,11 +225,11 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.4"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2 1.0.12",
"proc-macro2 1.0.19",
]
[[package]]
@ -354,7 +355,6 @@ dependencies = [
name = "rcore-fs-mountfs"
version = "0.1.0"
dependencies = [
"lazy_static",
"log",
"rcore-fs",
"spin",
@ -381,6 +381,15 @@ dependencies = [
"uuid",
]
[[package]]
name = "rcore-fs-unionfs"
version = "0.1.0"
dependencies = [
"log",
"rcore-fs",
"spin",
]
[[package]]
name = "rdrand"
version = "0.4.0"
@ -399,9 +408,9 @@ dependencies = [
[[package]]
name = "ryu"
version = "1.0.4"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "serde"
@ -415,9 +424,9 @@ dependencies = [
name = "serde_derive"
version = "1.0.104"
dependencies = [
"proc-macro2 1.0.12",
"quote 1.0.4",
"syn 1.0.19",
"proc-macro2 1.0.19",
"quote 1.0.7",
"syn 1.0.34",
]
[[package]]
@ -545,13 +554,13 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.19"
version = "1.0.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8e5aa70697bb26ee62214ae3288465ecec0000f05182f039b477001f08f5ae7"
checksum = "936cae2873c940d92e697597c5eee105fb570cd5689c695806f672883653349b"
dependencies = [
"proc-macro2 1.0.12",
"quote 1.0.4",
"unicode-xid 0.2.0",
"proc-macro2 1.0.19",
"quote 1.0.7",
"unicode-xid 0.2.1",
]
[[package]]
@ -562,9 +571,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
[[package]]
name = "unicode-xid"
version = "0.2.0"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "uuid"
@ -577,9 +586,9 @@ dependencies = [
[[package]]
name = "winapi"
version = "0.3.8"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",

@ -18,6 +18,7 @@ rcore-fs = { path = "../../deps/sefs/rcore-fs" }
rcore-fs-sefs = { path = "../../deps/sefs/rcore-fs-sefs" }
rcore-fs-ramfs = { path = "../../deps/sefs/rcore-fs-ramfs" }
rcore-fs-mountfs = { path = "../../deps/sefs/rcore-fs-mountfs" }
rcore-fs-unionfs = { path = "../../deps/sefs/rcore-fs-unionfs" }
serde = { path = "../../deps/serde-sgx/serde", features = ["derive"] }
serde_json = { path = "../../deps/serde-json-sgx" }

@ -123,12 +123,14 @@ pub enum ConfigMountFsType {
TYPE_SEFS,
TYPE_HOSTFS,
TYPE_RAMFS,
TYPE_UNIONFS,
}
#[derive(Debug)]
pub struct ConfigMountOptions {
pub integrity_only: bool,
pub mac: Option<sgx_aes_gcm_128bit_tag_t>,
pub layers: Option<Vec<ConfigMount>>,
}
impl Config {
@ -195,12 +197,13 @@ impl ConfigEnv {
impl ConfigMount {
fn from_input(input: &InputConfigMount) -> Result<ConfigMount> {
const ALL_FS_TYPES: [&str; 3] = ["sefs", "hostfs", "ramfs"];
const ALL_FS_TYPES: [&str; 4] = ["sefs", "hostfs", "ramfs", "unionfs"];
let type_ = match input.type_.as_str() {
"sefs" => ConfigMountFsType::TYPE_SEFS,
"hostfs" => ConfigMountFsType::TYPE_HOSTFS,
"ramfs" => ConfigMountFsType::TYPE_RAMFS,
"unionfs" => ConfigMountFsType::TYPE_UNIONFS,
_ => {
return_errno!(EINVAL, "Unsupported file system type");
}
@ -233,9 +236,19 @@ impl ConfigMountOptions {
}
(true, Some(parse_mac(&input.mac.as_ref().unwrap())?))
};
let layers = if let Some(layers) = &input.layers {
let layers = layers
.iter()
.map(|config| ConfigMount::from_input(config).expect("invalid mount config"))
.collect();
Some(layers)
} else {
None
};
Ok(ConfigMountOptions {
integrity_only,
mac,
layers,
})
}
}
@ -370,4 +383,6 @@ struct InputConfigMountOptions {
#[serde(rename = "MAC")]
#[serde(default)]
pub mac: Option<String>,
#[serde(default)]
pub layers: Option<Vec<InputConfigMount>>,
}

@ -8,6 +8,7 @@ use rcore_fs_mountfs::{MNode, MountFS};
use rcore_fs_ramfs::RamFS;
use rcore_fs_sefs::dev::*;
use rcore_fs_sefs::SEFS;
use rcore_fs_unionfs::UnionFS;
lazy_static! {
/// The root of file system
@ -29,38 +30,61 @@ lazy_static! {
};
}
fn open_root_fs_according_to(mount_config: &Vec<ConfigMount>) -> Result<Arc<MountFS>> {
let (root_sefs_mac, root_sefs_source) = {
let root_mount_config = mount_config
fn open_root_fs_according_to(mount_configs: &Vec<ConfigMount>) -> Result<Arc<MountFS>> {
let mount_config = mount_configs
.iter()
.find(|m| m.target == Path::new("/"))
.ok_or_else(|| errno!(Errno::ENOENT, "the mount point at / is not specified"))?;
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 integrity-only");
}
if root_mount_config.source.is_none() {
return_errno!(
EINVAL,
"The root SEFS must be given a source path (on host)"
);
.find(|m| m.target == Path::new("/") && m.type_ == ConfigMountFsType::TYPE_UNIONFS)
.ok_or_else(|| errno!(Errno::ENOENT, "the root UnionFS is not valid"))?;
if mount_config.options.layers.is_none() {
return_errno!(EINVAL, "The root UnionFS must be given the layers");
}
let layer_mount_configs = mount_config.options.layers.as_ref().unwrap();
// image SEFS in layers
let (root_image_sefs_mac, root_image_sefs_source) = {
let mount_config = layer_mount_configs
.iter()
.find(|m| m.type_ == ConfigMountFsType::TYPE_SEFS && m.options.integrity_only)
.ok_or_else(|| errno!(Errno::ENOENT, "the image SEFS in layers is not valid"))?;
(
root_mount_config.options.mac,
root_mount_config.source.as_ref().unwrap(),
mount_config.options.mac,
mount_config.source.as_ref().unwrap(),
)
};
let root_sefs = SEFS::open(
Box::new(SgxStorage::new(root_sefs_source, true, root_sefs_mac)),
let root_image_sefs = SEFS::open(
Box::new(SgxStorage::new(
root_image_sefs_source,
true,
root_image_sefs_mac,
)),
&time::OcclumTimeProvider,
&SgxUuidProvider,
)?;
let root_mountable_sefs = MountFS::new(root_sefs);
Ok(root_mountable_sefs)
// container SEFS in layers
let root_container_sefs_source = {
let mount_config = layer_mount_configs
.iter()
.find(|m| m.type_ == ConfigMountFsType::TYPE_SEFS && !m.options.integrity_only)
.ok_or_else(|| errno!(Errno::ENOENT, "the container SEFS in layers is not valid"))?;
mount_config.source.as_ref().unwrap()
};
let root_container_sefs = {
SEFS::open(
Box::new(SgxStorage::new(root_container_sefs_source, false, None)),
&time::OcclumTimeProvider,
&SgxUuidProvider,
)
}
.or_else(|_| {
SEFS::create(
Box::new(SgxStorage::new(root_container_sefs_source, false, None)),
&time::OcclumTimeProvider,
&SgxUuidProvider,
)
})?;
let root_unionfs = UnionFS::new(vec![root_container_sefs, root_image_sefs])?;
let root_mountable_unionfs = MountFS::new(root_unionfs);
Ok(root_mountable_unionfs)
}
fn mount_nonroot_fs_according_to(mount_config: &Vec<ConfigMount>, root: &MNode) -> Result<()> {
@ -116,6 +140,9 @@ fn mount_nonroot_fs_according_to(mount_config: &Vec<ConfigMount>, root: &MNode)
let ramfs = RamFS::new();
mount_fs_at(ramfs, &root, target_dirname)?;
}
TYPE_UNIONFS => {
return_errno!(EINVAL, "Cannot mount UnionFS at non-root path");
}
}
}
Ok(())

@ -39,6 +39,7 @@ extern crate rcore_fs;
extern crate rcore_fs_mountfs;
extern crate rcore_fs_ramfs;
extern crate rcore_fs_sefs;
extern crate rcore_fs_unionfs;
#[macro_use]
extern crate derive_builder;
extern crate ringbuf;

@ -30,6 +30,11 @@
"debuggable": true
},
"mount": [
{
"target": "/",
"type": "unionfs",
"options": {
"layers": [
{
"target": "/",
"type": "sefs",
@ -39,8 +44,11 @@
}
},
{
"target": "/root",
"target": "/",
"type": "sefs"
}
]
}
},
{
"target": "/host",

@ -75,6 +75,9 @@ static int do_perm_tests(
int expected_result = expected_results[i];
int fd = open_file(filename, flags, 0666);
if (fd < 0 && fd != expected_result) {
return -1;
}
int result = do_write ? write_file(fd) : read_file(fd);
if (result != expected_result) {
return -1;
@ -101,15 +104,15 @@ static int test_expected_results[NUM_TEST_CASES][NUM_TEST_FILES] = {
// test_open_ro_then_write()
{NG, NG, NG, NG, NG},
// test_open_wo_then_write()
{NG, NG, NG, OK, OK},
{OK, OK, OK, OK, OK},
// test_open_rw_then_write()
{NG, NG, NG, OK, OK},
{OK, OK, OK, OK, OK},
// test_open_ro_then_read()
{NG, NG, NG, OK, OK},
{OK, OK, OK, OK, OK},
// test_open_wo_then_read()
{NG, NG, NG, NG, NG},
// test_open_rw_then_read()
{NG, NG, NG, OK, OK},
{OK, OK, OK, OK, OK},
};
int test_open_ro_then_write() {

@ -106,7 +106,7 @@ check_has_init() {
check_has_built() {
check_has_init
if [ ! -d "$context_dir/run/mount/root" ]; then
if [ ! -d "$context_dir/run/mount/__ROOT" ]; then
echo "Error: the Occlum image and enclave are not built yet. Need to run \"occlum build\" first."
exit 1
fi
@ -187,11 +187,9 @@ cmd_build() {
cd build/lib && ln -sf "$pal_lib.$occlum_version" "libocclum-pal.so.$major_ver" && \
ln -sf "libocclum-pal.so.$major_ver" libocclum-pal.so && cd -
chmod 531 -R $working_dir/image/bin
chmod 531 -R $working_dir/image/lib
mkdir -p build/mount/
cd "$occlum_dir/$build_dir/bin/" && \
LD_LIBRARY_PATH="$SGX_SDK/sdk_libs" ./sefs-fuse \
LD_LIBRARY_PATH="$SGX_SDK/sdk_libs" ./sefs-cli \
--integrity-only \
"$context_dir/build/mount/__ROOT" \
"$working_dir/image" \
@ -237,7 +235,7 @@ cmd_build() {
echo "HW" > .sgx_mode
fi
mkdir -p "$context_dir/run/mount/root"
mkdir -p "$context_dir/run/mount/__ROOT"
ln -s $occlum_dir/$build_dir/bin/occlum_exec_client $context_dir/build/bin/occlum_exec_client
ln -s $occlum_dir/$build_dir/bin/occlum_exec_server $context_dir/build/bin/occlum_exec_server

@ -15,6 +15,11 @@ cat <<EOF
"default_mmap_size": "$OCCLUM_CONF_DEFAULT_MMAP_SIZE"
},
"mount": [
{
"target": "/",
"type": "unionfs",
"options": {
"layers": [
{
"target": "/",
"type": "sefs",
@ -25,9 +30,12 @@ cat <<EOF
}
},
{
"target": "/root",
"target": "/",
"type": "sefs",
"source": "$OCCLUM_INSTANCE_DIR/run/mount/root"
"source": "$OCCLUM_INSTANCE_DIR/run/mount/__ROOT"
}
]
}
},
{
"target": "/host",