diff --git a/src/runtime/monitor-api/src/lib.rs b/src/runtime/monitor-api/src/lib.rs index 92659c57..13099487 100644 --- a/src/runtime/monitor-api/src/lib.rs +++ b/src/runtime/monitor-api/src/lib.rs @@ -221,25 +221,38 @@ impl LibraryHandle { .unwrap(), ) } + + /// Get the descriptor for this handle. + pub fn desc(&self) -> Descriptor { + self.desc + } } /// A builder-type for loading libraries. -pub struct LibraryLoader { +pub struct LibraryLoader<'a> { id: ObjID, + comp: Option<&'a CompartmentHandle>, } -impl LibraryLoader { +impl<'a> LibraryLoader<'a> { /// Make a new LibraryLoader. pub fn new(id: ObjID) -> Self { - Self { id } + Self { id, comp: None } + } + + /// Load the library in the given compartment. + pub fn in_compartment(&'a mut self, comp: &'a CompartmentHandle) -> &'a mut Self { + self.comp = Some(comp); + self } /// Load the library. pub fn load(&self) -> Result { - let desc: Descriptor = gates::monitor_rt_load_library(self.id) - .ok() - .ok_or(gates::LoadLibraryError::Unknown) - .flatten()?; + let desc: Descriptor = + gates::monitor_rt_load_library(self.comp.map(|comp| comp.desc).flatten(), self.id) + .ok() + .ok_or(gates::LoadLibraryError::Unknown) + .flatten()?; Ok(LibraryHandle { desc }) } } @@ -259,6 +272,11 @@ impl CompartmentHandle { .unwrap(), ) } + + /// Get the descriptor for this handle, or None if the handle refers to the current compartment. + pub fn desc(&self) -> Option { + self.desc + } } /// A builder-type for loading compartments. @@ -272,7 +290,6 @@ impl CompartmentLoader { Self { id } } - // TODO: err /// Load the compartment. pub fn load(&self) -> Result { let desc = gates::monitor_rt_load_compartment(self.id) @@ -366,6 +383,7 @@ impl<'a> CompartmentInfo<'a> { } impl CompartmentHandle { + /// Get a handle to the current compartment. pub fn current() -> Self { Self { desc: None } } @@ -393,7 +411,7 @@ pub struct LibraryIter<'a> { } impl<'a> LibraryIter<'a> { - pub fn new(comp: &'a CompartmentHandle) -> Self { + fn new(comp: &'a CompartmentHandle) -> Self { Self { n: 0, comp } } } @@ -417,7 +435,7 @@ pub struct CompartmentDepsIter<'a> { } impl<'a> CompartmentDepsIter<'a> { - pub fn new(comp: &'a CompartmentHandle) -> Self { + fn new(comp: &'a CompartmentHandle) -> Self { Self { n: 0, comp } } } @@ -443,6 +461,7 @@ bitflags::bitflags! { /// Compartment state flags. #[derive(Clone, Debug, Copy, PartialEq, PartialOrd, Ord, Eq, Hash)] pub struct CompartmentFlags : u64 { + /// Compartment is ready (libraries relocated and constructors run). const READY = 0x1; } } @@ -466,6 +485,9 @@ impl MappedObjectAddrs { } mod lazy_sb { + //! A per-thread per-compartment simple buffer used for transferring strings between + //! compartments and the monitor. This is necessary because the monitor runs at too low of a + //! level for us to use nice shared memory techniques. This is simpler and more secure. use std::cell::OnceCell; use secgate::util::SimpleBuffer; @@ -513,13 +535,17 @@ mod lazy_sb { pub(super) fn read_string_from_sb(len: usize) -> String { let mut buf = vec![0u8; len]; + // Safety: this is per thread, and we only ever create the reference here or in the other + // read function below. let len = unsafe { LAZY_SB.read(&mut buf) }; String::from_utf8_lossy(&buf[0..len]).to_string() } pub(super) fn read_bytes_from_sb(len: usize) -> Vec { let mut buf = vec![0u8; len]; + // Safety: see above. let len = unsafe { LAZY_SB.read(&mut buf) }; + buf.truncate(len); buf } } diff --git a/src/runtime/monitor/secapi/gates.rs b/src/runtime/monitor/secapi/gates.rs index 9ea4a767..f39146a7 100644 --- a/src/runtime/monitor/secapi/gates.rs +++ b/src/runtime/monitor/secapi/gates.rs @@ -184,12 +184,13 @@ pub fn monitor_rt_drop_compartment_handle(info: &secgate::GateCallInfo, desc: De )] pub fn monitor_rt_load_library( info: &secgate::GateCallInfo, + compartment: Option, id: ObjID, ) -> Result { use crate::api::MONITOR_INSTANCE_ID; let monitor = crate::mon::get_monitor(); let caller = info.source_context().unwrap_or(MONITOR_INSTANCE_ID); - monitor.load_library(caller, id) + monitor.load_library(caller, id, compartment) } #[derive(Clone, Copy, Debug)] diff --git a/src/runtime/monitor/src/mon/compartment.rs b/src/runtime/monitor/src/mon/compartment.rs index 05253bf5..0fafc398 100644 --- a/src/runtime/monitor/src/mon/compartment.rs +++ b/src/runtime/monitor/src/mon/compartment.rs @@ -71,17 +71,20 @@ impl CompartmentMgr { self.get_mut(MONITOR_INSTANCE_ID).unwrap() } + /// Get an iterator over all compartments. pub fn compartments(&self) -> impl Iterator { self.instances.values() } + /// Get an iterator over all compartments (mutable). pub fn compartments_mut(&mut self) -> impl Iterator { self.instances.values_mut() } } impl super::Monitor { - //#[tracing::instrument(skip(self), ret)] + /// Get CompartmentInfo for this caller. Note that this will write to the compartment-thread's + /// simple buffer. pub fn get_compartment_info( &self, instance: ObjID, @@ -107,7 +110,7 @@ impl super::Monitor { }) } - //#[tracing::instrument(skip(self), ret)] + /// Open a compartment handle for this caller compartment. pub fn get_compartment_handle(&self, caller: ObjID, compartment: ObjID) -> Option { self.compartment_handles .write(ThreadKey::get().unwrap()) @@ -123,6 +126,7 @@ impl super::Monitor { ) } + /// Open a handle to the n'th dependency compartment of a given compartment. pub fn get_compartment_deps( &self, caller: ObjID, @@ -132,6 +136,7 @@ impl super::Monitor { todo!() } + /// Load a new compartment with a root library ID, and return a compartment handle. pub fn load_compartment( &self, caller: ObjID, @@ -140,10 +145,15 @@ impl super::Monitor { todo!() } - //#[tracing::instrument(skip(self), ret)] + /// Drop a compartment handle. pub fn drop_compartment_handle(&self, caller: ObjID, desc: Descriptor) { self.compartment_handles .write(ThreadKey::get().unwrap()) .remove(caller, desc); } } + +/// A handle to a compartment. +pub struct CompartmentHandle { + pub instance: ObjID, +} diff --git a/src/runtime/monitor/src/mon/library.rs b/src/runtime/monitor/src/mon/library.rs index 8ab43847..815999ef 100644 --- a/src/runtime/monitor/src/mon/library.rs +++ b/src/runtime/monitor/src/mon/library.rs @@ -7,13 +7,15 @@ use twizzler_runtime_api::{AddrRange, ObjID}; use super::Monitor; use crate::gates::{LibraryInfo, LoadLibraryError}; +/// A handle to a library. pub struct LibraryHandle { comp: ObjID, id: LibraryId, } impl Monitor { - //#[tracing::instrument(skip(self), ret)] + /// Get LibraryInfo for a given library handle. Note that this will write to the + /// compartment-thread's simple buffer. pub fn get_library_info( &self, instance: ObjID, @@ -49,7 +51,7 @@ impl Monitor { }) } - //#[tracing::instrument(skip(self), ret)] + /// Open a handle to the n'th library for a compartment. pub fn get_library_handle( &self, caller: ObjID, @@ -67,11 +69,17 @@ impl Monitor { handles.insert(comp_id, LibraryHandle { comp: comp_id, id }) } - pub fn load_library(&self, caller: ObjID, id: ObjID) -> Result { + /// Load a library in the given compartment. + pub fn load_library( + &self, + caller: ObjID, + id: ObjID, + comp: Option, + ) -> Result { todo!() } - //#[tracing::instrument(skip(self), ret)] + /// Drop a library handle. pub fn drop_library_handle(&self, caller: ObjID, desc: Descriptor) { self.library_handles .write(ThreadKey::get().unwrap()) diff --git a/src/runtime/monitor/src/mon/mod.rs b/src/runtime/monitor/src/mon/mod.rs index 1fffd6a2..be39799d 100644 --- a/src/runtime/monitor/src/mon/mod.rs +++ b/src/runtime/monitor/src/mon/mod.rs @@ -1,33 +1,25 @@ -use std::{ptr::NonNull, sync::OnceLock, thread::Thread}; +use std::{ptr::NonNull, sync::OnceLock}; use dynlink::compartment::MONITOR_COMPARTMENT_ID; use happylock::{LockCollection, RwLock, ThreadKey}; use monitor_api::{SharedCompConfig, TlsTemplateInfo}; use secgate::util::HandleMgr; use twizzler_abi::upcall::UpcallFrame; -use twizzler_runtime_api::{LibraryId, MapError, MapFlags, ObjID, SpawnError, ThreadSpawnArgs}; +use twizzler_runtime_api::{MapError, MapFlags, ObjID, SpawnError, ThreadSpawnArgs}; use twz_rt::{RuntimeState, RuntimeThreadControl, OUR_RUNTIME}; use self::{ - compartment::{CompConfigObject, RunComp}, + compartment::{CompConfigObject, CompartmentHandle, RunComp}, space::{MapHandle, MapInfo, Unmapper}, thread::{ManagedThread, ThreadCleaner}, }; -use crate::{ - api::MONITOR_INSTANCE_ID, - gates::{CompartmentInfo, LibraryInfo, LoadCompartmentError, LoadLibraryError}, - init::InitDynlinkContext, -}; +use crate::{api::MONITOR_INSTANCE_ID, init::InitDynlinkContext}; pub(crate) mod compartment; pub mod library; pub(crate) mod space; pub(crate) mod thread; -pub struct CompartmentHandle { - instance: ObjID, -} - /// A security monitor instance. All monitor logic is implemented as methods for this type. /// We split the state into the following components: 'space', managing the virtual memory space and /// mapping objects, 'thread_mgr', which manages all threads owned by the monitor (typically, all @@ -187,6 +179,7 @@ impl Monitor { Ok(handle) } + /// Get the object ID for this compartment-thread's simple buffer. pub fn get_thread_simple_buffer(&self, sctx: ObjID, thread: ObjID) -> Option { let mut locks = self.locks.lock(ThreadKey::get().unwrap()); let (ref mut space, _, ref mut comps, _, _, _) = *locks;