/// An actual current process may expose a bounded, owner-checked user range /// to a kernel-owned buffer. No external output is part of this operation. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum GuestCopyError { Fault, Context, Owner, } pub trait GuestCopyBackend: GuestLaunchBackend { fn copy_current_user_data( &self, bag: &Self::Bag, id: ProcessId, address: u64, output: &mut [u8], ) -> Result<(), GuestCopyError>; } impl Table { pub fn copy_current_user_data( &self, id: ProcessId, address: u64, output: &mut [u8], ) -> Result<(), GuestCopyError> { let before = self.gate().map_err(|_| GuestCopyError::Context)?; if before.current != Some(id) || before.kernel_bootstrap { return Err(GuestCopyError::Context); } self.current_launch(id) .map_err(|_| GuestCopyError::Context)?; let index = self.public_index(id).map_err(|_| GuestCopyError::Owner)?; let entry = &self.entries[index]; if entry.phase != Phase::Published { return Err(GuestCopyError::Owner); } let bag = entry.bag.as_ref().ok_or(GuestCopyError::Owner)?; self.backend() .copy_current_user_data(bag, id, address, output)?; if self.gate() != Ok(before) { return Err(GuestCopyError::Context); } Ok(()) } }