Support configurable Ext2+SwornDisk

This commit is contained in:
Shaowei Song 2024-05-12 20:21:23 +08:00 committed by volcano
parent 070a024c0d
commit 3cb34b95a7
28 changed files with 1142 additions and 80 deletions

@ -12,7 +12,9 @@ runs:
run: | run: |
docker exec ${{ inputs.container-name }} bash -c "git config --global --add safe.directory /root/occlum"; docker exec ${{ inputs.container-name }} bash -c "git config --global --add safe.directory /root/occlum";
docker exec ${{ inputs.container-name }} bash -c "git config --global --add safe.directory /root/occlum/deps/grpc-rust"; docker exec ${{ inputs.container-name }} bash -c "git config --global --add safe.directory /root/occlum/deps/grpc-rust";
docker exec ${{ inputs.container-name }} bash -c "git config --global --add safe.directory /root/occlum/deps/ext2-rs";
docker exec ${{ inputs.container-name }} bash -c "git config --global --add safe.directory /root/occlum/deps/itoa-sgx"; docker exec ${{ inputs.container-name }} bash -c "git config --global --add safe.directory /root/occlum/deps/itoa-sgx";
docker exec ${{ inputs.container-name }} bash -c "git config --global --add safe.directory /root/occlum/deps/mlsdisk";
docker exec ${{ inputs.container-name }} bash -c "git config --global --add safe.directory /root/occlum/deps/resolv-conf"; docker exec ${{ inputs.container-name }} bash -c "git config --global --add safe.directory /root/occlum/deps/resolv-conf";
docker exec ${{ inputs.container-name }} bash -c "git config --global --add safe.directory /root/occlum/deps/ringbuf"; docker exec ${{ inputs.container-name }} bash -c "git config --global --add safe.directory /root/occlum/deps/ringbuf";
docker exec ${{ inputs.container-name }} bash -c "git config --global --add safe.directory /root/occlum/deps/rust-sgx-sdk"; docker exec ${{ inputs.container-name }} bash -c "git config --global --add safe.directory /root/occlum/deps/rust-sgx-sdk";

6
.gitmodules vendored

@ -27,3 +27,9 @@
[submodule "deps/io-uring"] [submodule "deps/io-uring"]
path = deps/io-uring path = deps/io-uring
url = https://github.com/occlum/io-uring.git url = https://github.com/occlum/io-uring.git
[submodule "deps/mlsdisk"]
path = deps/mlsdisk
url = https://github.com/asterinas/mlsdisk
[submodule "deps/ext2-rs"]
path = deps/ext2-rs
url = https://github.com/liqinggd/ext2-rs

@ -71,6 +71,7 @@ init-submodule:
cd deps/serde-json-sgx && git apply ../serde-json-sgx.patch >/dev/null 2>&1 || git apply ../serde-json-sgx.patch -R --check cd deps/serde-json-sgx && git apply ../serde-json-sgx.patch >/dev/null 2>&1 || git apply ../serde-json-sgx.patch -R --check
cd deps/ringbuf && git apply ../ringbuf.patch >/dev/null 2>&1 || git apply ../ringbuf.patch -R --check cd deps/ringbuf && git apply ../ringbuf.patch >/dev/null 2>&1 || git apply ../ringbuf.patch -R --check
cd deps/resolv-conf && git apply ../resolv-conf.patch >/dev/null 2>&1 || git apply ../resolv-conf.patch -R --check cd deps/resolv-conf && git apply ../resolv-conf.patch >/dev/null 2>&1 || git apply ../resolv-conf.patch -R --check
cd deps/mlsdisk && git apply ../mlsdisk.patch >/dev/null 2>&1 || git apply ../mlsdisk.patch -R --check
src: src:
@$(MAKE) --no-print-directory -C src @$(MAKE) --no-print-directory -C src

1
deps/ext2-rs vendored Submodule

@ -0,0 +1 @@
Subproject commit e78615a899adeb7b6bef5811eb9244cc73680407

1
deps/mlsdisk vendored Submodule

@ -0,0 +1 @@
Subproject commit 864a00840110237d60d51e04d0e63394c812549a

28
deps/mlsdisk.patch vendored Normal file

@ -0,0 +1,28 @@
diff --git a/core/Cargo.toml b/core/Cargo.toml
index c1e1746..20b896f 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -22,16 +22,18 @@ serde = { version = "=1.0.188", default-features = false, features = ["alloc", "
spin = { version = "0.9.8", optional = true }
static_assertions = "1.1.0"
-sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["backtrace", "thread"], optional = true }
-sgx_rand = { git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true }
-sgx_tcrypto = { git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true }
-sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true }
+sgx_tstd = { path = "../../../deps/rust-sgx-sdk/sgx_tstd", features = ["backtrace", "thread"], optional = true }
+sgx_rand = { path = "../../../deps/rust-sgx-sdk/sgx_rand", optional = true }
+sgx_tcrypto = { path = "../../../deps/rust-sgx-sdk/sgx_tcrypto", optional = true }
+sgx_types = { path = "../../../deps/rust-sgx-sdk/sgx_types", optional = true }
+ext2-rs = { path = "../../../deps/ext2-rs", default-features = false, optional = true }
+ahash = { version="=0.8.6", default-features = false }
[features]
default = ["std"]
std = ["spin", "openssl", "log"]
linux = ["bindings"]
-occlum = ["sgx_tstd", "sgx_rand", "sgx_tcrypto", "sgx_types", "spin", "log"]
+occlum = ["sgx_tstd", "sgx_rand", "sgx_tcrypto", "sgx_types", "spin", "log", "ext2-rs/sgx"]
jinux = []

