diff --git a/sgx_trts/src/emm/alloc.rs b/sgx_trts/src/emm/alloc.rs index d8e67938..bc1e7f70 100644 --- a/sgx_trts/src/emm/alloc.rs +++ b/sgx_trts/src/emm/alloc.rs @@ -22,13 +22,13 @@ use intrusive_collections::singly_linked_list::{Link, SinglyLinkedList}; use intrusive_collections::UnsafeRef; use sgx_tlibc_sys::ENOMEM; +use crate::sync::Once; use crate::sync::SpinMutex as Mutex; use core::alloc::{AllocError, Allocator, Layout}; use core::any::Any; use core::mem::size_of; use core::mem::MaybeUninit; use core::ptr::NonNull; -use spin::Once; use super::ema::EmaOptions; use super::page::AllocFlags; @@ -64,21 +64,21 @@ static RSRV_ALLOCATOR: Once> = Once::new(); /// Init lowest level static memory allocator pub fn init_static_alloc() { - STATIC.call_once(|| { + let _ = STATIC.call_once(|| { let static_alloc = LockedHeap::empty(); unsafe { static_alloc .lock() .init(STATIC_MEM.as_ptr() as usize, STATIC_MEM_SIZE) }; - static_alloc + Ok(static_alloc) }); } /// Init reserve memory allocator /// init_reserve_alloc() need to be called after init_static_alloc() pub fn init_reserve_alloc() { - RSRV_ALLOCATOR.call_once(|| Mutex::new(Reserve::new(INIT_MEM_SIZE))); + let _ = RSRV_ALLOCATOR.call_once(|| Ok(Mutex::new(Reserve::new(INIT_MEM_SIZE)))); } pub trait EmmAllocator: Allocator + Any { diff --git a/sgx_trts/src/emm/vmmgr.rs b/sgx_trts/src/emm/vmmgr.rs index 767d54b7..072dd334 100644 --- a/sgx_trts/src/emm/vmmgr.rs +++ b/sgx_trts/src/emm/vmmgr.rs @@ -15,6 +15,7 @@ // specific language governing permissions and limitations // under the License.. +use crate::sync::Once; use crate::{ arch::{SE_PAGE_SHIFT, SE_PAGE_SIZE}, emm::{PageType, ProtFlags}, @@ -28,7 +29,6 @@ use intrusive_collections::{ }; use sgx_tlibc_sys::{EEXIST, EINVAL, ENOMEM, EPERM}; use sgx_types::error::OsResult; -use spin::Once; use super::{ alloc::AllocType, @@ -51,7 +51,7 @@ pub(crate) static VMMGR: Once> = Once::new(); /// Initialize range management pub fn init_vmmgr() { - VMMGR.call_once(|| SpinReentrantMutex::new(VmMgr::new())); + let _ = VMMGR.call_once(|| Ok(SpinReentrantMutex::new(VmMgr::new()))); } pub fn mm_init_static_region(options: &EmaOptions) -> OsResult { diff --git a/sgx_trts/src/se/report.rs b/sgx_trts/src/se/report.rs index 2f807949..0d21b221 100644 --- a/sgx_trts/src/se/report.rs +++ b/sgx_trts/src/se/report.rs @@ -26,15 +26,11 @@ use core::ptr; use sgx_types::error::{SgxResult, SgxStatus}; use sgx_types::marker::ContiguousMemory; use sgx_types::types::{ - Attributes, AttributesFlags, ConfigId, CpuSvn, Key128bit, KeyId, KeyName, KeyRequest, Mac, - Measurement, MiscSelect, Report, Report2Mac, ReportBody, ReportData, TargetInfo, + Key128bit, KeyName, KeyRequest, Mac, Report, Report2Mac, ReportBody, ReportData, TargetInfo, }; use sgx_types::types::{ - CONFIGID_SIZE, CPUSVN_SIZE, HASH_SIZE, ISVEXT_PROD_ID_SIZE, ISV_FAMILY_ID_SIZE, KEYID_SIZE, - MAC_SIZE, REPORT2_MAC_RESERVED1_BYTES, REPORT2_MAC_RESERVED2_BYTES, - REPORT_BODY_RESERVED1_BYTES, REPORT_BODY_RESERVED2_BYTES, REPORT_BODY_RESERVED3_BYTES, - REPORT_BODY_RESERVED4_BYTES, REPORT_DATA_SIZE, TEE_REPORT2_SUBTYPE, TEE_REPORT2_TYPE, - TEE_REPORT2_VERSION, TEE_REPORT2_VERSION_SERVICETD, + REPORT2_MAC_RESERVED1_BYTES, REPORT2_MAC_RESERVED2_BYTES, TEE_REPORT2_SUBTYPE, + TEE_REPORT2_TYPE, TEE_REPORT2_VERSION, TEE_REPORT2_VERSION_SERVICETD, }; #[repr(C, align(128))] @@ -58,51 +54,11 @@ unsafe impl ContiguousMemory for AlignTargetInfo {} unsafe impl ContiguousMemory for AlignReport {} unsafe impl ContiguousMemory for AlignReport2Mac {} -static SELF_REPORT: Once = Once::new(); -static mut REPORT: AlignReport = AlignReport(Report { - body: ReportBody { - cpu_svn: CpuSvn { - svn: [0; CPUSVN_SIZE], - }, - misc_select: MiscSelect::empty(), - reserved1: [0; REPORT_BODY_RESERVED1_BYTES], - isv_ext_prod_id: [0; ISVEXT_PROD_ID_SIZE], - attributes: Attributes { - flags: AttributesFlags::empty(), - xfrm: 0, - }, - mr_enclave: Measurement { m: [0; HASH_SIZE] }, - reserved2: [0; REPORT_BODY_RESERVED2_BYTES], - mr_signer: Measurement { m: [0; HASH_SIZE] }, - reserved3: [0; REPORT_BODY_RESERVED3_BYTES], - config_id: ConfigId { - id: [0; CONFIGID_SIZE], - }, - isv_prod_id: 0, - isv_svn: 0, - config_svn: 0, - reserved4: [0; REPORT_BODY_RESERVED4_BYTES], - isv_family_id: [0; ISV_FAMILY_ID_SIZE], - report_data: ReportData { - d: [0; REPORT_DATA_SIZE], - }, - }, - key_id: KeyId { - id: [0_u8; KEYID_SIZE], - }, - mac: [0_u8; MAC_SIZE], -}); +static REPORT: Once = Once::new(); impl AlignReport { pub fn get_self() -> &'static AlignReport { - unsafe { - let _ = SELF_REPORT.call_once(|| { - let report = AlignReport::for_self()?; - REPORT = report; - Ok(()) - }); - &REPORT - } + REPORT.call_once(|| AlignReport::for_self()).unwrap() } pub fn for_self() -> SgxResult { diff --git a/sgx_trts/src/sync/once.rs b/sgx_trts/src/sync/once.rs index 3261f011..14424385 100644 --- a/sgx_trts/src/sync/once.rs +++ b/sgx_trts/src/sync/once.rs @@ -16,46 +16,94 @@ // under the License.. use crate::sync::{SpinMutex, SpinMutexGuard}; -use core::sync::atomic::{AtomicUsize, Ordering}; +use core::{ + cell::UnsafeCell, + mem::MaybeUninit, + sync::atomic::{AtomicUsize, Ordering}, +}; use sgx_types::error::SgxResult; -pub struct Once { +pub struct Once { lock: SpinMutex<()>, state: AtomicUsize, + data: UnsafeCell>, } -unsafe impl Sync for Once {} -unsafe impl Send for Once {} +impl Default for Once { + fn default() -> Self { + Self::new() + } +} + +unsafe impl Sync for Once {} +unsafe impl Send for Once {} const INCOMPLETE: usize = 0x0; const COMPLETE: usize = 0x1; -impl Once { - pub const fn new() -> Once { - Once { - lock: SpinMutex::new(()), - state: AtomicUsize::new(INCOMPLETE), - } +impl Once { + /// Initialization constant of [`Once`]. + #[allow(clippy::declare_interior_mutable_const)] + pub const INIT: Self = Self { + lock: SpinMutex::new(()), + state: AtomicUsize::new(INCOMPLETE), + data: UnsafeCell::new(MaybeUninit::uninit()), + }; + + /// Creates a new [`Once`]. + pub const fn new() -> Self { + Self::INIT } pub fn lock(&self) -> SpinMutexGuard<()> { self.lock.lock() } - pub fn call_once(&self, init: F) -> SgxResult + pub fn call_once(&self, init: F) -> SgxResult<&T> where - F: FnOnce() -> SgxResult, + F: FnOnce() -> SgxResult, { if self.is_completed() { - return Ok(()); + return Ok(unsafe { + // SAFETY: The status is Complete + self.force_get() + }); } let _guard = self.lock.lock(); if !self.is_completed() { - init()?; + let val = init()?; + unsafe { + (*self.data.get()).as_mut_ptr().write(val); + } self.state.store(COMPLETE, Ordering::Release); } - Ok(()) + unsafe { Ok(self.force_get()) } + } + + /// Returns a reference to the inner value if the [`Once`] has been initialized. + pub fn get(&self) -> Option<&T> { + if self.state.load(Ordering::Acquire) == COMPLETE { + Some(unsafe { self.force_get() }) + } else { + None + } + } + + /// Get a reference to the initialized instance. Must only be called once COMPLETE. + unsafe fn force_get(&self) -> &T { + // SAFETY: + // * `UnsafeCell`/inner deref: data never changes again + // * `MaybeUninit`/outer deref: data was initialized + &*(*self.data.get()).as_ptr() + } + + /// Get a reference to the initialized instance. Must only be called once COMPLETE. + unsafe fn force_get_mut(&mut self) -> &mut T { + // SAFETY: + // * `UnsafeCell`/inner deref: data never changes again + // * `MaybeUninit`/outer deref: data was initialized + &mut *(*self.data.get()).as_mut_ptr() } #[inline]