vmi_core/os/
process.rs

1use serde::{Deserialize, Serialize};
2
3use super::{VmiOs, VmiOsImageArchitecture};
4use crate::{Pa, Va, VmiDriver, VmiError, VmiVa};
5
6/// A process ID within a system.
7#[derive(
8    Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
9)]
10pub struct ProcessId(pub u32);
11
12impl From<u32> for ProcessId {
13    fn from(value: u32) -> Self {
14        Self(value)
15    }
16}
17
18impl From<ProcessId> for u32 {
19    fn from(value: ProcessId) -> Self {
20        value.0
21    }
22}
23
24impl std::fmt::Display for ProcessId {
25    fn fmt(&self, f: &mut std::fmt::Formatter) -> ::std::fmt::Result {
26        write!(f, "{}", self.0)
27    }
28}
29
30/// A process object within a system.
31///
32/// Equivalent to `EPROCESS*` on Windows or `task_struct*` on Linux.
33#[derive(
34    Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
35)]
36pub struct ProcessObject(pub Va);
37
38impl ProcessObject {
39    /// Checks if the process object is a null reference.
40    pub fn is_null(&self) -> bool {
41        self.0.0 == 0
42    }
43
44    /// Converts the process object to a 64-bit unsigned integer.
45    pub fn to_u64(&self) -> u64 {
46        self.0.0
47    }
48}
49
50impl From<Va> for ProcessObject {
51    fn from(value: Va) -> Self {
52        Self(value)
53    }
54}
55
56impl From<ProcessObject> for Va {
57    fn from(value: ProcessObject) -> Self {
58        value.0
59    }
60}
61
62impl std::fmt::Display for ProcessObject {
63    fn fmt(&self, f: &mut std::fmt::Formatter) -> ::std::fmt::Result {
64        write!(f, "{}", self.0)
65    }
66}
67
68/// A trait for process objects.
69///
70/// This trait provides an abstraction over processes within a guest OS.
71pub trait VmiOsProcess<'a, Driver>: VmiVa + 'a
72where
73    Driver: VmiDriver,
74{
75    /// The VMI OS type.
76    type Os: VmiOs<Driver>;
77
78    /// Returns the process ID.
79    fn id(&self) -> Result<ProcessId, VmiError>;
80
81    /// Returns the process object.
82    fn object(&self) -> Result<ProcessObject, VmiError>;
83
84    /// Returns the name of the process.
85    ///
86    /// # Platform-specific
87    ///
88    /// - **Windows**: `_EPROCESS.ImageFileName` (limited to 16 characters).
89    /// - **Linux**: `_task_struct.comm` (limited to 16 characters).
90    fn name(&self) -> Result<String, VmiError>;
91
92    /// Returns the parent process ID.
93    fn parent_id(&self) -> Result<ProcessId, VmiError>;
94
95    /// Returns the architecture of the process.
96    fn architecture(&self) -> Result<VmiOsImageArchitecture, VmiError>;
97
98    /// Returns the process's page table translation root.
99    fn translation_root(&self) -> Result<Pa, VmiError>;
100
101    /// Returns the user-mode page table translation root.
102    ///
103    /// If KPTI is disabled, this function will return the same value as
104    /// [`translation_root`](Self::translation_root).
105    fn user_translation_root(&self) -> Result<Pa, VmiError>;
106
107    /// Returns the base address of the process image.
108    fn image_base(&self) -> Result<Va, VmiError>;
109
110    /// Returns an iterator over the process's memory regions.
111    fn regions(
112        &self,
113    ) -> Result<
114        impl Iterator<Item = Result<<Self::Os as VmiOs<Driver>>::Region<'a>, VmiError>>,
115        VmiError,
116    >;
117
118    /// Finds the memory region containing the given address.
119    fn find_region(
120        &self,
121        address: Va,
122    ) -> Result<Option<<Self::Os as VmiOs<Driver>>::Region<'a>>, VmiError>;
123
124    /// Returns an iterator over the threads in the process.
125    ///
126    /// # Platform-specific
127    ///
128    /// - **Windows**: `_EPROCESS.ThreadListHead`.
129    fn threads(
130        &self,
131    ) -> Result<
132        impl Iterator<Item = Result<<Self::Os as VmiOs<Driver>>::Thread<'a>, VmiError>>,
133        VmiError,
134    >;
135
136    /// Checks whether the given virtual address is valid in the process.
137    ///
138    /// This method checks if page-faulting on the address would result in
139    /// a successful access.
140    fn is_valid_address(&self, address: Va) -> Result<Option<bool>, VmiError>;
141}