@ -1,6 +1,6 @@
# Occlum File System Overview # Occlum File System Overview
Occlum supports various file systems: e.g., read-only integrity-protected SEFS, writable encrypted SEFS, UnionFS, Async-SFS, untrusted HostFS, RamFS, and other pseudo filesystems. Occlum supports various file systems: e.g., read-only integrity-protected SEFS, writable encrypted SEFS, UnionFS, Ext2, untrusted HostFS, RamFS, and other pseudo filesystems.
Here is the default FS layout: Here is the default FS layout:
@ -16,12 +16,12 @@ Here is the default FS layout:
│ │ │ │
└──────┬──────┘ └──────┬──────┘
┌────────┬───┴─────┬───────┐ ──────────┬───┴─────┬───────┐
│ │ │
│"/sfs" │"/dev/shm"│"/proc" │"/dev" │"/dev/shm"│"/proc" │"/dev" │"/ext2"(optional)
┌───┴─┐ ┌──┴──┐ ┌───┴──┐ ┌──┴──┐ ┌──┴──┐ ┌───┴──┐ ┌──┴──┐ ┌─┴──┐
│A-SFS│ │RamFS│ │ProcFS│ │DevFS│ │RamFS│ │ProcFS│ │DevFS│ │Ext2│
└─────┘ └─────┘ └─────┘ └────┘ └─────┘ └─────┘ └─────┘ └────┘
``` ```
## SEFS ## SEFS
@ -103,33 +103,19 @@ Here is the configuration of rootfs, the first item is the lower layer RO-SEFS a
source: ./run/mount/__ROOT source: ./run/mount/__ROOT
``` ```
## Async-SFS ## Ext2
The Async-SFS is an asynchronous filesystem, which uses Rust asynchronous programming skills, making it fast and concurrent. It is mounted at `/sfs` by default. To achieve the high-performanced security, it uses the JinDisk as the underlying data storage and sends async I/O requests to it. The [Ext2](https://github.com/liqinggd/ext2-rs) is an independent filesystem Rust crate that resembles Linux's Ext2. For the sake of performance and security, it utilizes [SwornDisk](https://github.com/asterinas/mlsdisk) as its underlying block device. Compared with SEFS, the file I/O performance of "Ext2+SwornDisk" is superior. If your App's performance is highly dependent on file I/O, it is recommended to enable Ext2 in Occlum.json.
To accelerate block I/O, the page cache is introduced. It caches all the block I/O in the middle of Async-SFS and JinDisk. Thanks to the page cache and JinDisk, the result of the benchmark (e.g., FIO and Filebench) is significantly better than SEFS. If your App's performance is highly dependent on disk I/O, it is recommended to use Async-SFS.
``` ```
┌───────────┐ "mount": [{
│ │ "target": "/ext2",
│ Async-SFS │ "type": "ext2",
│ │ "options": {
└─────┬─────┘ "disk_size": "10GB"
}
┌─────┴─────┐ }]
│ │
│ Page Cache│
│ │
└─────┬─────┘
┌─────┴─────┐
│ │
│ JinDisk │
│ │
└───────────┘
``` ```
The configuration of enabling Ext2 is showed above, you can specify your mount point at `target`, the disk size that Ext2 manages should be specified at `options.disk_size`.
Currently, there are some limitations of Async-SFS:
1. The maximum size of the file is 4GB.
2. The maximum size of FS is 16TB.
## HostFS ## HostFS
The HostFS is used for convenient data exchange between the LibOS and the host OS. It simply wraps the untrusted host OS file to implement the functionalities of FS. So the data is straightforwardly transferred between LibOS and host OS without any protection or validation. The HostFS is used for convenient data exchange between the LibOS and the host OS. It simply wraps the untrusted host OS file to implement the functionalities of FS. So the data is straightforwardly transferred between LibOS and host OS without any protection or validation.

@ -147,6 +147,13 @@ The template of `Occlum.json` is shown below.
{ {
"target": "/dev", "target": "/dev",
"type": "devfs" "type": "devfs"
},
{
"target": "/ext2",
"type": "ext2",
"options": {
"disk_size": "10GB"
}
} }
] ]
} }

@ -15,7 +15,7 @@ For every application to be running in Occlum (TEE env), all the running require
| |-- opt | |-- opt
| |-- proc | |-- proc
| |-- root | |-- root
| |-- sfs | |-- sbin
| |-- sys | |-- sys
| `-- tmp | `-- tmp
|-- initfs // Occlum init file system |-- initfs // Occlum init file system

@ -13,3 +13,5 @@ targets:
- root - root
- sys - sys
- tmp - tmp
- sbin
- ext2

