From 2897ceb379b217c995793ae803897a523942a8e7 Mon Sep 17 00:00:00 2001 From: ClawSeven Date: Mon, 26 Jun 2023 17:40:41 +0800 Subject: [PATCH] Implement memory range transition and management --- sgx_trts/Cargo.toml | 3 +- sgx_trts/src/emm/bitmap.rs | 8 +-- sgx_trts/src/emm/ema.rs | 64 ++++++++++-------- sgx_trts/src/emm/interior.rs | 127 ++++++++++++++++++++++++++++------- sgx_trts/src/emm/user.rs | 41 ++++++++--- sgx_trts/src/lib.rs | 1 + 6 files changed, 175 insertions(+), 69 deletions(-) diff --git a/sgx_trts/Cargo.toml b/sgx_trts/Cargo.toml index d1e2cb4e2..bc9df5d15 100644 --- a/sgx_trts/Cargo.toml +++ b/sgx_trts/Cargo.toml @@ -39,7 +39,8 @@ hyper = ["sgx_types/hyper"] sgx_types = { path = "../sgx_types" } sgx_crypto_sys = { path = "../sgx_crypto/sgx_crypto_sys" } sgx_tlibc_sys = { path = "../sgx_libc/sgx_tlibc_sys" } -intrusive-collections = "0.9.5" + +intrusive-collections = { git = "https://github.com/ClawSeven/intrusive-rs.git", version = "0.9.5" } buddy_system_allocator = "0.9.0" spin = "0.9.4" bitflags = "1.3" diff --git a/sgx_trts/src/emm/bitmap.rs b/sgx_trts/src/emm/bitmap.rs index 5a7e1e370..2acd58e82 100644 --- a/sgx_trts/src/emm/bitmap.rs +++ b/sgx_trts/src/emm/bitmap.rs @@ -99,10 +99,10 @@ impl BitArray { break; } } - true_range.push((start,end)); + true_range.push((start, end)); } - return true_range; + return true_range; } /// Set the value of the bit at a given index. @@ -155,6 +155,4 @@ impl BitArray { } } - - -// FIXME: add more unit test \ No newline at end of file +// FIXME: add more unit test diff --git a/sgx_trts/src/emm/ema.rs b/sgx_trts/src/emm/ema.rs index cee7e1516..65c466a99 100644 --- a/sgx_trts/src/emm/ema.rs +++ b/sgx_trts/src/emm/ema.rs @@ -103,38 +103,33 @@ where } } - // Returns a newly allocated ema in charging of the memory in the range [addr, len). - // After the call, the original ema will be left containing the elements [0, addr) + // Returns a newly allocated ema in charging of the memory in the range [addr, len). + // After the call, the original ema will be left containing the elements [0, addr) // with its previous capacity unchanged. - pub fn split(&mut self, addr: usize) -> SgxResult,A>> { + pub fn split(&mut self, addr: usize) -> SgxResult, A>> { let l_start = self.start; let l_length = addr - l_start; let r_start = addr; let r_length = (self.start + self.length) - addr; - let new_bitarray = match &mut self.eaccept_map{ + let new_bitarray = match &mut self.eaccept_map { Some(bitarray) => { let pos = (addr - self.start) >> crate::arch::SE_PAGE_SHIFT; // split self.eaccept_map Some(bitarray.split(pos)?) } - None => { - None - } + None => None, }; - + // 这里之后可以优化 // 1. self.clone() 会把原有的bitmap重新alloc并复制一份,但其实clone之后这里是None即可 // 2. 使用Box::new_in 会把 self.clone() 这部分在栈上的数据再拷贝一份到Box新申请的内存区域 - let mut new_ema: Box,A> = Box::new_in( - self.clone(), - self.alloc.clone() - ); + let mut new_ema: Box, A> = Box::new_in(self.clone(), self.alloc.clone()); self.start = l_start; self.length = l_length; - + new_ema.start = r_start; new_ema.length = r_length; new_ema.eaccept_map = new_bitarray; @@ -145,7 +140,11 @@ where // If the previous ema is divided into three parts -> (left ema, middle ema, right ema), return (middle ema, right ema). // If the previous ema is divided into two parts -> (left ema, right ema) // end split: return (None, right ema), start split: return (left ema, None) - fn split_into_three(&mut self, start: usize, length: usize) -> SgxResult<(Option,A>>, Option,A>>)> { + fn split_into_three( + &mut self, + start: usize, + length: usize, + ) -> SgxResult<(Option, A>>, Option, A>>)> { if start > self.start { let mut new_ema = self.split(start)?; if new_ema.start + new_ema.length > start + length { @@ -260,8 +259,10 @@ where /// uncommit EPC page pub fn uncommit(&mut self, start: usize, length: usize, prot: ProtFlags) -> SgxResult { // need READ for trimming - ensure!(self.info.prot != ProtFlags::NONE && self.eaccept_map.is_some(), - SgxStatus::InvalidParameter); + ensure!( + self.info.prot != ProtFlags::NONE && self.eaccept_map.is_some(), + SgxStatus::InvalidParameter + ); if self.alloc_flags.contains(AllocFlags::RESERVED) { return Ok(()); @@ -303,21 +304,23 @@ where } let block_length = block_end - block_start; - perm::modify_ocall(block_start, block_length, - PageInfo { + perm::modify_ocall( + block_start, + block_length, + PageInfo { typ: self.info.typ, prot, }, - PageInfo { + PageInfo { typ: PageType::Trim, prot, }, )?; let pages = PageRange::new( - block_start, - block_length / crate::arch::SE_PAGE_SIZE, - trim_info + block_start, + block_length / crate::arch::SE_PAGE_SIZE, + trim_info, )?; let init_idx = (block_start - self.start) >> crate::arch::SE_PAGE_SHIFT; @@ -328,12 +331,14 @@ where } // eaccept trim notify - perm::modify_ocall(block_start, block_length, - PageInfo { + perm::modify_ocall( + block_start, + block_length, + PageInfo { typ: PageType::Trim, prot, }, - PageInfo { + PageInfo { typ: PageType::Trim, prot, }, @@ -401,7 +406,7 @@ where )?; } - Ok(()) + Ok(()) } pub fn dealloc(&mut self) -> SgxResult { @@ -425,6 +430,10 @@ where self.start } + pub fn len(&self) -> usize { + self.length + } + // get and set attributes pub fn set_flags(flags: AllocFlags) -> SgxResult<()> { todo!() @@ -443,7 +452,7 @@ where } } -// +// // intrusive_adapter!(pub RegEmaAda = Box, ResAlloc>: EMA { link: LinkedListLink }); // regular ema adapter @@ -451,4 +460,3 @@ intrusive_adapter!(pub RegEmaAda = Box>: EMA { link: Lin // reserve ema adapter intrusive_adapter!(pub ResEmaAda = Box>: EMA { link: LinkedListLink }); - diff --git a/sgx_trts/src/emm/interior.rs b/sgx_trts/src/emm/interior.rs index daca9dd47..cd4767bab 100644 --- a/sgx_trts/src/emm/interior.rs +++ b/sgx_trts/src/emm/interior.rs @@ -17,6 +17,7 @@ use buddy_system_allocator::LockedHeap; use intrusive_collections::intrusive_adapter; +use intrusive_collections::linked_list::CursorMut; use intrusive_collections::{LinkedList, LinkedListLink}; use alloc::boxed::Box; @@ -30,8 +31,9 @@ use spin::{Mutex, Once}; use sgx_types::error::{SgxResult, SgxStatus}; use sgx_types::types::ProtectPerm; +use crate::emm::alloc::ResAlloc; use crate::emm::ema::EMA; -use crate::emm::user::{USER_RANGE, self, is_within_user_range}; +use crate::emm::user::{self, is_within_rts_range, is_within_user_range, USER_RANGE}; use crate::enclave::is_within_enclave; use super::ema::ResEmaAda; @@ -40,7 +42,7 @@ const STATIC_MEM_SIZE: usize = 65536; /// first level: static memory static STATIC: LockedHeap<32> = LockedHeap::empty(); - + static mut STATIC_MEM: [u8; STATIC_MEM_SIZE] = [0; STATIC_MEM_SIZE]; pub fn init() { @@ -185,57 +187,130 @@ impl Reserve { todo!() } + fn search_ema_range( + &mut self, + addr: usize, + len: usize, + ) -> SgxResult<(Box>, usize)> { + let mut cursor: CursorMut<'_, ResEmaAda> = self.emas.front_mut(); + let ema_box = cursor.as_cursor().clone_pointer().unwrap(); + + let ptr = Box::into_raw(ema_box) as *const EMA; + + let cursor_mut = unsafe { self.emas.cursor_mut_from_ptr(ptr) }; + + todo!() + } + + // Find a free space at addr with 'len' bytes in reserve region, + // the request space mustn't intersect with existed ema node. + // If success, return the next ema cursor. + fn find_free_region_at( + &mut self, + addr: usize, + len: usize, + ) -> SgxResult> { + if !is_within_enclave(addr as *const u8, len) || !is_within_rts_range(addr, len) { + return Err(SgxStatus::InvalidParameter); + } + + let mut cursor: CursorMut<'_, ResEmaAda> = self.emas.front_mut(); + while !cursor.is_null() { + let start_curr = cursor.get().map(|ema| ema.start()).unwrap(); + let end_curr = start_curr + cursor.get().map(|ema| ema.len()).unwrap(); + if start_curr >= addr + len { + return Ok(cursor); + } + + if addr >= end_curr { + cursor.move_next(); + } else { + break; + } + } + + // means addr is larger than the end of the last ema node + if cursor.is_null() { + return Ok(cursor); + } + + return Err(SgxStatus::InvalidParameter); + } + // Find a free space of size at least 'size' bytes in reserve region, // return the start address - fn find_free_region(&mut self, len: usize, align: usize) -> SgxResult { + fn find_free_region( + &mut self, + len: usize, + align: usize, + ) -> SgxResult<(usize, CursorMut<'_, ResEmaAda>)> { let user_range = USER_RANGE.get().unwrap(); let user_base = user_range.start; let user_end = user_range.end; - // no ema in list - if self.emas.is_empty() { - let mut addr = 0; + let mut addr = 0; + let mut cursor: CursorMut<'_, ResEmaAda> = self.emas.front_mut(); + // no ema in list + if cursor.is_null() { if user_base >= len { addr = trim_to!(user_base - len, align); if is_within_enclave(addr as *const u8, len) { - return Ok(addr); + return Ok((addr, cursor)); } } else { addr = round_to!(user_end, align); if is_within_enclave(addr as *const u8, len) { - return Ok(addr); + return Ok((addr, cursor)); } } return Err(SgxStatus::InvalidParameter); } + let mut cursor_next = cursor.peek_next(); - let mut cursor = self.emas.cursor_mut(); - while !cursor.is_null() { - let curr_end = cursor.get() - .map(|ema| ema.aligned_end(align)).unwrap(); + // ema is_null means pointing to the Null object, not means this ema is empty + while !cursor_next.is_null() { + let curr_end = cursor.get().map(|ema| ema.aligned_end(align)).unwrap(); - cursor.move_next(); - if cursor.is_null() { - break; - } - - let next_start = cursor.get() - .map(|ema| ema.start()).unwrap(); - - if curr_end < next_start { - let free_size = next_start - curr_end; - // 这里或许得用is_within_rts - if free_size < len && is_within_enclave(curr_end as *const u8, len){ - return Ok(curr_end); + let start_next = cursor_next.get().map(|ema| ema.start()).unwrap(); + + if curr_end < start_next { + let free_size = start_next - curr_end; + if free_size < len && is_within_rts_range(curr_end, len) { + cursor.move_next(); + return Ok((curr_end, cursor)); } } cursor.move_next(); + cursor_next = cursor.peek_next(); } + addr = cursor.get().map(|ema| ema.aligned_end(align)).unwrap(); - todo!() + if is_within_enclave(addr as *const u8, len) && is_within_rts_range(addr, len) { + cursor.move_next(); + return Ok((addr, cursor)); + } + + // Cursor moves to emas->front_mut. + // Firstly cursor moves to None, then moves to linkedlist head + cursor.move_next(); + cursor.move_next(); + + // Back to the first ema to check rts region before user region + let start_first = cursor.get().map(|ema| ema.start()).unwrap(); + if start_first < len { + return Err(SgxStatus::InvalidParameter); + } + + addr = trim_to!(start_first, align); + + if is_within_enclave(addr as *const u8, len) && is_within_rts_range(addr, len) { + return Ok((addr, cursor)); + } + + Err(SgxStatus::InvalidParameter) } } diff --git a/sgx_trts/src/emm/user.rs b/sgx_trts/src/emm/user.rs index b8876744f..a8dd18dfa 100644 --- a/sgx_trts/src/emm/user.rs +++ b/sgx_trts/src/emm/user.rs @@ -20,13 +20,13 @@ use crate::emm::interior::Reserve; use crate::enclave::MmLayout; use alloc::boxed::Box; use alloc::sync::Arc; -use spin::{Once, Mutex}; use core::alloc::Layout; use core::ffi::c_void; use core::ptr::NonNull; use intrusive_collections::intrusive_adapter; use intrusive_collections::{LinkedList, LinkedListLink}; use sgx_types::error::{SgxResult, SgxStatus}; +use spin::{Mutex, Once}; #[derive(Clone, Copy)] pub struct UserRange { @@ -34,16 +34,37 @@ pub struct UserRange { pub end: usize, } +impl UserRange { + fn start(&self) -> usize { + self.start + } + fn end(&self) -> usize { + self.end + } +} + pub static USER_RANGE: Once = Once::new(); pub fn init_range(start: usize, end: usize) { - // init - *USER_RANGE.call_once(|| { - UserRange { - start, - end, + // init + let _ = *USER_RANGE.call_once(|| UserRange { start, end }); +} + +pub fn is_within_rts_range(start: usize, len: usize) -> bool { + let end = if len > 0 { + if let Some(end) = start.checked_add(len - 1) { + end + } else { + return false; } - }); + } else { + start + }; + let user_range = USER_RANGE.get().unwrap(); + let user_start = user_range.start(); + let user_end = user_range.end(); + + (start >= user_end) || (end < user_start) } pub fn is_within_user_range(start: usize, len: usize) -> bool { @@ -56,9 +77,11 @@ pub fn is_within_user_range(start: usize, len: usize) -> bool { } else { start }; - let base = MmLayout::elrange_base(); + let user_range = USER_RANGE.get().unwrap(); + let user_start = user_range.start(); + let user_end = user_range.end(); - (start <= end) && (start >= base) && (end < base + MmLayout::elrange_size()) + (start <= end) && (start >= user_start) && (end < user_end) } pub struct UserMem { diff --git a/sgx_trts/src/lib.rs b/sgx_trts/src/lib.rs index 5c7c744bb..2253d9793 100644 --- a/sgx_trts/src/lib.rs +++ b/sgx_trts/src/lib.rs @@ -36,6 +36,7 @@ #![allow(clippy::missing_safety_doc)] #![allow(dead_code)] #![allow(non_camel_case_types)] +#![feature(linked_list_cursors)] #[cfg(all(feature = "sim", feature = "hyper"))] compile_error!("feature \"sim\" and feature \"hyper\" cannot be enabled at the same time");