You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by rd...@apache.org on 2022/09/02 12:41:18 UTC

[incubator-teaclave-sgx-sdk] branch v2.0.0-preview updated: Improve SGX Protected FS

This is an automated email from the ASF dual-hosted git repository.

rduan pushed a commit to branch v2.0.0-preview
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave-sgx-sdk.git


The following commit(s) were added to refs/heads/v2.0.0-preview by this push:
     new d893bc45 Improve SGX Protected FS
d893bc45 is described below

commit d893bc456cdd46c0ab56cabb8cd41a4c54d38e9f
Author: volcano <vo...@163.com>
AuthorDate: Fri Sep 2 20:40:47 2022 +0800

    Improve SGX Protected FS
---
 sgx_protected_fs/tfs/src/capi.rs          | 70 +++++++++++++++++++++--
 sgx_protected_fs/tfs/src/fs.rs            | 92 ++++++++++++++++++++++++-------
 sgx_protected_fs/tfs/src/sys/file/mod.rs  | 18 ++++--
 sgx_protected_fs/tfs/src/sys/file/node.rs |  2 +-
 sgx_protected_fs/tfs/src/sys/file/open.rs | 22 +++++++-
 sgx_protected_fs/tfs/src/sys/metadata.rs  | 11 ----
 sgx_protected_fs/tfs/src/sys/mod.rs       |  6 +-
 sgx_protected_fs/ufs/src/lib.rs           |  8 ++-
 8 files changed, 185 insertions(+), 44 deletions(-)