@ -4,6 +4,7 @@ enclave {
from "sgx_tstdc.edl" import *; from "sgx_tstdc.edl" import *;
from "sgx_tstd.edl" import *; from "sgx_tstd.edl" import *;
from "sgx_tprotected_fs.edl" import *; from "sgx_tprotected_fs.edl" import *;
from "sgx_thread.edl" import *;
from "sgx_net.edl" import *; from "sgx_net.edl" import *;
from "sgx_occlum_utils.edl" import *; from "sgx_occlum_utils.edl" import *;
from "sgx_vdso_time_ocalls.edl" import *; from "sgx_vdso_time_ocalls.edl" import *;

494
src/libos/Cargo.lock generated

@ -15,6 +15,7 @@ dependencies = [
"derive_builder", "derive_builder",
"downcast-rs", "downcast-rs",
"errno", "errno",
"ext2-rs",
"goblin", "goblin",
"intrusive-collections", "intrusive-collections",
"io-uring-callback", "io-uring-callback",
@ -35,7 +36,7 @@ dependencies = [
"resolv-conf", "resolv-conf",
"ringbuf", "ringbuf",
"scroll", "scroll",
"serde", "serde 1.0.104",
"serde_json", "serde_json",
"sgx-untrusted-alloc", "sgx-untrusted-alloc",
"sgx_cov", "sgx_cov",
@ -45,9 +46,22 @@ dependencies = [
"sgx_tstd", "sgx_tstd",
"sgx_types", "sgx_types",
"spin 0.7.1", "spin 0.7.1",
"sworndisk-v2",
"vdso-time", "vdso-time",
] ]
[[package]]
name = "ahash"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a"
dependencies = [
"cfg-if",
"once_cell",
"version_check",
"zerocopy",
]
[[package]] [[package]]
name = "aligned" name = "aligned"
version = "0.4.1" version = "0.4.1"
@ -57,6 +71,26 @@ dependencies = [
"as-slice", "as-slice",
] ]
[[package]]
name = "allocator-api2"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
[[package]]
name = "anymap"
version = "1.0.0-beta.2"
source = "git+https://github.com/lucassong-mh/anymap?branch=1.0.0-beta.2-patched#18f6555cf93ee5609b883feb6d1ec46ca14f2a78"
dependencies = [
"hashbrown",
]
[[package]]
name = "array-init"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc"
[[package]] [[package]]
name = "as-slice" name = "as-slice"
version = "0.2.1" version = "0.2.1"
@ -75,6 +109,15 @@ dependencies = [
"autocfg 1.1.0", "autocfg 1.1.0",
] ]
[[package]]
name = "atomic-polyfill"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
dependencies = [
"critical-section",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "0.1.8" version = "0.1.8"
@ -96,6 +139,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bittle"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14173f083171cee3f00fbbfa3d3d2492401c25c015874aad543bbf829d6389f8"
[[package]] [[package]]
name = "bitvec" name = "bitvec"
version = "0.17.4" version = "0.17.4"
@ -145,6 +194,33 @@ dependencies = [
"bitflags", "bitflags",
] ]
[[package]]
name = "cobs"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
[[package]]
name = "critical-section"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
[[package]]
name = "crossbeam-queue"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
[[package]] [[package]]
name = "ctor" name = "ctor"
version = "0.1.23" version = "0.1.23"
@ -152,7 +228,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdffe87e1d521a10f9696f833fe502293ea446d7f256c06128293a4119bdf4cb" checksum = "cdffe87e1d521a10f9696f833fe502293ea446d7f256c06128293a4119bdf4cb"
dependencies = [ dependencies = [
"quote", "quote",
"syn", "syn 1.0.99",
] ]
[[package]] [[package]]
@ -161,8 +237,18 @@ version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
dependencies = [ dependencies = [
"darling_core", "darling_core 0.10.2",
"darling_macro", "darling_macro 0.10.2",
]
[[package]]
name = "darling"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
dependencies = [
"darling_core 0.13.4",
"darling_macro 0.13.4",
] ]
[[package]] [[package]]
@ -175,8 +261,22 @@ dependencies = [
"ident_case", "ident_case",
"proc-macro2", "proc-macro2",
"quote", "quote",
"strsim", "strsim 0.9.3",
"syn", "syn 1.0.99",
]
[[package]]
name = "darling_core"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim 0.10.0",
"syn 1.0.99",
] ]
[[package]] [[package]]
@ -185,9 +285,20 @@ version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
dependencies = [ dependencies = [
"darling_core", "darling_core 0.10.2",
"quote", "quote",
"syn", "syn 1.0.99",
]
[[package]]
name = "darling_macro"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
dependencies = [
"darling_core 0.13.4",
"quote",
"syn 1.0.99",
] ]
[[package]] [[package]]
@ -196,11 +307,11 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0" checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0"
dependencies = [ dependencies = [
"darling", "darling 0.10.2",
"derive_builder_core", "derive_builder_core",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.99",
] ]
[[package]] [[package]]
@ -209,10 +320,10 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef" checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef"
dependencies = [ dependencies = [
"darling", "darling 0.10.2",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.99",
] ]
[[package]] [[package]]
@ -237,6 +348,55 @@ dependencies = [
"sgx_tstd", "sgx_tstd",
] ]
[[package]]
name = "ext-trait"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d772df1c1a777963712fb68e014235e80863d6a91a85c4e06ba2d16243a310e5"
dependencies = [
"ext-trait-proc_macros",
]
[[package]]
name = "ext-trait-proc_macros"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ab7934152eaf26aa5aa9f7371408ad5af4c31357073c9e84c3b9d7f11ad639a"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.99",
]
[[package]]
name = "ext2-rs"
version = "0.1.0"
dependencies = [
"bitflags",
"bitvec 1.0.1",
"cfg-if",
"inherit-methods-macro",
"log",
"lru",
"pod",
"rcore-fs",
"sgx_libc",
"sgx_trts",
"sgx_tstd",
"sgx_types",
"spin 0.9.8",
"static_assertions 1.1.0",
]
[[package]]
name = "extension-traits"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a296e5a895621edf9fa8329c83aa1cb69a964643e36cf54d8d7a69b789089537"
dependencies = [
"ext-trait",
]
[[package]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"
@ -327,16 +487,61 @@ dependencies = [
"scroll", "scroll",
] ]
[[package]]
name = "hash32"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
dependencies = [
"byteorder",
]
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
dependencies = [
"ahash",
"allocator-api2",
"serde 1.0.188",
]
[[package]] [[package]]
name = "hashbrown_tstd" name = "hashbrown_tstd"
version = "0.12.0" version = "0.12.0"
[[package]]
name = "heapless"
version = "0.7.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
dependencies = [
"atomic-polyfill",
"hash32",
"rustc_version",
"serde 1.0.188",
"spin 0.9.8",
"stable_deref_trait",
]
[[package]] [[package]]
name = "ident_case" name = "ident_case"
version = "1.0.1" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "inherit-methods-macro"
version = "0.1.0"
source = "git+https://github.com/asterinas/inherit-methods-macro?rev=98f7e3e#98f7e3eb9efdac98faf5a7076f154f30894b9b02"
dependencies = [
"darling 0.13.4",
"proc-macro2",
"quote",
"syn 1.0.99",
]
[[package]] [[package]]
name = "intrusive-collections" name = "intrusive-collections"
version = "0.9.4" version = "0.9.4"
@ -406,10 +611,35 @@ dependencies = [
] ]
[[package]] [[package]]
name = "libc" name = "lending-iterator"
version = "0.2.132" version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" checksum = "bc07588c853b50689205fb5c00498aa681d89828e0ce8cbd965ebc7a5d8ae260"
dependencies = [
"extension-traits",
"lending-iterator-proc_macros",
"macro_rules_attribute",
"never-say-never",
"nougat",
"polonius-the-crab",
]
[[package]]
name = "lending-iterator-proc_macros"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5445dd1c0deb1e97b8a16561d17fc686ca83e8411128fb036e9668a72d51b1d"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.99",
]
[[package]]
name = "libc"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
@ -429,6 +659,31 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "lru"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc"
dependencies = [
"hashbrown",
]
[[package]]
name = "macro_rules_attribute"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf0c9b980bf4f3a37fd7b1c066941dd1b1d0152ce6ee6e8fe8c49b9f6810d862"
dependencies = [
"macro_rules_attribute-proc_macro",
"paste",
]
[[package]]
name = "macro_rules_attribute-proc_macro"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58093314a45e00c77d5c508f76e77c3396afbbc0d01506e7fae47b018bac2b1d"
[[package]] [[package]]
name = "memoffset" name = "memoffset"
version = "0.5.6" version = "0.5.6"
@ -465,7 +720,34 @@ checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.99",
]
[[package]]
name = "never-say-never"
version = "6.6.666"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf5a574dadd7941adeaa71823ecba5e28331b8313fb2e1c6a5c7e5981ea53ad6"
[[package]]
name = "nougat"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b57b9ced431322f054fc673f1d3c7fa52d80efd9df74ad2fc759f044742510"
dependencies = [
"macro_rules_attribute",
"nougat-proc_macros",
]
[[package]]
name = "nougat-proc_macros"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c84f77a45e99a2f9b492695d99e1c23844619caa5f3e57647cffacad773ca257"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.99",
] ]
[[package]] [[package]]
@ -485,9 +767,21 @@ checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.99",
] ]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.13" version = "0.2.13"
@ -507,10 +801,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
[[package]] [[package]]
name = "proc-macro2" name = "pod"
version = "1.0.43" version = "0.1.0"
source = "git+https://github.com/asterinas/pod?rev=d7dba56#d7dba56cc202a10d483b60aba4f734b1f49cb37b"
dependencies = [
"pod-derive",
]
[[package]]
name = "pod-derive"
version = "0.1.0"
source = "git+https://github.com/asterinas/pod?rev=d7dba56#d7dba56cc202a10d483b60aba4f734b1f49cb37b"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.99",
]
[[package]]
name = "polonius-the-crab"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" checksum = "c2a69ee997a6282f8462abf1e0d8c38c965e968799e912b3bed8c9e8a28c2f9f"
[[package]]
name = "postcard"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9ee729232311d3cd113749948b689627618133b1c5012b77342c1950b25eaeb"
dependencies = [
"cobs",
"heapless",
"serde 1.0.188",
]
[[package]]
name = "proc-macro2"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -527,9 +856,9 @@ source = "git+https://github.com/mesalock-linux/quick-error-sgx.git#468bf2cce746
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.21" version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -749,6 +1078,15 @@ dependencies = [
"sgx_tstd", "sgx_tstd",
] ]
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver",
]
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.11" version = "1.0.11"
@ -778,24 +1116,50 @@ checksum = "bdbda6ac5cd1321e724fa9cee216f3a61885889b896f073b8f82322789c5250e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.99",
] ]
[[package]]
name = "semver"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.104" version = "1.0.104"
dependencies = [ dependencies = [
"serde_derive", "serde_derive 1.0.104",
"sgx_tstd", "sgx_tstd",
] ]
[[package]]
name = "serde"
version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
dependencies = [
"serde_derive 1.0.188",
]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.104" version = "1.0.104"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.99",
]
[[package]]
name = "serde_derive"
version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.50",
] ]
[[package]] [[package]]
@ -804,7 +1168,7 @@ version = "1.0.40"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
"serde", "serde 1.0.104",
"sgx_tstd", "sgx_tstd",
] ]
@ -951,6 +1315,15 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13287b4da9d1207a4f4929ac390916d64eacfe236a487e9a9f5b3be392be5162" checksum = "13287b4da9d1207a4f4929ac390916d64eacfe236a487e9a9f5b3be392be5162"
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
dependencies = [
"lock_api",
]
[[package]] [[package]]
name = "stable_deref_trait" name = "stable_deref_trait"
version = "1.2.0" version = "1.2.0"
@ -975,6 +1348,38 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "sworndisk-v2"
version = "0.1.0"
dependencies = [
"ahash",
"anymap",
"array-init",
"bittle",
"crossbeam-queue",
"ext2-rs",
"hashbrown",
"inherit-methods-macro",
"lending-iterator",
"log",
"lru",
"pod",
"postcard",
"serde 1.0.188",
"sgx_rand",
"sgx_tcrypto",
"sgx_tstd",
"sgx_types",
"spin 0.9.8",
"static_assertions 1.1.0",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.99" version = "1.0.99"
@ -986,6 +1391,17 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "syn"
version = "2.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]] [[package]]
name = "tap" name = "tap"
version = "1.0.1" version = "1.0.1"
@ -1021,6 +1437,12 @@ dependencies = [
"sgx_types", "sgx_types",
] ]
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"
@ -1051,3 +1473,23 @@ checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
dependencies = [ dependencies = [
"tap", "tap",
] ]
[[package]]
name = "zerocopy"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.50",
]

