use std::{
alloc::{self, Layout},
ptr,
sync::{
LazyLock,
atomic::{AtomicU32, Ordering},
},
};
use dashmap::DashMap;
use log::warn;
use super::{context::ContextManager, safe_ptr, vmem};
use crate::{Error, ErrorKind, Result, raw};
const SHM_ID_NONE: i32 = -1;
const SHM_FLAG_BUFFER_ALLOCED: u32 = 1 << 0;
const MAX_SHARED_MEMORY_SIZE: usize = 100 * 1024 * 1024;
struct ShmEntry {
context_id: i32,
ptr: *mut u8,
size: usize,
}
unsafe impl Send for ShmEntry {}
unsafe impl Sync for ShmEntry {}
impl Drop for ShmEntry {
fn drop(&mut self) {
if !self.ptr.is_null() && self.size > 0 {
unsafe {
alloc::dealloc(self.ptr, Layout::from_size_align(self.size, 1).unwrap());
}
self.ptr = ptr::null_mut();
}
}
}
type SharedMemoryMap = DashMap<i32, ShmEntry>;
static SHMS: LazyLock<SharedMemoryMap> = LazyLock::new(DashMap::new);
type RegisteredAddrMap = DashMap<usize, i32>;
static REGISTERED_SHMS: LazyLock<RegisteredAddrMap> = LazyLock::new(DashMap::new);
static SHM_ID_COUNTER: LazyLock<AtomicU32> = LazyLock::new(|| AtomicU32::new(0));
pub struct SharedMemoryManager;
impl SharedMemoryManager {
pub fn allocate(
ctx: *mut raw::TEEC_Context,
shm: *mut raw::TEEC_SharedMemory,
register: bool,
) -> Result<()> {
let mut shm_nn = safe_ptr::deref_mut(shm)?;
let ctx_nn = safe_ptr::deref(ctx)?;
let shm_ref = unsafe { shm_nn.as_mut() };
let ctx_ref = unsafe { ctx_nn.as_ref() };
let context_id = ctx_ref.imp.fd;
let flags = shm_ref.flags;
let size = shm_ref.size;
if size == 0 || flags == 0 || flags & !(raw::TEEC_MEM_INPUT | raw::TEEC_MEM_OUTPUT) != 0 {
return Err(Error::new(ErrorKind::BadParameters));
}
if size > MAX_SHARED_MEMORY_SIZE {
warn!(
"共享内存请求过大: {} bytes (最大允许: {} bytes)",
size, MAX_SHARED_MEMORY_SIZE
);
return Err(Error::new(ErrorKind::OutOfMemory));
}
Self::allocate_cc(ctx, shm_ref, context_id, size, register)?;
Ok(())
}
fn allocate_cc(
_ctx: *mut raw::TEEC_Context,
shm_ref: &mut raw::TEEC_SharedMemory,
context_id: i32,
size: usize,
register: bool,
) -> Result<()> {
let layout =
Layout::from_size_align(size, 1).map_err(|_| Error::new(ErrorKind::BadParameters))?;
let buf_ptr = unsafe { alloc::alloc_zeroed(layout) };
if buf_ptr.is_null() {
return Err(Error::new(ErrorKind::OutOfMemory));
}
if register {
if shm_ref.buffer.is_null() {
unsafe { alloc::dealloc(buf_ptr, layout) };
return Err(Error::new(ErrorKind::BadParameters));
}
if !vmem::range_readable(shm_ref.buffer as *const u8, size) {
unsafe { alloc::dealloc(buf_ptr, layout) };
return Err(Error::new(ErrorKind::BadParameters));
}
unsafe { ptr::copy_nonoverlapping(shm_ref.buffer as *const u8, buf_ptr, size) };
}
let shm_id = SHM_ID_COUNTER.fetch_add(1, Ordering::Relaxed) as i32;
shm_ref.buffer = buf_ptr as *mut std::ffi::c_void;
shm_ref.imp.id = shm_id;
shm_ref.imp.registered_fd = -1;
shm_ref.imp.shadow_buffer = ptr::null_mut();
shm_ref.imp.alloced_size = size;
shm_ref.imp.flags = SHM_FLAG_BUFFER_ALLOCED;
SHMS.insert(
shm_id,
ShmEntry {
context_id,
ptr: buf_ptr,
size,
},
);
REGISTERED_SHMS.insert(shm_ref as *const raw::TEEC_SharedMemory as usize, shm_id);
Ok(())
}
pub fn release(shm: *mut raw::TEEC_SharedMemory) {
if let Ok(mut shm_nn) = safe_ptr::deref_mut(shm) {
let shm_ref = unsafe { shm_nn.as_mut() };
if shm_ref.imp.id == SHM_ID_NONE {
return;
}
let id = shm_ref.imp.id;
let should_release = SHMS
.get(&id)
.is_some_and(|entry| std::ptr::eq(entry.ptr, shm_ref.buffer as *mut u8));
if !should_release {
return;
}
shm_ref.imp.id = SHM_ID_NONE;
shm_ref.size = 0;
shm_ref.flags = 0;
shm_ref.buffer = ptr::null_mut();
SHMS.remove(&id);
REGISTERED_SHMS.remove(&(shm as *const raw::TEEC_SharedMemory as usize));
}
}
pub fn is_registered(shm: *const raw::TEEC_SharedMemory) -> bool {
!shm.is_null() && REGISTERED_SHMS.contains_key(&(shm as usize))
}
pub fn read_buffer_locked(
parent: *const raw::TEEC_SharedMemory,
offset: usize,
size: usize,
) -> Result<Vec<u8>> {
let bad_params = || Error::new(ErrorKind::BadParameters);
if parent.is_null() {
return Err(bad_params());
}
let shm_id = *REGISTERED_SHMS
.get(&(parent as usize))
.ok_or_else(bad_params)?;
let entry = SHMS.get(&shm_id).ok_or_else(bad_params)?;
let parent_ref = unsafe { &*parent };
let buf_ptr = parent_ref.buffer as *const u8;
if buf_ptr.is_null() || !std::ptr::eq(buf_ptr, entry.value().ptr) {
return Err(bad_params());
}
if offset.saturating_add(size) > entry.value().size {
return Err(bad_params());
}
if size == 0 {
return Ok(Vec::new());
}
let start = unsafe { buf_ptr.add(offset) };
Ok(unsafe { std::slice::from_raw_parts(start, size) }.to_vec())
}
pub fn write_buffer_locked(
parent: *const raw::TEEC_SharedMemory,
offset: usize,
data: &[u8],
) -> Result<()> {
let bad_params = || Error::new(ErrorKind::BadParameters);
if parent.is_null() {
return Err(bad_params());
}
let shm_id = *REGISTERED_SHMS
.get(&(parent as usize))
.ok_or_else(bad_params)?;
let entry = SHMS.get(&shm_id).ok_or_else(bad_params)?;
let parent_ref = unsafe { &*parent };
let buf_ptr = parent_ref.buffer as *mut u8;
if buf_ptr.is_null() || !std::ptr::eq(buf_ptr, entry.value().ptr) {
return Err(bad_params());
}
if offset.saturating_add(data.len()) > entry.value().size {
return Err(bad_params());
}
if data.is_empty() {
return Ok(());
}
let dst = unsafe { buf_ptr.add(offset) };
unsafe { std::ptr::copy_nonoverlapping(data.as_ptr(), dst, data.len()) };
Ok(())
}
#[cfg(test)]
pub fn get_buffer(shm: *const raw::TEEC_SharedMemory) -> Option<Vec<u8>> {
if shm.is_null() {
return None;
}
let shm_ref = unsafe { &*shm };
let id = shm_ref.imp.id;
if id == SHM_ID_NONE || shm_ref.buffer.is_null() {
return None;
}
SHMS.get(&id).and_then(|entry| {
let entry_ptr = entry.value().ptr;
let entry_size = entry.value().size;
if entry_ptr.is_null() || entry_size == 0 {
return None;
}
if !std::ptr::eq(entry_ptr, shm_ref.buffer as *mut u8) {
return None;
}
Some(unsafe { std::slice::from_raw_parts(entry_ptr, entry_size).to_vec() })
})
}
pub fn release_by_context(ctx: *mut raw::TEEC_Context) {
let Some(registered_id) = ContextManager::registered_id(ctx) else {
return;
};
if let Ok(ctx_nn) = safe_ptr::deref(ctx) {
let ctx_ref = unsafe { ctx_nn.as_ref() };
let context_id = ctx_ref.imp.fd;
if context_id != registered_id {
return;
}
SHMS.retain(|_, entry| entry.context_id != context_id);
REGISTERED_SHMS.retain(|_, shm_id| SHMS.contains_key(shm_id));
}
}
}
#[cfg(test)]
mod shared_memory_tests {
use super::*;
fn create_test_context(id: i32) -> raw::TEEC_Context {
raw::TEEC_Context {
imp: raw::TEEC_Context__Imp {
fd: id,
memref_null: false,
reg_mem: false,
},
}
}
fn create_test_shm() -> raw::TEEC_SharedMemory {
raw::TEEC_SharedMemory {
buffer: ptr::null_mut(),
size: 0,
flags: 0,
imp: raw::TEEC_SharedMemory__Imp {
id: -1,
registered_fd: -1,
shadow_buffer: ptr::null_mut(),
alloced_size: 0,
flags: 0,
},
}
}
#[test]
fn test_allocate_valid_memory() {
let mut ctx = create_test_context(100);
let mut shm = create_test_shm();
shm.size = 64;
shm.flags = raw::TEEC_MEM_INPUT;
let result = SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
);
assert!(result.is_ok(), "应该成功分配共享内存");
assert!(!shm.buffer.is_null(), "缓冲区指针应该非空");
assert!(shm.imp.id >= 0, "ID 应该为非负的唯一共享内存 id");
assert_eq!(shm.imp.alloced_size, 64, "分配大小应该正确");
SharedMemoryManager::release(&mut shm as *mut raw::TEEC_SharedMemory);
}
#[test]
fn test_allocate_with_registration() {
let mut ctx = create_test_context(101);
let mut data = vec![1u8, 2, 3, 4, 5];
let mut shm = create_test_shm();
shm.size = data.len();
shm.flags = raw::TEEC_MEM_INPUT;
shm.buffer = data.as_mut_ptr() as *mut std::ffi::c_void;
let result = SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
true,
);
assert!(result.is_ok(), "应该成功注册共享内存");
if let Some(buffer) = SharedMemoryManager::get_buffer(&shm) {
assert_eq!(buffer, data, "数据应该被正确复制");
}
SharedMemoryManager::release(&mut shm as *mut raw::TEEC_SharedMemory);
}
#[test]
fn test_allocate_zero_size() {
let mut ctx = create_test_context(102);
let mut shm = create_test_shm();
shm.size = 0;
shm.flags = raw::TEEC_MEM_INPUT;
let result = SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
);
assert!(result.is_err(), "零大小分配应该失败");
}
#[test]
fn test_allocate_invalid_flags() {
let mut ctx = create_test_context(103);
let mut shm = create_test_shm();
shm.size = 64;
shm.flags = 0;
let result = SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
);
assert!(result.is_err(), "无效标志位应该导致失败");
}
#[test]
fn test_allocate_excessive_size() {
let mut ctx = create_test_context(104);
let mut shm = create_test_shm();
shm.size = MAX_SHARED_MEMORY_SIZE + 1;
shm.flags = raw::TEEC_MEM_INPUT;
let result = SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
);
assert!(result.is_err(), "过大的分配应该失败");
}
#[test]
fn test_allocate_null_context() {
let mut shm = create_test_shm();
shm.size = 64;
shm.flags = raw::TEEC_MEM_INPUT;
let result = SharedMemoryManager::allocate(
ptr::null_mut(),
&mut shm as *mut raw::TEEC_SharedMemory,
false,
);
assert!(result.is_err(), "空上下文应该导致失败");
}
#[test]
fn test_allocate_null_shm() {
let mut ctx = create_test_context(105);
let result = SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
ptr::null_mut(),
false,
);
assert!(result.is_err(), "空共享内存指针应该导致失败");
}
#[test]
fn test_release_valid_memory() {
let mut ctx = create_test_context(106);
let mut shm = create_test_shm();
shm.size = 64;
shm.flags = raw::TEEC_MEM_INPUT;
SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
)
.unwrap();
assert!(SharedMemoryManager::get_buffer(&shm).is_some());
SharedMemoryManager::release(&mut shm as *mut raw::TEEC_SharedMemory);
assert_eq!(shm.imp.id, -1, "ID 应该被重置为 -1");
assert_eq!(shm.size, 0, "大小应该被重置为 0");
assert!(shm.buffer.is_null(), "缓冲区指针应该为空");
assert!(
SharedMemoryManager::get_buffer(&shm).is_none(),
"缓存应该被清除"
);
}
#[test]
fn test_release_null_shm() {
SharedMemoryManager::release(ptr::null_mut());
}
#[test]
fn test_release_already_released() {
let mut ctx = create_test_context(107);
let mut shm = create_test_shm();
shm.size = 64;
shm.flags = raw::TEEC_MEM_INPUT;
SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
)
.unwrap();
SharedMemoryManager::release(&mut shm as *mut raw::TEEC_SharedMemory);
SharedMemoryManager::release(&mut shm as *mut raw::TEEC_SharedMemory);
}
#[test]
fn test_get_buffer_null_shm() {
let result = SharedMemoryManager::get_buffer(ptr::null());
assert!(result.is_none(), "空指针应该返回 None");
}
#[test]
fn test_get_buffer_unregistered() {
let shm = create_test_shm();
let result = SharedMemoryManager::get_buffer(&shm);
assert!(result.is_none(), "未注册的共享内存应该返回 None");
}
#[test]
fn test_multiple_allocations() {
let mut contexts = vec![];
let mut shms = vec![];
for i in 200..205 {
let mut ctx = create_test_context(i);
let mut shm = create_test_shm();
shm.size = 32;
shm.flags = raw::TEEC_MEM_INPUT;
SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
)
.unwrap();
contexts.push(ctx);
shms.push(shm);
}
for shm in &shms {
assert!(SharedMemoryManager::get_buffer(shm).is_some());
}
for shm in &mut shms {
SharedMemoryManager::release(shm as *mut raw::TEEC_SharedMemory);
}
for shm in &shms {
assert!(SharedMemoryManager::get_buffer(shm).is_none());
}
}
#[test]
fn test_allocate_both_flags() {
let mut ctx = create_test_context(300);
let mut shm = create_test_shm();
shm.size = 64;
shm.flags = raw::TEEC_MEM_INPUT | raw::TEEC_MEM_OUTPUT;
let result = SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
);
assert!(result.is_ok(), "同时设置 INPUT 和 OUTPUT 应该成功");
SharedMemoryManager::release(&mut shm as *mut raw::TEEC_SharedMemory);
}
#[test]
fn test_allocate_exactly_max_size() {
let mut ctx = create_test_context(301);
let mut shm = create_test_shm();
shm.size = MAX_SHARED_MEMORY_SIZE;
shm.flags = raw::TEEC_MEM_INPUT;
let result = SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
);
assert!(result.is_ok(), "正好等于最大大小应该成功");
SharedMemoryManager::release(&mut shm as *mut raw::TEEC_SharedMemory);
}
#[test]
fn test_allocate_invalid_flag_combinations() {
let mut ctx = create_test_context(303);
let mut shm = create_test_shm();
shm.size = 64;
shm.flags = raw::TEEC_MEM_OUTPUT;
let result = SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
);
drop(result);
shm.flags = 0x12345678;
let result = SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
);
assert!(result.is_err(), "无效标志位应该失败");
}
#[test]
fn test_release_with_different_states() {
let mut shm1 = create_test_shm();
SharedMemoryManager::release(&mut shm1 as *mut raw::TEEC_SharedMemory);
assert_eq!(shm1.imp.id, -1);
let mut ctx = create_test_context(304);
let mut shm2 = create_test_shm();
shm2.size = 32;
shm2.flags = raw::TEEC_MEM_INPUT;
SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm2 as *mut raw::TEEC_SharedMemory,
false,
)
.unwrap();
SharedMemoryManager::release(&mut shm2 as *mut raw::TEEC_SharedMemory);
assert_eq!(shm2.imp.id, -1);
assert_eq!(shm2.size, 0);
}
#[test]
fn test_get_buffer_edge_cases() {
let mut shm = create_test_shm();
shm.imp.id = 0;
let result = SharedMemoryManager::get_buffer(&shm);
assert!(result.is_none());
}
#[test]
fn test_stress_multiple_rapid_allocations() {
let mut ctx = create_test_context(400);
for i in 0..100 {
let mut shm = create_test_shm();
shm.size = 16;
shm.flags = raw::TEEC_MEM_INPUT;
let result = SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
);
assert!(result.is_ok(), "第 {} 次分配应该成功", i);
SharedMemoryManager::release(&mut shm as *mut raw::TEEC_SharedMemory);
}
}
#[test]
fn test_multiple_allocations_same_context() {
let mut ctx = create_test_context(500);
let mut shm1 = create_test_shm();
shm1.size = 32;
shm1.flags = raw::TEEC_MEM_INPUT;
let mut shm2 = create_test_shm();
shm2.size = 64;
shm2.flags = raw::TEEC_MEM_INPUT;
SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm1 as *mut raw::TEEC_SharedMemory,
false,
)
.unwrap();
SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm2 as *mut raw::TEEC_SharedMemory,
false,
)
.unwrap();
assert_ne!(
shm1.imp.id, shm2.imp.id,
"同一 context 下多次分配应该有不同的 shm id"
);
assert!(SharedMemoryManager::get_buffer(&shm1).is_some());
assert!(SharedMemoryManager::get_buffer(&shm2).is_some());
SharedMemoryManager::release(&mut shm1 as *mut raw::TEEC_SharedMemory);
assert!(SharedMemoryManager::get_buffer(&shm1).is_none());
assert!(
SharedMemoryManager::get_buffer(&shm2).is_some(),
"释放 shm1 不应影响 shm2"
);
SharedMemoryManager::release(&mut shm2 as *mut raw::TEEC_SharedMemory);
assert!(SharedMemoryManager::get_buffer(&shm2).is_none());
}
#[test]
fn test_read_write_buffer_locked_basic() {
let mut ctx = create_test_context(600);
let mut shm = create_test_shm();
shm.size = 32;
shm.flags = raw::TEEC_MEM_INPUT | raw::TEEC_MEM_OUTPUT;
SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
)
.unwrap();
let parent = &shm as *const raw::TEEC_SharedMemory;
SharedMemoryManager::write_buffer_locked(parent, 0, &[1, 2, 3, 4]).unwrap();
let data = SharedMemoryManager::read_buffer_locked(parent, 0, 4).unwrap();
assert_eq!(data, vec![1, 2, 3, 4]);
SharedMemoryManager::write_buffer_locked(parent, 16, &[9, 8, 7]).unwrap();
let data = SharedMemoryManager::read_buffer_locked(parent, 16, 3).unwrap();
assert_eq!(data, vec![9, 8, 7]);
assert!(
SharedMemoryManager::read_buffer_locked(parent, 0, 0)
.unwrap()
.is_empty()
);
SharedMemoryManager::write_buffer_locked(parent, 0, &[]).unwrap();
SharedMemoryManager::release(&mut shm as *mut raw::TEEC_SharedMemory);
}
#[test]
fn test_locked_access_boundary_checks() {
let mut ctx = create_test_context(601);
let mut shm = create_test_shm();
shm.size = 16;
shm.flags = raw::TEEC_MEM_INPUT;
SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
)
.unwrap();
let parent = &shm as *const raw::TEEC_SharedMemory;
assert!(SharedMemoryManager::read_buffer_locked(parent, 0, 17).is_err());
assert!(SharedMemoryManager::read_buffer_locked(parent, 16, 1).is_err());
assert!(SharedMemoryManager::write_buffer_locked(parent, 8, &[0u8; 9]).is_err());
assert!(SharedMemoryManager::read_buffer_locked(parent, 0, 16).is_ok());
assert!(SharedMemoryManager::write_buffer_locked(parent, 16, &[]).is_ok());
shm.size = 1024;
assert!(SharedMemoryManager::read_buffer_locked(parent, 0, 512).is_err());
assert!(SharedMemoryManager::write_buffer_locked(parent, 0, &[0u8; 512]).is_err());
shm.size = 16;
SharedMemoryManager::release(&mut shm as *mut raw::TEEC_SharedMemory);
}
#[test]
fn test_locked_access_rejects_tampered_buffer_ptr() {
let mut ctx = create_test_context(602);
let mut shm = create_test_shm();
shm.size = 16;
shm.flags = raw::TEEC_MEM_INPUT;
SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
)
.unwrap();
let parent = &shm as *const raw::TEEC_SharedMemory;
let mut fake = [0u8; 8];
shm.buffer = fake.as_mut_ptr() as *mut std::ffi::c_void;
assert!(SharedMemoryManager::read_buffer_locked(parent, 0, 4).is_err());
assert!(SharedMemoryManager::write_buffer_locked(parent, 0, &[1, 2, 3, 4]).is_err());
SharedMemoryManager::release(&mut shm as *mut raw::TEEC_SharedMemory);
}
#[test]
fn test_locked_access_rejects_unregistered_parent() {
let shm = create_test_shm();
let parent = &shm as *const raw::TEEC_SharedMemory;
assert!(SharedMemoryManager::read_buffer_locked(parent, 0, 4).is_err());
assert!(SharedMemoryManager::write_buffer_locked(parent, 0, &[1]).is_err());
let null_parent = ptr::null::<raw::TEEC_SharedMemory>();
assert!(SharedMemoryManager::read_buffer_locked(null_parent, 0, 4).is_err());
assert!(SharedMemoryManager::write_buffer_locked(null_parent, 0, &[1]).is_err());
}
#[test]
fn test_concurrent_release_during_locked_read() {
let mut ctx = create_test_context(603);
let mut shm = create_test_shm();
shm.size = 4096;
shm.flags = raw::TEEC_MEM_INPUT;
SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
)
.unwrap();
let parent = &shm as *const raw::TEEC_SharedMemory;
SharedMemoryManager::write_buffer_locked(parent, 0, &[0xAA; 4096]).unwrap();
let shm_addr = &mut shm as *mut raw::TEEC_SharedMemory as usize;
let parent_addr = parent as usize;
let releaser = std::thread::spawn(move || {
SharedMemoryManager::release(shm_addr as *mut raw::TEEC_SharedMemory);
});
match SharedMemoryManager::read_buffer_locked(
parent_addr as *const raw::TEEC_SharedMemory,
0,
4096,
) {
Ok(data) => assert_eq!(data, vec![0xAA; 4096]),
Err(_) => {
}
}
releaser.join().unwrap();
}
#[test]
fn test_concurrent_locked_reads() {
let mut ctx = create_test_context(604);
let mut shm = create_test_shm();
shm.size = 1024;
shm.flags = raw::TEEC_MEM_INPUT;
SharedMemoryManager::allocate(
&mut ctx as *mut raw::TEEC_Context,
&mut shm as *mut raw::TEEC_SharedMemory,
false,
)
.unwrap();
let parent = &shm as *const raw::TEEC_SharedMemory;
SharedMemoryManager::write_buffer_locked(parent, 0, &[0x5A; 1024]).unwrap();
let parent_addr = parent as usize;
let readers: Vec<_> = (0..4)
.map(|_| {
std::thread::spawn(move || {
SharedMemoryManager::read_buffer_locked(
parent_addr as *const raw::TEEC_SharedMemory,
0,
1024,
)
})
})
.collect();
for reader in readers {
let data = reader.join().unwrap().unwrap();
assert_eq!(data, vec![0x5A; 1024]);
}
SharedMemoryManager::release(&mut shm as *mut raw::TEEC_SharedMemory);
}
}