diff --git a/sgx_protected_fs/tfs/src/capi.rs b/sgx_protected_fs/tfs/src/capi.rs
index 595f9224..39d93c45 100644
--- a/sgx_protected_fs/tfs/src/capi.rs
+++ b/sgx_protected_fs/tfs/src/capi.rs
@@ -37,11 +37,19 @@ pub unsafe extern "C" fn sgx_fopen(
     mode: *const c_char,
     key: *const Key128bit,
 ) -> RawProtectedFile {
-    if filename.is_null() || mode.is_null() || key.is_null() {
+    if filename.is_null() || mode.is_null() {
         eos!(EINVAL).set_errno();
         return ptr::null_mut();
     }
 
+    #[cfg(not(feature = "tfs"))]
+    {
+        if key.is_null() {
+            eos!(EINVAL).set_errno();
+            return ptr::null_mut();
+        }
+    }
+
     let name = match CStr::from_ptr(filename).to_str() {
         Ok(name) => name,
         Err(_) => {
@@ -58,8 +66,12 @@ pub unsafe extern "C" fn sgx_fopen(
         }
     };
 
-    let encrypt_mode = EncryptMode::EncryptWithIntegrity(*key);
-    match SgxFile::open(name, &opts, &encrypt_mode) {
+    let encrypt_mode = if key.is_null() {
+        EncryptMode::EncryptAutoKey
+    } else {
+        EncryptMode::EncryptWithIntegrity(*key)
+    };
+    match SgxFile::open(name, &opts, &encrypt_mode, None) {
         Ok(file) => file.into_raw(),
         Err(_) => ptr::null_mut(),
     }
@@ -94,7 +106,7 @@ pub unsafe extern "C" fn sgx_fopen_auto_key(
     };
 
     let encrypt_mode = EncryptMode::EncryptAutoKey;
-    match SgxFile::open(name, &opts, &encrypt_mode) {
+    match SgxFile::open(name, &opts, &encrypt_mode, None) {
         Ok(file) => file.into_raw(),
         Err(_) => ptr::null_mut(),
     }
@@ -128,7 +140,55 @@ pub unsafe extern "C" fn sgx_fopen_integrity_only(
     };
 
     let encrypt_mode = EncryptMode::IntegrityOnly;
-    match SgxFile::open(name, &opts, &encrypt_mode) {
+    match SgxFile::open(name, &opts, &encrypt_mode, None) {
+        Ok(file) => file.into_raw(),
+        Err(_) => ptr::null_mut(),
+    }
+}
+
+/// # Safety
+#[no_mangle]
+pub unsafe extern "C" fn sgx_fopen_ex(
+    filename: *const c_char,
+    mode: *const c_char,
+    key: *const Key128bit,
+    cache_size: u64,
+) -> RawProtectedFile {
+    if filename.is_null() || mode.is_null() || cache_size < fs_imp::DEFAULT_CACHE_SIZE as u64 {
+        eos!(EINVAL).set_errno();
+        return ptr::null_mut();
+    }
+
+    #[cfg(not(feature = "tfs"))]
+    {
+        if key.is_null() {
+            eos!(EINVAL).set_errno();
+            return ptr::null_mut();
+        }
+    }
+
+    let name = match CStr::from_ptr(filename).to_str() {
+        Ok(name) => name,
+        Err(_) => {
+            eos!(EINVAL).set_errno();
+            return ptr::null_mut();
+        }
+    };
+
+    let opts = match parse_mode(CStr::from_ptr(mode)) {
+        Ok(mode) => mode,
+        Err(error) => {
+            error.set_errno();
+            return ptr::null_mut();
+        }
+    };
+
+    let encrypt_mode = if key.is_null() {
+        EncryptMode::EncryptAutoKey
+    } else {
+        EncryptMode::EncryptWithIntegrity(*key)
+    };
+    match SgxFile::open(name, &opts, &encrypt_mode, Some(cache_size as usize)) {
         Ok(file) => file.into_raw(),
         Err(_) => ptr::null_mut(),
     }
diff --git a/sgx_protected_fs/tfs/src/fs.rs b/sgx_protected_fs/tfs/src/fs.rs
index 60e6f21b..c73de67f 100644
--- a/sgx_protected_fs/tfs/src/fs.rs
+++ b/sgx_protected_fs/tfs/src/fs.rs
@@ -41,6 +41,9 @@ cfg_if! {
 #[derive(Clone, Debug)]
 pub struct OpenOptions(fs_imp::OpenOptions);
 
+#[derive(Clone, Debug)]
+pub struct EncryptMode(fs_imp::EncryptMode);
+
 /// A reference to an open Sgxfile on the filesystem.
 ///
 /// An instance of a `SgxFile` can be read and/or written depending on what options
@@ -76,14 +79,14 @@ pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result
     SgxFile::create(path)?.write_all(contents.as_ref())
 }
 
-pub fn read_with_key<P: AsRef<Path>>(path: P, key: &Key128bit) -> io::Result<Vec<u8>> {
+pub fn read_with_key<P: AsRef<Path>>(path: P, key: Key128bit) -> io::Result<Vec<u8>> {
     let mut file = SgxFile::open_with_key(path, key)?;
     let mut bytes = Vec::with_capacity(buffer_capacity_required(&file));
     file.read_to_end(&mut bytes)?;
     Ok(bytes)
 }
 
-pub fn read_to_string_with_key<P: AsRef<Path>>(path: P, key: &Key128bit) -> io::Result<String> {
+pub fn read_to_string_with_key<P: AsRef<Path>>(path: P, key: Key128bit) -> io::Result<String> {
     let mut file = SgxFile::open_with_key(path, key)?;
     let mut string = String::with_capacity(buffer_capacity_required(&file));
     file.read_to_string(&mut string)?;
@@ -92,7 +95,7 @@ pub fn read_to_string_with_key<P: AsRef<Path>>(path: P, key: &Key128bit) -> io::
 
 pub fn write_with_key<P: AsRef<Path>, C: AsRef<[u8]>>(
     path: P,
-    key: &Key128bit,
+    key: Key128bit,
     contents: C,
 ) -> io::Result<()> {
     SgxFile::create_with_key(path, key)?.write_all(contents.as_ref())
@@ -135,19 +138,19 @@ impl SgxFile {
         OpenOptions::new().append(true).open(path.as_ref())
     }
 
-    pub fn open_with_key<P: AsRef<Path>>(path: P, key: &Key128bit) -> io::Result<SgxFile> {
+    pub fn open_with_key<P: AsRef<Path>>(path: P, key: Key128bit) -> io::Result<SgxFile> {
         OpenOptions::new()
             .read(true)
             .open_with_key(path.as_ref(), key)
     }
 
-    pub fn create_with_key<P: AsRef<Path>>(path: P, key: &Key128bit) -> io::Result<SgxFile> {
+    pub fn create_with_key<P: AsRef<Path>>(path: P, key: Key128bit) -> io::Result<SgxFile> {
         OpenOptions::new()
             .write(true)
             .open_with_key(path.as_ref(), key)
     }
 
-    pub fn append_with_key<P: AsRef<Path>>(path: P, key: &Key128bit) -> io::Result<SgxFile> {
+    pub fn append_with_key<P: AsRef<Path>>(path: P, key: Key128bit) -> io::Result<SgxFile> {
         OpenOptions::new()
             .append(true)
             .open_with_key(path.as_ref(), key)
@@ -171,7 +174,37 @@ impl SgxFile {
             .open_integrity_only(path.as_ref())
     }
 
-    pub fn with_options() -> OpenOptions {
+    pub fn open_with<P: AsRef<Path>>(
+        path: P,
+        encrypt_mode: EncryptMode,
+        cache_size: Option<usize>,
+    ) -> io::Result<SgxFile> {
+        OpenOptions::new()
+            .read(true)
+            .open_with(path.as_ref(), encrypt_mode, cache_size)
+    }
+
+    pub fn create_with<P: AsRef<Path>>(
+        path: P,
+        encrypt_mode: EncryptMode,
+        cache_size: Option<usize>,
+    ) -> io::Result<SgxFile> {
+        OpenOptions::new()
+            .write(true)
+            .open_with(path.as_ref(), encrypt_mode, cache_size)
+    }
+
+    pub fn append_with<P: AsRef<Path>>(
+        path: P,
+        encrypt_mode: EncryptMode,
+        cache_size: Option<usize>,
+    ) -> io::Result<SgxFile> {
+        OpenOptions::new()
+            .append(true)
+            .open_with(path.as_ref(), encrypt_mode, cache_size)
+    }
+
+    pub fn options() -> OpenOptions {
         OpenOptions::new()
     }
 
@@ -299,8 +332,8 @@ pub fn export_key<P: AsRef<Path>>(path: P) -> io::Result<Key128bit> {
 }
 
 #[cfg(feature = "tfs")]
-pub fn import_key<P: AsRef<Path>>(path: P, key: &Key128bit) -> io::Result<()> {
-    fs_imp::import_key(path.as_ref(), *key)
+pub fn import_key<P: AsRef<Path>>(path: P, key: Key128bit) -> io::Result<()> {
+    fs_imp::import_key(path.as_ref(), key)
 }
 
 impl OpenOptions {
@@ -342,21 +375,24 @@ impl OpenOptions {
     /// Opens a file at `path` with the options specified by `self`.
     #[cfg(feature = "tfs")]
     pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<SgxFile> {
-        let inner = fs_imp::SgxFile::open(path, &self.0, &fs_imp::EncryptMode::EncryptAutoKey)?;
-        Ok(SgxFile { inner })
+        self.open_with(path, EncryptMode::with_auto_key(), None)
     }
 
-    pub fn open_with_key<P: AsRef<Path>>(&self, path: P, key: &Key128bit) -> io::Result<SgxFile> {
-        let inner = fs_imp::SgxFile::open(
-            path,
-            &self.0,
-            &fs_imp::EncryptMode::EncryptWithIntegrity(*key),
-        )?;
-        Ok(SgxFile { inner })
+    pub fn open_with_key<P: AsRef<Path>>(&self, path: P, key: Key128bit) -> io::Result<SgxFile> {
+        self.open_with(path, EncryptMode::with_user_key(key), None)
     }
 
     pub fn open_integrity_only<P: AsRef<Path>>(&self, path: P) -> io::Result<SgxFile> {
-        let inner = fs_imp::SgxFile::open(path, &self.0, &fs_imp::EncryptMode::IntegrityOnly)?;
+        self.open_with(path, EncryptMode::integrity_only(), None)
+    }
+
+    pub fn open_with<P: AsRef<Path>>(
+        &self,
+        path: P,
+        encrypt_mode: EncryptMode,
+        cache_size: Option<usize>,
+    ) -> io::Result<SgxFile> {
+        let inner = fs_imp::SgxFile::open(path, &self.0, &encrypt_mode.0, cache_size)?;
         Ok(SgxFile { inner })
     }
 }
@@ -366,3 +402,21 @@ impl Default for OpenOptions {
         Self::new()
     }
 }
+
+impl EncryptMode {
+    #[cfg(feature = "tfs")]
+    #[inline]
+    pub fn with_auto_key() -> EncryptMode {
+        EncryptMode(fs_imp::EncryptMode::EncryptAutoKey)
+    }
+
+    #[inline]
+    pub fn with_user_key(key: Key128bit) -> EncryptMode {
+        EncryptMode(fs_imp::EncryptMode::EncryptWithIntegrity(key))
+    }
+
+    #[inline]
+    pub fn integrity_only() -> EncryptMode {
+        EncryptMode(fs_imp::EncryptMode::IntegrityOnly)
+    }
+}
diff --git a/sgx_protected_fs/tfs/src/sys/file/mod.rs b/sgx_protected_fs/tfs/src/sys/file/mod.rs
index 986f8138..162d7d02 100644
--- a/sgx_protected_fs/tfs/src/sys/file/mod.rs
+++ b/sgx_protected_fs/tfs/src/sys/file/mod.rs
@@ -30,6 +30,8 @@ use std::path::Path;
 use std::path::PathBuf;
 use std::sync::Mutex;
 
+pub use open::DEFAULT_CACHE_SIZE;
+
 mod close;
 mod flush;
 mod node;
@@ -43,8 +45,6 @@ pub struct ProtectedFile {
     file: Mutex<FileInner>,
 }
 
-const MAX_PAGES_IN_CACHE: usize = 48;
-
 #[derive(Debug)]
 struct FileInner {
     host_file: HostFile,
@@ -54,6 +54,7 @@ struct FileInner {
     opts: OpenOptions,
     need_writing: bool,
     end_of_file: bool,
+    max_cache_page: usize,
     offset: usize,
     last_error: FsError,
     status: FileStatus,
@@ -62,8 +63,13 @@ struct FileInner {
 }
 
 impl ProtectedFile {
-    pub fn open<P: AsRef<Path>>(path: P, opts: &OpenOptions, mode: &OpenMode) -> FsResult<Self> {
-        let file = FileInner::open(path.as_ref(), opts, mode)?;
+    pub fn open<P: AsRef<Path>>(
+        path: P,
+        opts: &OpenOptions,
+        mode: &OpenMode,
+        cache_size: Option<usize>,
+    ) -> FsResult<Self> {
+        let file = FileInner::open(path.as_ref(), opts, mode, cache_size)?;
         Ok(Self {
             file: Mutex::new(file),
         })
@@ -270,6 +276,7 @@ impl ProtectedFile {
             path.as_ref(),
             &OpenOptions::new().read(true),
             &OpenMode::AutoKey,
+            None,
         )?;
         file.close(CloseMode::Export).map(|key| key.unwrap())
     }
@@ -280,6 +287,7 @@ impl ProtectedFile {
             path.as_ref(),
             &OpenOptions::new().read(true).update(true),
             &OpenMode::ImportKey(key),
+            None,
         )?;
         file.close(CloseMode::Import).map(|_| ())
     }
@@ -418,6 +426,7 @@ impl OpenMode {
 impl From<EncryptMode> for OpenMode {
     fn from(encrypt_mode: EncryptMode) -> OpenMode {
         match encrypt_mode {
+            #[cfg(feature = "tfs")]
             EncryptMode::EncryptAutoKey => Self::AutoKey,
             EncryptMode::EncryptWithIntegrity(key) => Self::UserKey(key),
             EncryptMode::IntegrityOnly => Self::IntegrityOnly,
@@ -428,6 +437,7 @@ impl From<EncryptMode> for OpenMode {
 impl From<&EncryptMode> for OpenMode {
     fn from(encrypt_mode: &EncryptMode) -> OpenMode {
         match encrypt_mode {
+            #[cfg(feature = "tfs")]
             EncryptMode::EncryptAutoKey => Self::AutoKey,
             EncryptMode::EncryptWithIntegrity(key) => Self::UserKey(*key),
             EncryptMode::IntegrityOnly => Self::IntegrityOnly,
diff --git a/sgx_protected_fs/tfs/src/sys/file/node.rs b/sgx_protected_fs/tfs/src/sys/file/node.rs
index b3f53914..24ad03c4 100644
--- a/sgx_protected_fs/tfs/src/sys/file/node.rs
+++ b/sgx_protected_fs/tfs/src/sys/file/node.rs
@@ -187,7 +187,7 @@ impl FileInner {
     }
 
     fn shrink_cache(&mut self) -> FsResult {
-        while self.cache.len() > super::MAX_PAGES_IN_CACHE {
+        while self.cache.len() > self.max_cache_page {
             let node = self.cache.back().ok_or(SgxStatus::Unexpected)?;
             if !node.borrow().need_writing {
                 let _node = self.cache.pop_back();
diff --git a/sgx_protected_fs/tfs/src/sys/file/open.rs b/sgx_protected_fs/tfs/src/sys/file/open.rs
index 193d8c9d..ddd1f8b8 100644
--- a/sgx_protected_fs/tfs/src/sys/file/open.rs
+++ b/sgx_protected_fs/tfs/src/sys/file/open.rs
@@ -28,12 +28,29 @@ use crate::sys::node::{FileNode, FileNodeRef};
 use sgx_types::error::errno::*;
 use sgx_types::error::SgxStatus;
 use sgx_types::memeq::ConstTimeEq;
+use sgx_types::metadata::SE_PAGE_SIZE;
 use sgx_types::types::Key128bit;
 use std::borrow::ToOwned;
 use std::path::Path;
 
+macro_rules! is_page_aligned {
+    ($num:expr) => {
+        $num & (SE_PAGE_SIZE - 1) == 0
+    };
+}
+
+pub const DEFAULT_CACHE_SIZE: usize = 48 * SE_PAGE_SIZE;
+
 impl FileInner {
-    pub fn open(path: &Path, opts: &OpenOptions, mode: &OpenMode) -> FsResult<Self> {
+    pub fn open(
+        path: &Path,
+        opts: &OpenOptions,
+        mode: &OpenMode,
+        cache_size: Option<usize>,
+    ) -> FsResult<Self> {
+        let cache_size = cache_size.unwrap_or(DEFAULT_CACHE_SIZE);
+        ensure!(is_page_aligned!(cache_size), eos!(EINVAL));
+
         let file_name = path.file_name().ok_or(EINVAL)?.to_str().ok_or(EINVAL)?;
         Self::check_open_param(path, file_name, opts, mode)?;
 
@@ -86,11 +103,12 @@ impl FileInner {
             opts: *opts,
             need_writing,
             end_of_file: false,
+            max_cache_page: cache_size,
             offset,
             last_error: esgx!(SgxStatus::Success),
             status: FileStatus::NotInitialized,
             recovery_path,
-            cache: LruCache::new(super::MAX_PAGES_IN_CACHE),
+            cache: LruCache::new(cache_size),
         };
 
         protected_file.status = FileStatus::Ok;
diff --git a/sgx_protected_fs/tfs/src/sys/metadata.rs b/sgx_protected_fs/tfs/src/sys/metadata.rs
index 439012cb..42c14dc0 100644
--- a/sgx_protected_fs/tfs/src/sys/metadata.rs
+++ b/sgx_protected_fs/tfs/src/sys/metadata.rs
@@ -20,7 +20,6 @@ use crate::sys::file::OpenMode;
 use crate::sys::host::HostFs;
 use crate::sys::keys::{DeriveKey, KeyType, RestoreKey};
 use crate::sys::node::{META_DATA_PHY_NUM, NODE_SIZE};
-use crate::sys::EncryptMode;
 use sgx_crypto::aes::gcm::{Aad, AesGcm, Nonce};
 use sgx_types::error::SgxStatus;
 use sgx_types::types::{Attributes, CpuSvn, Key128bit, KeyId, Mac128bit};
@@ -74,16 +73,6 @@ impl From<&OpenMode> for EncryptFlags {
     }
 }
 
-impl From<&EncryptMode> for EncryptFlags {
-    fn from(mode: &EncryptMode) -> Self {
-        match mode {
-            EncryptMode::EncryptAutoKey => Self::AutoKey,
-            EncryptMode::EncryptWithIntegrity(_) => Self::UserKey,
-            EncryptMode::IntegrityOnly => Self::IntegrityOnly,
-        }
-    }
-}
-
 #[derive(Clone, Copy, Debug, Default)]
 #[repr(C, packed)]
 pub struct MetadataPlain {
diff --git a/sgx_protected_fs/tfs/src/sys/mod.rs b/sgx_protected_fs/tfs/src/sys/mod.rs
index 770bccf6..8744cd2a 100644
--- a/sgx_protected_fs/tfs/src/sys/mod.rs
+++ b/sgx_protected_fs/tfs/src/sys/mod.rs
@@ -23,6 +23,8 @@ use std::io::{Result, SeekFrom};
 use std::mem::ManuallyDrop;
 use std::path::Path;
 
+pub use file::DEFAULT_CACHE_SIZE;
+
 #[macro_use]
 pub(crate) mod error;
 #[macro_use]
@@ -39,6 +41,7 @@ pub struct OpenOptions(file_imp::OpenOptions);
 
 #[derive(Clone, Debug)]
 pub enum EncryptMode {
+    #[cfg(feature = "tfs")]
     EncryptAutoKey,
     EncryptWithIntegrity(Key128bit),
     IntegrityOnly,
@@ -89,9 +92,10 @@ impl SgxFile {
         path: P,
         opts: &OpenOptions,
         encrypt_mode: &EncryptMode,
+        cache_size: Option<usize>,
     ) -> Result<SgxFile> {
         opts.check_access_mode()?;
-        ProtectedFile::open(path, &opts.0, &From::from(encrypt_mode))
+        ProtectedFile::open(path, &opts.0, &encrypt_mode.into(), cache_size)
             .map_err(|e| {
                 e.set_errno();
                 e.to_io_error()
diff --git a/sgx_protected_fs/ufs/src/lib.rs b/sgx_protected_fs/ufs/src/lib.rs
index 6ff08118..5054ee78 100644
--- a/sgx_protected_fs/ufs/src/lib.rs
+++ b/sgx_protected_fs/ufs/src/lib.rs
@@ -110,7 +110,12 @@ impl HostFile {
     }
 
     pub fn flush(&mut self) -> OsResult {
-        self.stream.flush()
+        self.stream.flush()?;
+        if unsafe { libc::fsync(self.fd) } == 0 {
+            Ok(())
+        } else {
+            Err(errno())
+        }
     }
 
     pub fn size(&self) -> OsResult<usize> {
@@ -144,6 +149,7 @@ impl Drop for HostFile {
     fn drop(&mut self) {
         unsafe {
             libc::flock(self.fd, libc::LOCK_UN);
+            libc::fsync(self.fd);
         }
     }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org