From 85d6977118dec6bc8ec392ddd795b3dfc0927a97 Mon Sep 17 00:00:00 2001 From: LI Qing Date: Fri, 3 Sep 2021 10:51:10 +0800 Subject: [PATCH] Modify the statfs on SEFS or UnionFS with ocall --- src/Enclave.edl | 2 + src/libos/include/edl/occlum_edl_types.h | 17 ++++++- src/libos/src/fs/fs_ops/statfs.rs | 61 ++++++++++++++++++++++-- src/pal/include/edl/occlum_edl_types.h | 1 + src/pal/src/ocalls/fs.c | 5 ++ 5 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/Enclave.edl b/src/Enclave.edl index 3b0a9e0f..48f6d26d 100644 --- a/src/Enclave.edl +++ b/src/Enclave.edl @@ -153,6 +153,8 @@ enclave { void occlum_ocall_sync(void); + int occlum_ocall_statfs([in, string] const char* path, [out] struct statfs* buf) propagate_errno; + void* occlum_ocall_posix_memalign(size_t alignment, size_t size); void occlum_ocall_free([user_check] void* ptr); diff --git a/src/libos/include/edl/occlum_edl_types.h b/src/libos/include/edl/occlum_edl_types.h index 3a749cb9..72676baa 100644 --- a/src/libos/include/edl/occlum_edl_types.h +++ b/src/libos/include/edl/occlum_edl_types.h @@ -19,7 +19,7 @@ struct occlum_stdio_fds { int stderr_fd; }; -typedef struct _timespec{ +struct _timespec{ time_t tv_sec; syscall_slong_t tv_nsec; }; @@ -34,4 +34,19 @@ typedef struct { unsigned long fds_bits[FD_SETSIZE / 8 / sizeof(long)]; } fd_set; +struct statfs { + unsigned long f_type; + unsigned long f_bsize; + unsigned long f_blocks; + unsigned long f_bfree; + unsigned long f_bavail; + unsigned long f_files; + unsigned long f_ffree; + int f_fsid[2]; + unsigned long f_namelen; + unsigned long f_frsize; + unsigned long f_flags; + unsigned long f_spare[4]; +}; + #endif /* __OCCLUM_EDL_TYPES_H__ */ diff --git a/src/libos/src/fs/fs_ops/statfs.rs b/src/libos/src/fs/fs_ops/statfs.rs index 983938b2..1b1d47b5 100644 --- a/src/libos/src/fs/fs_ops/statfs.rs +++ b/src/libos/src/fs/fs_ops/statfs.rs @@ -1,11 +1,15 @@ use super::*; use rcore_fs::vfs::FsInfo; +use std::ffi::CString; pub fn do_fstatfs(fd: FileDesc) -> Result { debug!("fstatfs: fd: {}", fd); let file_ref = current!().file(fd)?; - let statfs = Statfs::from(file_ref.fs()?.info()); + let statfs = { + let fs_info = file_ref.fs()?.info(); + do_statfs_inner(fs_info)? + }; trace!("fstatfs result: {:?}", statfs); Ok(statfs) } @@ -18,12 +22,28 @@ pub fn do_statfs(path: &str) -> Result { let fs = current.fs().read().unwrap(); fs.lookup_inode(path)? }; - let statfs = Statfs::from(inode.fs().info()); + let statfs = { + let fs_info = inode.fs().info(); + do_statfs_inner(fs_info)? + }; trace!("statfs result: {:?}", statfs); Ok(statfs) } -#[derive(Debug)] +fn do_statfs_inner(fs_info: FsInfo) -> Result { + let statfs = if fs_info.magic == rcore_fs_unionfs::UNIONFS_MAGIC + || fs_info.magic == rcore_fs_sefs::SEFS_MAGIC as usize + { + let mut host_statfs = host_statfs()?; + host_statfs.f_type = fs_info.magic; + host_statfs + } else { + Statfs::from(fs_info) + }; + Ok(statfs) +} + +#[derive(Default, Debug)] #[repr(C)] pub struct Statfs { /// Type of filesystem @@ -52,6 +72,21 @@ pub struct Statfs { f_spare: [usize; 4], } +impl Statfs { + fn validate(&self) -> Result<()> { + if self.f_blocks < self.f_bfree || self.f_blocks < self.f_bavail { + return_errno!(EINVAL, "invalid blocks"); + } + if self.f_files < self.f_ffree { + return_errno!(EINVAL, "invalid inodes"); + } + if self.f_bsize == 0 || self.f_namelen == 0 || self.f_frsize == 0 { + return_errno!(EINVAL, "invalid non-zero fields"); + } + Ok(()) + } +} + impl From for Statfs { fn from(info: FsInfo) -> Self { Self { @@ -78,3 +113,23 @@ impl From for Statfs { } } } + +fn host_statfs() -> Result { + extern "C" { + fn occlum_ocall_statfs(ret: *mut i32, path: *const i8, buf: *mut Statfs) -> sgx_status_t; + } + + let mut ret: i32 = 0; + let mut statfs: Statfs = Default::default(); + let host_dir = unsafe { CString::new(INSTANCE_DIR.as_bytes()).unwrap() }; + let sgx_status = unsafe { occlum_ocall_statfs(&mut ret, host_dir.as_ptr(), &mut statfs) }; + assert!(sgx_status == sgx_status_t::SGX_SUCCESS); + assert!(ret == 0 || libc::errno() == Errno::EINTR as i32); + if ret != 0 { + return_errno!(EINTR, "failed to get host statfs"); + } + + // do sanity check + statfs.validate().expect("invalid statfs"); + Ok(statfs) +} diff --git a/src/pal/include/edl/occlum_edl_types.h b/src/pal/include/edl/occlum_edl_types.h index 8994d714..1477cfd4 100644 --- a/src/pal/include/edl/occlum_edl_types.h +++ b/src/pal/include/edl/occlum_edl_types.h @@ -5,6 +5,7 @@ #include // import fd_set #include // import struct timeval #include // import struct iovec +#include // import struct statfs #include // import occlum_stdio_fds #endif /* __OCCLUM_EDL_TYPES__ */ diff --git a/src/pal/src/ocalls/fs.c b/src/pal/src/ocalls/fs.c index 7b7ccf6d..ac6dabab 100644 --- a/src/pal/src/ocalls/fs.c +++ b/src/pal/src/ocalls/fs.c @@ -3,6 +3,7 @@ #include #include #include +#include void occlum_ocall_sync(void) { sync(); @@ -41,3 +42,7 @@ int occlum_ocall_ioctl(int fd, int request, void *arg, size_t len) { return ioctl(fd, request, arg); } + +int occlum_ocall_statfs(const char *path, struct statfs *buf) { + return statfs(path, buf); +} \ No newline at end of file