@ -35,6 +35,8 @@ regex = { git = "https://github.com/mesalock-linux/regex-sgx", default-features
goblin = { version = "0.5.4", default-features = false, features = ["elf64", "elf32", "endian_fd"] } goblin = { version = "0.5.4", default-features = false, features = ["elf64", "elf32", "endian_fd"] }
intrusive-collections = "0.9" intrusive-collections = "0.9"
modular-bitfield = "0.11.2" modular-bitfield = "0.11.2"
sworndisk-v2 = { path = "../../deps/mlsdisk/core", default-features = false, features = ["occlum"] }
ext2-rs = { path = "../../deps/ext2-rs", default-features = false, features = ["sgx"] }
sgx-untrusted-alloc = { path = "./crates/sgx-untrusted-alloc", features = ["sgx"]} sgx-untrusted-alloc = { path = "./crates/sgx-untrusted-alloc", features = ["sgx"]}
io-uring-callback = { path = "./crates/io-uring-callback", features = ["sgx"]} io-uring-callback = { path = "./crates/io-uring-callback", features = ["sgx"]}

@ -0,0 +1,182 @@
//! Block device wrapper, currently used for the DevFS.
use super::{BlockDevice, BlockDeviceExt, RawDisk, GB};
use crate::fs::*;
use crate::prelude::*;
use crate::util::sgx::get_autokey;
use core::any::Any;
use rcore_fs::vfs::{self, FileType, INode, Metadata, Timespec};
use std::path::PathBuf;
use sworndisk_v2::{AeadKey, SwornDisk, BLOCK_SIZE};
lazy_static! {
pub static ref SWORNDISK: RwLock<Option<Arc<SwornDisk<RawDisk>>>> = { RwLock::new(None) };
pub static ref SWORNDISK_METADATA: RwLock<SwornDiskMeta> =
{ RwLock::new(SwornDiskMeta::default()) };
}
pub const DEV_SWORNDISK: &str = "sworndisk";
/// Block device wrapper.
pub struct DevDisk {
disk: Arc<dyn BlockDevice>,
}
impl DevDisk {
pub fn open_or_create(name: &str) -> Result<Self> {
let disk: Arc<dyn BlockDevice> = match name {
// Currently only support SwornDisk
DEV_SWORNDISK => {
let mut sworndisk_opt = SWORNDISK.write().unwrap();
if let Some(sworndisk) = sworndisk_opt.as_ref() {
sworndisk.clone()
} else {
let metadata = SWORNDISK_METADATA.read().unwrap();
if !metadata.is_setup {
return_errno!(EINVAL, "SwornDisk not set up");
}
let total_blocks = metadata.size / BLOCK_SIZE;
let image_path = {
let mut path = metadata.image_dir.clone();
path.push("sworndisk.image");
path
};
let raw_disk =
RawDisk::open_or_create(total_blocks, image_path.to_str().unwrap())?;
let root_key = metadata.root_key;
let sworndisk = Arc::new(
SwornDisk::open(raw_disk.clone(), root_key, None).unwrap_or_else(|_e| {
SwornDisk::create(raw_disk, root_key, None).unwrap()
}),
);
sworndisk_opt.insert(sworndisk.clone());
sworndisk
}
}
_ => return_errno!(EINVAL, "Unrecognized block device"),
};
Ok(Self { disk })
}
pub fn disk(&self) -> Arc<dyn BlockDevice> {
self.disk.clone()
}
}
// Used for registering the disk to the DevFS
impl INode for DevDisk {
fn read_at(&self, offset: usize, buf: &mut [u8]) -> vfs::Result<usize> {
if rw_args_block_aligned(offset, buf.len()) {
self.disk
.read_blocks((offset / BLOCK_SIZE) as _, &mut [buf])?;
} else {
self.disk.read_bytes(offset, buf)?;
}
Ok(buf.len())
}
fn write_at(&self, offset: usize, buf: &[u8]) -> vfs::Result<usize> {
if rw_args_block_aligned(offset, buf.len()) {
self.disk.write_blocks((offset / BLOCK_SIZE) as _, &[buf])?;
} else {
self.disk.write_bytes(offset, buf)?;
}
Ok(buf.len())
}
fn metadata(&self) -> vfs::Result<Metadata> {
Ok(Metadata {
dev: 0,
inode: 0xfe23_1d08,
size: self.disk.total_bytes(),
blk_size: BLOCK_SIZE,
blocks: self.disk.total_blocks(),
atime: Timespec { sec: 0, nsec: 0 },
mtime: Timespec { sec: 0, nsec: 0 },
ctime: Timespec { sec: 0, nsec: 0 },
type_: FileType::File,
mode: 0o666,
nlinks: 1,
uid: 0,
gid: 0,
rdev: 0,
})
}
fn sync_all(&self) -> vfs::Result<()> {
self.disk.sync()?;
Ok(())
}
fn sync_data(&self) -> vfs::Result<()> {
self.disk.sync()?;
Ok(())
}
fn as_any_ref(&self) -> &dyn Any {
self
}
}
fn rw_args_block_aligned(offset: usize, buf_len: usize) -> bool {
if offset % BLOCK_SIZE == 0 && buf_len > 0 && buf_len % BLOCK_SIZE == 0 {
true
} else {
false
}
}
/// Metadata for SwornDisk.
#[derive(Debug)]
pub struct SwornDiskMeta {
size: usize,
root_key: AeadKey,
image_dir: PathBuf,
is_setup: bool,
}
impl Default for SwornDiskMeta {
fn default() -> Self {
Self {
size: 0,
root_key: AeadKey::default(),
image_dir: PathBuf::from("run"),
is_setup: false,
}
}
}
impl SwornDiskMeta {
pub fn setup(
disk_size: u64,
user_key: &Option<sgx_key_128bit_t>,
source_path: Option<&PathBuf>,
) -> Result<()> {
let mut metadata = SWORNDISK_METADATA.write().unwrap();
if metadata.is_setup {
return_errno!(EEXIST, "SwornDisk already set up");
};
if disk_size < (5 * GB) as _ {
return_errno!(EINVAL, "Disk size too small for SwornDisk");
};
metadata.size = disk_size as _;
if let Some(source_path) = source_path {
metadata.image_dir = source_path.clone();
}
let root_key = if let Some(user_key) = user_key {
*user_key
} else {
get_autokey(&metadata.image_dir)?
};
metadata.root_key = AeadKey::from(root_key);
metadata.is_setup = true;
Ok(())
}
pub fn is_setup() -> bool {
SWORNDISK_METADATA.read().unwrap().is_setup
}
}

13
src/libos/src/blk/mod.rs Normal file

@ -0,0 +1,13 @@
//! Block layer.
mod dev_disk;
mod raw_disk;
pub use self::dev_disk::{DevDisk, SwornDiskMeta, DEV_SWORNDISK};
pub use self::raw_disk::RawDisk;
pub use ext2_rs::{Bid, BlockDevice, BlockDeviceExt};
pub const BLOCK_SIZE: usize = 0x1000;
pub const MB: usize = 1024 * 1024;
pub const GB: usize = 1024 * MB;

@ -0,0 +1,137 @@
//! Raw disk.
use super::{Bid, BlockDevice};
use crate::blk::BLOCK_SIZE;
use crate::prelude::*;
use alloc::ffi::CString;
use alloc::string::{String, ToString};
use core::ops::Range;
use sgx_trts::libc::ocall::{fdatasync, ftruncate, open64, pread64, pwrite64, unlink};
use sgx_trts::libc::{O_CREAT, O_DIRECT, O_RDWR, O_TRUNC};
use std::os::unix::io::{AsRawFd, RawFd};
use ext2_rs::FsError as Ext2Error;
use sworndisk_v2::{BlockId, BlockSet, BufMut, BufRef, Errno as SwornErrno, Error as SwornError};
/// A raw disk as a block device, backed by a host file.
#[derive(Clone, Debug)]
pub struct RawDisk {
fd: RawFd,
path: String,
range: Range<BlockId>,
}
impl RawDisk {
pub fn open_or_create(nblocks: usize, path: &str) -> Result<Self> {
unsafe {
let flags = O_RDWR | O_CREAT; // w/o O_DIRECT
// let flags = O_RDWR | O_CREAT | O_DIRECT; // w/o O_TRUNC
let cpath = CString::new(path).unwrap();
let fd = open64(cpath.as_ptr() as _, flags, 0o666);
if fd == -1 {
return_errno!(EIO, "raw disk open failed");
}
let res = ftruncate(fd, (nblocks * BLOCK_SIZE) as _);
if res == -1 {
return_errno!(EIO, "raw disk truncate failed");
}
Ok(Self {
fd,
path: path.to_string(),
range: 0..nblocks,
})
}
}
}
// Used by `SwornDisk` as its underlying disk.
impl BlockSet for RawDisk {
fn read(&self, mut pos: BlockId, mut buf: BufMut) -> core::result::Result<(), SwornError> {
pos += self.range.start;
debug_assert!(pos + buf.nblocks() <= self.range.end);
let buf_mut_slice = buf.as_mut_slice();
unsafe {
let res = pread64(
self.fd,
buf_mut_slice.as_ptr() as _,
buf_mut_slice.len(),
(pos * BLOCK_SIZE) as _,
);
if res == -1 {
return Err(SwornError::with_msg(
SwornErrno::IoFailed,
"raw disk read failed",
));
}
}
Ok(())
}
fn write(&self, mut pos: BlockId, buf: BufRef) -> core::result::Result<(), SwornError> {
pos += self.range.start;
debug_assert!(pos + buf.nblocks() <= self.range.end);
let buf_slice = buf.as_slice();
unsafe {
let res = pwrite64(
self.fd,
buf_slice.as_ptr() as _,
buf_slice.len(),
(pos * BLOCK_SIZE) as _,
);
if res == -1 {
return Err(SwornError::with_msg(
SwornErrno::IoFailed,
"raw disk write failed",
));
}
}
Ok(())
}
fn subset(&self, range: Range<BlockId>) -> core::result::Result<Self, SwornError>
where
Self: Sized,
{
debug_assert!(self.range.start + range.end <= self.range.end);
Ok(Self {
fd: self.fd,
path: self.path.clone(),
range: Range {
start: self.range.start + range.start,
end: self.range.start + range.end,
},
})
}
fn flush(&self) -> core::result::Result<(), SwornError> {
unsafe {
let res = fdatasync(self.fd);
if res == -1 {
return Err(SwornError::with_msg(
SwornErrno::IoFailed,
"raw disk sync failed",
));
}
}
Ok(())
}
fn nblocks(&self) -> usize {
self.range.len()
}
}
impl Drop for RawDisk {
fn drop(&mut self) {
unsafe {
// XXX: When should we delete the host file?
// unlink(self.path.as_ptr() as _);
}
}
}

@ -162,6 +162,7 @@ pub enum ConfigMountFsType {
TYPE_UNIONFS, TYPE_UNIONFS,
TYPE_DEVFS, TYPE_DEVFS,
TYPE_PROCFS, TYPE_PROCFS,
TYPE_EXT2,
} }
impl ConfigMountFsType { impl ConfigMountFsType {
@ -175,6 +176,7 @@ impl ConfigMountFsType {
"unionfs" => ConfigMountFsType::TYPE_UNIONFS, "unionfs" => ConfigMountFsType::TYPE_UNIONFS,
"devfs" => ConfigMountFsType::TYPE_DEVFS, "devfs" => ConfigMountFsType::TYPE_DEVFS,
"procfs" => ConfigMountFsType::TYPE_PROCFS, "procfs" => ConfigMountFsType::TYPE_PROCFS,
"ext2" => ConfigMountFsType::TYPE_EXT2,
_ => { _ => {
return_errno!(EINVAL, "Unsupported file system type"); return_errno!(EINVAL, "Unsupported file system type");
} }
@ -189,6 +191,7 @@ pub struct ConfigMountOptions {
pub layers: Option<Vec<ConfigMount>>, pub layers: Option<Vec<ConfigMount>>,
pub temporary: bool, pub temporary: bool,
pub cache_size: Option<u64>, pub cache_size: Option<u64>,
pub disk_size: Option<u64>,
pub index: u32, pub index: u32,
} }
@ -363,11 +366,17 @@ impl ConfigMountOptions {
} else { } else {
None None
}; };
let disk_size = if input.disk_size.is_some() {
Some(parse_memory_size(input.disk_size.as_ref().unwrap())? as _)
} else {
None
};
Ok(ConfigMountOptions { Ok(ConfigMountOptions {
mac, mac,
layers, layers,
temporary: input.temporary, temporary: input.temporary,
cache_size, cache_size,
disk_size,
index: input.index, index: input.index,
}) })
} }
@ -518,6 +527,8 @@ struct InputConfigMountOptions {
#[serde(default)] #[serde(default)]
pub cache_size: Option<String>, pub cache_size: Option<String>,
#[serde(default)] #[serde(default)]
pub disk_size: Option<String>,
#[serde(default)]
pub index: u32, pub index: u32,
} }

