Struct shadow_rs::host::memory_manager::MemoryManager
source · pub struct MemoryManager { /* private fields */ }
Expand description
Provides accessors for reading and writing another process’s memory.
When in use, any operation that touches that process’s memory must go through the MemoryManager to ensure soundness. See MemoryManager::new.
Implementations§
source§impl MemoryManager
impl MemoryManager
sourcepub unsafe fn new(pid: Pid) -> Self
pub unsafe fn new(pid: Pid) -> Self
§Safety
pid
’s memory must not be modified without holding an exclusive
(mutable) reference to the returned MemoryManager. In Shadow we ensure
this by:
- Creating only one MemoryManager for a given process.
- TODO: Not allowing any thread in the process to execute without holding a mutable reference to its MemoryManager.
- Not directly modifying process memory via other techniques.
- Assuming (!) nothing else concurrently modifies memory of the given process.
(e.g. that some other process doesn’t start calling
process_vm_writev
to write to the process’s memory). - TODO: Validating that the process doesn’t have any shared memory mappings other than with Shadow or other simulated processes under Shadow’s control.
sourcepub fn memory_ref<T: Pod + Debug>(
&self,
ptr: ForeignArrayPtr<T>,
) -> Result<ProcessMemoryRef<'_, T>, Errno>
pub fn memory_ref<T: Pod + Debug>( &self, ptr: ForeignArrayPtr<T>, ) -> Result<ProcessMemoryRef<'_, T>, Errno>
Returns a reference to the given memory, copying to a local buffer if the memory isn’t mapped into Shadow.
sourcepub fn memory_ref_prefix<T: Pod + Debug>(
&self,
ptr: ForeignArrayPtr<T>,
) -> Result<ProcessMemoryRef<'_, T>, Errno>
pub fn memory_ref_prefix<T: Pod + Debug>( &self, ptr: ForeignArrayPtr<T>, ) -> Result<ProcessMemoryRef<'_, T>, Errno>
Returns a reference to the memory from the beginning of the given pointer to the last address in the pointer that’s accessible. Useful for accessing string data of unknown size. The data is copied to a local buffer if the memory isn’t mapped into Shadow.
sourcepub fn reader(&self, ptr: ForeignArrayPtr<u8>) -> MemoryReaderCursor<'_> ⓘ
pub fn reader(&self, ptr: ForeignArrayPtr<u8>) -> MemoryReaderCursor<'_> ⓘ
Creates a std::io::Read accessor for the specified plugin memory. Useful for handing off the ability to read process memory to non-Shadow APIs, without copying it to local memory first.
sourcepub fn read<T: Pod + Debug>(&self, ptr: ForeignPtr<T>) -> Result<T, Errno>
pub fn read<T: Pod + Debug>(&self, ptr: ForeignPtr<T>) -> Result<T, Errno>
Reads the memory into a local copy. memory_ref
is potentially more
efficient, but this is useful to avoid borrowing from the MemoryManager;
e.g. when we still want to be able to access the data while also writing
to process memory.
Examples:
let ptr: ForeignPtr<u32> = todo!();
let val: u32 = memory_manager.read(ptr)?;
let ptr: ForeignPtr<[u32; 2]> = todo!();
let val: [u32; 2] = memory_manager.read(ptr)?;
sourcepub fn write<T: Pod + Debug>(
&mut self,
ptr: ForeignPtr<T>,
val: &T,
) -> Result<(), Errno>
pub fn write<T: Pod + Debug>( &mut self, ptr: ForeignPtr<T>, val: &T, ) -> Result<(), Errno>
Writes a local value val
into the memory at ptr
.
let ptr: ForeignPtr<u32> = todo!();
let val = 5;
memory_manager.write(ptr, &val)?;
sourcepub fn copy_from_ptr<T: Debug + Pod>(
&self,
dst: &mut [T],
src: ForeignArrayPtr<T>,
) -> Result<(), Errno>
pub fn copy_from_ptr<T: Debug + Pod>( &self, dst: &mut [T], src: ForeignArrayPtr<T>, ) -> Result<(), Errno>
Similar to read
, but saves a copy if you already have a dst
to copy the data into.
sourcepub fn copy_str_from_ptr<'a>(
&self,
dst: &'a mut [u8],
src: ForeignArrayPtr<u8>,
) -> Result<&'a CStr, Errno>
pub fn copy_str_from_ptr<'a>( &self, dst: &'a mut [u8], src: ForeignArrayPtr<u8>, ) -> Result<&'a CStr, Errno>
Copies a NULL-terminated string starting from the beginning of src
and
contained completely within src
. Still works if some of src
isn’t
readable, as long as a NULL-terminated-string is contained in the
readable prefix.
If holding a reference to the MemoryManager for the lifetime of the
string is acceptable, use memory_ref_prefix
and
ProcessMemoryRef::get_str
to potentially avoid an extra copy.
sourcepub fn memory_ref_mut<T: Pod + Debug>(
&mut self,
ptr: ForeignArrayPtr<T>,
) -> Result<ProcessMemoryRefMut<'_, T>, Errno>
pub fn memory_ref_mut<T: Pod + Debug>( &mut self, ptr: ForeignArrayPtr<T>, ) -> Result<ProcessMemoryRefMut<'_, T>, Errno>
Returns a mutable reference to the given memory. If the memory isn’t mapped into Shadow, copies the data to a local buffer, which is written back into the process if and when the reference is flushed.
sourcepub fn memory_ref_mut_uninit<T: Pod + Debug>(
&mut self,
ptr: ForeignArrayPtr<T>,
) -> Result<ProcessMemoryRefMut<'_, T>, Errno>
pub fn memory_ref_mut_uninit<T: Pod + Debug>( &mut self, ptr: ForeignArrayPtr<T>, ) -> Result<ProcessMemoryRefMut<'_, T>, Errno>
Returns a mutable reference to the given memory. If the memory isn’t mapped into Shadow, just returns a buffer with unspecified contents, which will be written back into the process if and when the reference is flushed.
sourcepub fn copy_to_ptr<T: Pod + Debug>(
&mut self,
dst: ForeignArrayPtr<T>,
src: &[T],
) -> Result<(), Errno>
pub fn copy_to_ptr<T: Pod + Debug>( &mut self, dst: ForeignArrayPtr<T>, src: &[T], ) -> Result<(), Errno>
Writes the memory from a local copy. If src
doesn’t already exist,
using memory_ref_mut_uninit
and initializing the data in that
reference saves a copy.
sourcepub fn init_mapper(&mut self, ctx: &ThreadContext<'_>)
pub fn init_mapper(&mut self, ctx: &ThreadContext<'_>)
Initialize the MemoryMapper, allowing for more efficient access. Needs a running thread.
sourcepub fn has_mapper(&self) -> bool
pub fn has_mapper(&self) -> bool
Whether the internal MemoryMapper has been initialized.
sourcepub fn writer(&mut self, ptr: ForeignArrayPtr<u8>) -> MemoryWriterCursor<'_> ⓘ
pub fn writer(&mut self, ptr: ForeignArrayPtr<u8>) -> MemoryWriterCursor<'_> ⓘ
Create a write accessor for the specified plugin memory.
pub fn handle_brk( &mut self, ctx: &ThreadContext<'_>, ptr: ForeignPtr<u8>, ) -> Result<ForeignPtr<u8>, SyscallError>
pub fn do_mmap( &mut self, ctx: &ThreadContext<'_>, addr: ForeignPtr<u8>, length: usize, prot: ProtFlags, flags: MapFlags, fd: i32, offset: i64, ) -> Result<ForeignPtr<u8>, Errno>
pub fn handle_munmap( &mut self, ctx: &ThreadContext<'_>, addr: ForeignPtr<u8>, length: usize, ) -> Result<(), SyscallError>
pub fn handle_mremap( &mut self, ctx: &ThreadContext<'_>, old_address: ForeignPtr<u8>, old_size: usize, new_size: usize, flags: i32, new_address: ForeignPtr<u8>, ) -> Result<ForeignPtr<u8>, SyscallError>
pub fn handle_mprotect( &mut self, ctx: &ThreadContext<'_>, addr: ForeignPtr<u8>, size: usize, prot: ProtFlags, ) -> Result<(), SyscallError>
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for MemoryManager
impl !RefUnwindSafe for MemoryManager
impl Send for MemoryManager
impl !Sync for MemoryManager
impl Unpin for MemoryManager
impl UnwindSafe for MemoryManager
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more