@ -12,6 +12,7 @@ use self::dev_random::DevRandom;
use self::dev_sgx::DevSgx; use self::dev_sgx::DevSgx;
use self::dev_shm::DevShm; use self::dev_shm::DevShm;
use self::dev_zero::DevZero; use self::dev_zero::DevZero;
use blk::DevDisk;
mod dev_fd; mod dev_fd;
mod dev_null; mod dev_null;
@ -21,7 +22,7 @@ mod dev_shm;
mod dev_zero; mod dev_zero;
/// API to initialize the DevFS /// API to initialize the DevFS
pub fn init_devfs() -> Result<Arc<MountFS>> { pub fn init_devfs(disk_options: &[DevDiskOption]) -> Result<Arc<MountFS>> {
let devfs = DevFS::new(); let devfs = DevFS::new();
let dev_null = Arc::new(DevNull) as _; let dev_null = Arc::new(DevNull) as _;
devfs.add("null", dev_null)?; devfs.add("null", dev_null)?;
@ -37,6 +38,11 @@ pub fn init_devfs() -> Result<Arc<MountFS>> {
devfs.add("shm", dev_shm)?; devfs.add("shm", dev_shm)?;
let dev_fd = Arc::new(DevFd) as _; let dev_fd = Arc::new(DevFd) as _;
devfs.add("fd", dev_fd); devfs.add("fd", dev_fd);
for disk_option in disk_options {
let disk_name = &disk_option.name;
let dev_disk = Arc::new(DevDisk::open_or_create(disk_name)?);
devfs.add(disk_name, dev_disk)?;
}
let mountable_devfs = MountFS::new(devfs); let mountable_devfs = MountFS::new(devfs);
// Mount the ramfs at '/shm' // Mount the ramfs at '/shm'
let ramfs = RamFS::new(); let ramfs = RamFS::new();
@ -49,3 +55,14 @@ pub fn init_devfs() -> Result<Arc<MountFS>> {
// TODO: Add stdio(stdin, stdout, stderr) into DevFS // TODO: Add stdio(stdin, stdout, stderr) into DevFS
Ok(mountable_devfs) Ok(mountable_devfs)
} }
/// Options of block device under the DevFS.
pub struct DevDiskOption {
name: &'static str,
}
impl DevDiskOption {
pub fn new(name: &'static str) -> Self {
Self { name }
}
}

@ -24,13 +24,14 @@ pub fn do_mount_rootfs(
let mount_config = &user_app_config.mount; let mount_config = &user_app_config.mount;
let new_rootfs = open_root_fs_according_to(mount_config, user_key)?; 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)?; let root_inode = new_rootfs.root_inode();
MOUNT_ONCE.call_once(|| { MOUNT_ONCE.call_once(|| {
let mut rootfs = ROOT_FS.write().unwrap(); let mut rootfs = ROOT_FS.write().unwrap();
rootfs.sync().expect("failed to sync old rootfs"); rootfs.sync().expect("failed to sync old rootfs");
*rootfs = new_rootfs; *rootfs = new_rootfs;
*ENTRY_POINTS.write().unwrap() = user_app_config.entry_points.to_owned(); *ENTRY_POINTS.write().unwrap() = user_app_config.entry_points.to_owned();
}); });
mount_nonroot_fs_according_to(&root_inode, mount_config, user_key, true)?;
// Write resolv.conf file into mounted file system // Write resolv.conf file into mounted file system
write_host_file(HostFile::ResolvConf)?; write_host_file(HostFile::ResolvConf)?;
@ -137,18 +138,25 @@ pub fn do_mount(
}; };
(vec![mc], None) (vec![mc], None)
} }
MountOptions::Ext2 => {
let mc = ConfigMount {
type_: ConfigMountFsType::TYPE_EXT2,
target,
source: None,
options: Default::default(),
};
(vec![mc], None)
}
}; };
let mut rootfs = ROOT_FS.write().unwrap(); let mut rootfs = ROOT_FS.write().unwrap();
// Should we sync the fs before mount? // Should we sync the fs before mount?
rootfs.sync()?; rootfs.sync()?;
let root_inode = rootfs.root_inode();
drop(rootfs);
let follow_symlink = !flags.contains(MountFlags::MS_NOSYMFOLLOW); let follow_symlink = !flags.contains(MountFlags::MS_NOSYMFOLLOW);
mount_nonroot_fs_according_to( mount_nonroot_fs_according_to(&root_inode, &mount_configs, &user_key, follow_symlink)?;
&rootfs.root_inode(),
&mount_configs,
&user_key,
follow_symlink,
)?;
Ok(()) Ok(())
} }
@ -215,6 +223,7 @@ pub enum MountOptions {
SEFS(SEFSMountOptions), SEFS(SEFSMountOptions),
HostFS(PathBuf), HostFS(PathBuf),
RamFS, RamFS,
Ext2,
} }
impl MountOptions { impl MountOptions {
@ -253,6 +262,7 @@ impl MountOptions {
Self::HostFS(dir) Self::HostFS(dir)
} }
ConfigMountFsType::TYPE_RAMFS => Self::RamFS, ConfigMountFsType::TYPE_RAMFS => Self::RamFS,
ConfigMountFsType::TYPE_EXT2 => Self::Ext2,
_ => { _ => {
return_errno!(EINVAL, "unsupported fs type"); return_errno!(EINVAL, "unsupported fs type");
} }

@ -3,18 +3,20 @@ use super::hostfs::HostFS;
use super::procfs::ProcFS; use super::procfs::ProcFS;
use super::sefs::{SgxStorage, SgxUuidProvider}; use super::sefs::{SgxStorage, SgxUuidProvider};
use super::*; use super::*;
use config::{ConfigApp, ConfigMountFsType}; use crate::blk::{DevDisk, SwornDiskMeta, DEV_SWORNDISK};
use std::mem::size_of; use crate::config::{ConfigApp, ConfigMountFsType};
use std::path::{Path, PathBuf}; use crate::fs::dev_fs::DevDiskOption;
use std::untrusted::path::PathEx; use crate::time::OcclumTimeProvider;
use alloc::ffi::CString;
use ext2_rs::{BlockDevice, Ext2};
use rcore_fs_mountfs::{MNode, MountFS}; use rcore_fs_mountfs::{MNode, MountFS};
use rcore_fs_ramfs::RamFS; use rcore_fs_ramfs::RamFS;
use rcore_fs_sefs::dev::*; use rcore_fs_sefs::dev::*;
use rcore_fs_sefs::SEFS; use rcore_fs_sefs::SEFS;
use rcore_fs_unionfs::UnionFS; use rcore_fs_unionfs::UnionFS;
use std::path::{Path, PathBuf};
use util::mem_util::from_user; use std::untrusted::path::PathEx;
lazy_static! { lazy_static! {
/// The root of file system /// The root of file system
@ -102,6 +104,14 @@ pub fn mount_nonroot_fs_according_to(
user_key: &Option<sgx_key_128bit_t>, user_key: &Option<sgx_key_128bit_t>,
follow_symlink: bool, follow_symlink: bool,
) -> Result<()> { ) -> Result<()> {
let mc_ext2_opt = mount_configs
.iter()
.find(|mc| mc.type_ == ConfigMountFsType::TYPE_EXT2);
if let Some(mc) = mc_ext2_opt {
// Setup disk metadata first if enabled Ext2
setup_disk_meta_for_ext2(mc, user_key)?;
}
for mc in mount_configs { for mc in mount_configs {
if mc.target == Path::new("/") { if mc.target == Path::new("/") {
continue; continue;
@ -140,7 +150,12 @@ pub fn mount_nonroot_fs_according_to(
mount_fs_at(ramfs, root, &mc.target, follow_symlink)?; mount_fs_at(ramfs, root, &mc.target, follow_symlink)?;
} }
TYPE_DEVFS => { TYPE_DEVFS => {
let devfs = dev_fs::init_devfs()?; let disk_options = if mc_ext2_opt.is_some() {
vec![DevDiskOption::new(DEV_SWORNDISK)]
} else {
vec![]
};
let devfs = dev_fs::init_devfs(&disk_options)?;
mount_fs_at(devfs, root, &mc.target, follow_symlink)?; mount_fs_at(devfs, root, &mc.target, follow_symlink)?;
} }
TYPE_PROCFS => { TYPE_PROCFS => {
@ -172,8 +187,17 @@ pub fn mount_nonroot_fs_according_to(
}; };
mount_fs_at(unionfs, root, &mc.target, follow_symlink)?; mount_fs_at(unionfs, root, &mc.target, follow_symlink)?;
} }
TYPE_EXT2 => {
// Leave mounting the Ext2 to the final step
// before the disk under the DevFS is ready
}
} }
} }
if let Some(mc) = mc_ext2_opt {
let ext2 = open_ext2()?;
mount_fs_at(ext2, root, &mc.target, follow_symlink)?;
}
Ok(()) Ok(())
} }
@ -266,3 +290,44 @@ fn open_or_create_sefs_according_to(
}; };
Ok(sefs) Ok(sefs)
} }
fn open_ext2() -> Result<Arc<Ext2>> {
debug_assert!(SwornDiskMeta::is_setup());
let sworndisk = DevDisk::open_or_create(DEV_SWORNDISK)?.disk();
let ext2 = match Ext2::open(sworndisk, Arc::new(OcclumTimeProvider)) {
Err(e) if e == ext2_rs::FsError::WrongFs => {
let sworndisk = format_disk_for_ext2()?;
Ext2::open(sworndisk, Arc::new(OcclumTimeProvider))?
}
res => res?,
};
Ok(ext2)
}
fn format_disk_for_ext2() -> Result<Arc<dyn BlockDevice>> {
// Format the SwornDisk using 'mke2fs' tool for Ext2
let path = PathBuf::from("/sbin/mke2fs");
let argv = vec![
CString::new("mke2fs").unwrap(),
CString::new("-q").unwrap(),
CString::new("-t").unwrap(),
CString::new("ext2").unwrap(),
CString::new("/dev/".to_owned() + DEV_SWORNDISK).unwrap(),
];
let pid = process::do_spawn(&path.to_str().unwrap(), &argv, &[], &[], None, &current!())?;
let _ = process::do_wait4(pid as _, core::ptr::null_mut(), 0)?;
let sworndisk = DevDisk::open_or_create(DEV_SWORNDISK)?.disk();
Ok(sworndisk)
}
fn setup_disk_meta_for_ext2(mc: &ConfigMount, user_key: &Option<sgx_key_128bit_t>) -> Result<()> {
debug_assert_eq!(mc.type_, ConfigMountFsType::TYPE_EXT2);
let disk_size = mc.options.disk_size;
if disk_size.is_none() {
return_errno!(EINVAL, "Disk size is expected for Ext2");
}
let source_path = mc.source.as_ref();
SwornDiskMeta::setup(disk_size.unwrap(), user_key, source_path)
}

@ -21,6 +21,7 @@ macro_rules! try_libc_stdio {
// Struct for the occlum_stdio_fds // Struct for the occlum_stdio_fds
#[repr(C)] #[repr(C)]
#[derive(Debug)]
pub struct HostStdioFds { pub struct HostStdioFds {
pub stdin_fd: i32, pub stdin_fd: i32,
pub stdout_fd: i32, pub stdout_fd: i32,
@ -30,11 +31,7 @@ pub struct HostStdioFds {
impl HostStdioFds { impl HostStdioFds {
pub fn from_user(ptr: *const HostStdioFds) -> Result<Self> { pub fn from_user(ptr: *const HostStdioFds) -> Result<Self> {
if ptr.is_null() { if ptr.is_null() {
return Ok(Self { return Ok(Self::default());
stdin_fd: libc::STDIN_FILENO,
stdout_fd: libc::STDOUT_FILENO,
stderr_fd: libc::STDERR_FILENO,
});
} }
let host_stdio_fds_c = unsafe { &*ptr }; let host_stdio_fds_c = unsafe { &*ptr };
if host_stdio_fds_c.stdin_fd < 0 if host_stdio_fds_c.stdin_fd < 0
@ -51,6 +48,16 @@ impl HostStdioFds {
} }
} }
impl Default for HostStdioFds {
fn default() -> Self {
Self {
stdin_fd: libc::STDIN_FILENO,
stdout_fd: libc::STDOUT_FILENO,
stderr_fd: libc::STDERR_FILENO,
}
}
}
struct StdoutRaw { struct StdoutRaw {
host_fd: i32, host_fd: i32,
} }

@ -30,6 +30,7 @@
#![feature(linkage)] #![feature(linkage)]
#![feature(new_uninit)] #![feature(new_uninit)]
#![feature(raw_ref_op)] #![feature(raw_ref_op)]
#![feature(let_chains)]
#[macro_use] #[macro_use]
extern crate alloc; extern crate alloc;
@ -86,6 +87,7 @@ mod error;
#[macro_use] #[macro_use]
mod net; mod net;
mod blk;
mod config; mod config;
mod entry; mod entry;
mod events; mod events;

@ -24,7 +24,7 @@ use self::wait::{WaitQueue, Waiter};
pub use self::do_exit::handle_force_exit; pub use self::do_exit::handle_force_exit;
pub use self::do_futex::{futex_wait, futex_wake}; pub use self::do_futex::{futex_wait, futex_wake};
pub use self::do_robust_list::RobustListHead; pub use self::do_robust_list::RobustListHead;
pub use self::do_spawn::do_spawn_without_exec; pub use self::do_spawn::{do_spawn, do_spawn_without_exec};
pub use self::do_vfork::{do_vfork, handle_force_stop}; pub use self::do_vfork::{do_vfork, handle_force_stop};
pub use self::do_wait4::idle_reap_zombie_children; pub use self::do_wait4::idle_reap_zombie_children;
pub use self::process::{Process, ProcessFilter, ProcessStatus, IDLE}; pub use self::process::{Process, ProcessFilter, ProcessStatus, IDLE};

@ -309,6 +309,13 @@ impl TimeProvider for OcclumTimeProvider {
} }
} }
impl ext2_rs::TimeProvider for OcclumTimeProvider {
fn now(&self) -> ext2_rs::UnixTime {
let time = do_gettimeofday();
ext2_rs::UnixTime { sec: time.sec as _ }
}
}
// For Timerfd // For Timerfd
#[repr(C)] #[repr(C)]
#[derive(Debug, Default, Copy, Clone)] #[derive(Debug, Default, Copy, Clone)]

@ -21,7 +21,7 @@ pub use self::dcap::{
QuoteGenerator as SgxDCAPQuoteGenerator, QuoteVerifier as SgxDCAPQuoteVerifier, QuoteGenerator as SgxDCAPQuoteGenerator, QuoteVerifier as SgxDCAPQuoteVerifier,
}; };
pub use self::epid::AttestationAgent as SgxEPIDAttestationAgent; pub use self::epid::AttestationAgent as SgxEPIDAttestationAgent;
pub use self::sgx_key::get_key; pub use self::sgx_key::{get_autokey, get_key};
pub use self::sgx_report::{create_report, get_self_target, verify_report}; pub use self::sgx_report::{create_report, get_self_target, verify_report};
pub fn allow_debug() -> bool { pub fn allow_debug() -> bool {

@ -1,6 +1,11 @@
use super::*; use super::*;
use crate::misc::get_random;
use std::io::{Read, Write};
use std::mem::{size_of, transmute};
use std::path::PathBuf;
use std::ptr; use std::ptr;
use std::untrusted::{fs::File, path::PathEx};
pub fn get_key(key_request: &sgx_key_request_t) -> Result<sgx_key_128bit_t> { pub fn get_key(key_request: &sgx_key_request_t) -> Result<sgx_key_128bit_t> {
let mut key = sgx_key_128bit_t::default(); let mut key = sgx_key_128bit_t::default();
@ -14,3 +19,91 @@ pub fn get_key(key_request: &sgx_key_request_t) -> Result<sgx_key_128bit_t> {
} }
} }
} }
pub fn get_autokey(path: &PathBuf) -> Result<sgx_key_128bit_t> {
let mut key_request = sgx_key_request_t::default();
key_request.key_name = SGX_KEYSELECT_SEAL;
key_request.key_policy = SGX_KEYPOLICY_MRSIGNER;
let key_metadata = {
let metadata_path = {
let mut metadata_path = path.clone();
if !metadata_path.is_dir() {
metadata_path = metadata_path.parent().unwrap().to_path_buf();
}
metadata_path.push(KEY_METADATA_FILE_NAME);
metadata_path
};
let load_res = if metadata_path.exists() {
KeyMetadata::load_from(&metadata_path)
} else {
Err(errno!(ENOENT))
};
load_res.unwrap_or_else(|_| {
let key_metadata = KeyMetadata::default();
let _ = key_metadata.persist_to(&metadata_path);
key_metadata
})
};
key_request.key_id = key_metadata.key_id;
key_request.cpu_svn = key_metadata.cpu_svn;
key_request.isv_svn = key_metadata.isv_svn;
key_request.attribute_mask.flags = TSEAL_DEFAULT_FLAGSMASK;
key_request.attribute_mask.xfrm = 0x0;
key_request.misc_mask = TSEAL_DEFAULT_MISCMASK;
get_key(&key_request)
}
const KEY_METADATA_FILE_NAME: &str = "metadata";
const KEY_METADATA_SIZE: usize = size_of::<KeyMetadata>();
#[repr(C)]
struct KeyMetadata {
pub key_id: sgx_key_id_t,
pub cpu_svn: sgx_cpu_svn_t,
pub isv_svn: sgx_isv_svn_t,
}
impl Default for KeyMetadata {
fn default() -> Self {
let key_id = {
let mut key_id = sgx_key_id_t::default();
let _ = get_random(&mut key_id.id);
key_id
};
let report = sgx_tse::rsgx_self_report();
Self {
key_id,
cpu_svn: report.body.cpu_svn,
isv_svn: report.body.isv_svn,
}
}
}
impl KeyMetadata {
pub fn load_from(metadata_path: &PathBuf) -> Result<Self> {
debug_assert!(metadata_path.ends_with(KEY_METADATA_FILE_NAME));
let mut metadata_file = File::open(metadata_path)?;
let mut metadata_buf = [0u8; KEY_METADATA_SIZE];
metadata_file.read(&mut metadata_buf)?;
Ok(Self::from_bytes(metadata_buf))
}
pub fn persist_to(&self, metadata_path: &PathBuf) -> Result<()> {
debug_assert!(metadata_path.ends_with(KEY_METADATA_FILE_NAME));
let mut metadata_file = File::create(metadata_path)?;
metadata_file.write(self.as_bytes())?;
Ok(())
}
fn as_bytes(&self) -> &[u8; KEY_METADATA_SIZE] {
unsafe { transmute::<&Self, &[u8; KEY_METADATA_SIZE]>(self) }
}
fn from_bytes(bytes: [u8; KEY_METADATA_SIZE]) -> Self {
unsafe { transmute::<[u8; KEY_METADATA_SIZE], Self>(bytes) }
}
}

@ -793,6 +793,8 @@ struct OcclumMountOptions {
pub temporary: bool, pub temporary: bool,
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_size: Option<String>, pub cache_size: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub disk_size: Option<String>,
} }
#[inline] #[inline]

@ -318,6 +318,8 @@ cmd_init() {
mkdir -p image/dev mkdir -p image/dev
mkdir -p image/proc mkdir -p image/proc
mkdir -p image/etc mkdir -p image/etc
mkdir -p image/sbin
mkdir -p image/ext2
local occlum_glibc_lib=/opt/occlum/glibc/lib local occlum_glibc_lib=/opt/occlum/glibc/lib
local occlum_glibc_etc=/opt/occlum/glibc/etc local occlum_glibc_etc=/opt/occlum/glibc/etc
if [ -d "$occlum_glibc_lib" ]; then if [ -d "$occlum_glibc_lib" ]; then
@ -429,6 +431,8 @@ cmd_build() {
cp "$instance_dir/init_ra_conf.json" "$instance_dir/initfs/etc/" cp "$instance_dir/init_ra_conf.json" "$instance_dir/initfs/etc/"
fi fi
prepare_ext2_if_enabled
# If sgx mode is changed, build thoroughly again # If sgx mode is changed, build thoroughly again
if [[ -n $SGX_MODE && "$SGX_MODE" != "HW" ]]; then if [[ -n $SGX_MODE && "$SGX_MODE" != "HW" ]]; then
if [ "$(cat $instance_dir/.sgx_mode 2>/dev/null)" != "$SGX_MODE" ]; then if [ "$(cat $instance_dir/.sgx_mode 2>/dev/null)" != "$SGX_MODE" ]; then
@ -468,6 +472,39 @@ cmd_build() {
echo "Built the Occlum image and enclave successfully" echo "Built the Occlum image and enclave successfully"
} }
prepare_ext2_if_enabled() {
if ! jq -e '.mount[] | select(.type == "ext2")' "$instance_dir/Occlum.json" > /dev/null 2>&1; then
return
fi
local mke2fs_path="/usr/sbin/mke2fs"
local occlum_glibc_lib="/opt/occlum/glibc/lib"
local os_lib_path="/usr/lib/x86_64-linux-gnu" # for ubuntu
local os_release=`awk -F= '/^NAME/{print $2}' /etc/os-release`
if [ "$os_release" != "\"Ubuntu\"" ]; then
os_lib_path="/usr/lib64" # for openanolis, alios
fi
if [ -f "$mke2fs_path" ] && [ -d "$os_lib_path" ] && [ -d "$occlum_glibc_lib" ]; then
cp -t "$instance_dir/image/sbin/" "$mke2fs_path"
mkdir -p "$instance_dir/image/$occlum_glibc_lib"
cp -t "$instance_dir/image/$occlum_glibc_lib" \
"$os_lib_path/libext2fs.so.2" \
"$os_lib_path/libcom_err.so.2" \
"$os_lib_path/libblkid.so.1" \
"$os_lib_path/libuuid.so.1" \
"$os_lib_path/libe2p.so.2"
cp -t "$instance_dir/image/lib64/" \
"$occlum_glibc_lib/ld-linux-x86-64.so.2"
ln -sf /lib64/ld-linux-x86-64.so.2 "$instance_dir/image/$occlum_glibc_lib/ld-linux-x86-64.so.2"
cp -t "$instance_dir/image/$occlum_glibc_lib" \
"$occlum_glibc_lib/libc.so.6" \
"$occlum_glibc_lib/libpthread.so.0" \
"$occlum_glibc_lib/libm.so.6"
else
exit_error "Ext2 enabled but mke2fs tool or its libs not found"
fi
}
cmd_run() { cmd_run() {
check_has_built check_has_built