memflow/os/
root.rs

1//! Describes the root of the Operating System
2
3use super::process::*;
4use super::{AddressCallback, ProcessInfo, ProcessInfoCallback};
5
6use crate::prelude::v1::{Result, *};
7
8use crate::cglue::*;
9use std::prelude::v1::*;
10
11/// High level OS trait implemented by OS layers.
12///
13/// This trait provides all necessary functions for handling an OS, retrieving processes, and
14/// moving resources into processes.
15///
16/// There are also methods for accessing system level modules.
17#[cfg_attr(feature = "plugins", cglue_trait)]
18#[int_result]
19pub trait Os: Send {
20    #[wrap_with_group(crate::plugins::os::ProcessInstance)]
21    type ProcessType<'a>: crate::os::process::Process + MemoryView + 'a
22    where
23        Self: 'a;
24    #[wrap_with_group(crate::plugins::os::IntoProcessInstance)]
25    type IntoProcessType: crate::os::process::Process + MemoryView + Clone + 'static;
26
27    /// Walks a process list and calls a callback for each process structure address
28    ///
29    /// The callback is fully opaque. We need this style so that C FFI can work seamlessly.
30    fn process_address_list_callback(&mut self, callback: AddressCallback) -> Result<()>;
31
32    /// Retrieves a process address list
33    ///
34    /// This will be a list of unique internal addresses for underlying process structures
35    #[skip_func]
36    fn process_address_list(&mut self) -> Result<Vec<Address>> {
37        let mut ret = vec![];
38        self.process_address_list_callback((&mut ret).into())?;
39        Ok(ret)
40    }
41
42    /// Walks a process list and calls a callback for each process
43    ///
44    /// The callback is fully opaque. We need this style so that C FFI can work seamlessly.
45    fn process_info_list_callback(&mut self, mut callback: ProcessInfoCallback) -> Result<()> {
46        // This is safe, because control will flow back to the callback.
47        let sptr = self as *mut Self;
48        let inner_callback = &mut |addr| match unsafe { &mut *sptr }.process_info_by_address(addr) {
49            Ok(info) => callback.call(info),
50            Err(Error(_, ErrorKind::PartialData)) => {
51                log::trace!("Partial error when reading process {:x}", addr);
52                true
53            }
54            Err(e) => {
55                log::trace!("Error when reading process {:x} {:?}", addr, e);
56                false
57            }
58        };
59        unsafe { sptr.as_mut().unwrap() }.process_address_list_callback(inner_callback.into())
60    }
61
62    /// Retrieves a process list
63    #[skip_func]
64    fn process_info_list(&mut self) -> Result<Vec<ProcessInfo>> {
65        let mut ret = vec![];
66        self.process_info_list_callback((&mut ret).into())?;
67        Ok(ret)
68    }
69
70    /// Find process information by its internal address
71    fn process_info_by_address(&mut self, address: Address) -> Result<ProcessInfo>;
72
73    /// Find process information by its name
74    ///
75    /// # Remarks:
76    ///
77    /// This function only returns processes whose state is not [`ProcessState::Dead`].
78    fn process_info_by_name(&mut self, name: &str) -> Result<ProcessInfo> {
79        let mut ret = Err(Error(ErrorOrigin::OsLayer, ErrorKind::ProcessNotFound));
80        let callback = &mut |data: ProcessInfo| {
81            if (data.state == ProcessState::Unknown || data.state == ProcessState::Alive)
82                && data.name.as_ref() == name
83            {
84                ret = Ok(data);
85                false
86            } else {
87                true
88            }
89        };
90        self.process_info_list_callback(callback.into())?;
91        ret
92    }
93
94    /// Find process information by its ID
95    fn process_info_by_pid(&mut self, pid: Pid) -> Result<ProcessInfo> {
96        let mut ret = Err(Error(ErrorOrigin::OsLayer, ErrorKind::ProcessNotFound));
97        let callback = &mut |data: ProcessInfo| {
98            if data.pid == pid {
99                ret = Ok(data);
100                false
101            } else {
102                true
103            }
104        };
105        self.process_info_list_callback(callback.into())?;
106        ret
107    }
108
109    /// Construct a process by its info, borrowing the OS
110    ///
111    /// It will share the underlying memory resources
112    fn process_by_info(&mut self, info: ProcessInfo) -> Result<Self::ProcessType<'_>>;
113
114    /// Construct a process by its info, consuming the OS
115    ///
116    /// This function will consume the Kernel instance and move its resources into the process
117    fn into_process_by_info(self, info: ProcessInfo) -> Result<Self::IntoProcessType>;
118
119    /// Creates a process by its internal address, borrowing the OS
120    ///
121    /// It will share the underlying memory resources
122    ///
123    /// If no process with the specified address can be found this function will return an Error.
124    ///
125    /// This function can be useful for quickly accessing a process.
126    fn process_by_address(&mut self, addr: Address) -> Result<Self::ProcessType<'_>> {
127        self.process_info_by_address(addr)
128            .and_then(move |i| self.process_by_info(i))
129    }
130
131    /// Creates a process by its name, borrowing the OS
132    ///
133    /// It will share the underlying memory resources
134    ///
135    /// If no process with the specified name can be found this function will return an Error.
136    ///
137    /// This function can be useful for quickly accessing a process.
138    ///
139    /// # Remarks:
140    ///
141    /// This function only returns processes whose state is not [`ProcessState::Dead`].
142    fn process_by_name(&mut self, name: &str) -> Result<Self::ProcessType<'_>> {
143        self.process_info_by_name(name)
144            .and_then(move |i| self.process_by_info(i))
145    }
146
147    /// Creates a process by its ID, borrowing the OS
148    ///
149    /// It will share the underlying memory resources
150    ///
151    /// If no process with the specified ID can be found this function will return an Error.
152    ///
153    /// This function can be useful for quickly accessing a process.
154    fn process_by_pid(&mut self, pid: Pid) -> Result<Self::ProcessType<'_>> {
155        self.process_info_by_pid(pid)
156            .and_then(move |i| self.process_by_info(i))
157    }
158
159    /// Creates a process by its internal address, consuming the OS
160    ///
161    /// It will consume the OS and not affect memory usage
162    ///
163    /// If no process with the specified address can be found this function will return an Error.
164    ///
165    /// This function can be useful for quickly accessing a process.
166    fn into_process_by_address(mut self, addr: Address) -> Result<Self::IntoProcessType>
167    where
168        Self: Sized,
169    {
170        self.process_info_by_address(addr)
171            .and_then(|i| self.into_process_by_info(i))
172    }
173
174    /// Creates a process by its name, consuming the OS
175    ///
176    /// It will consume the OS and not affect memory usage
177    ///
178    /// If no process with the specified name can be found this function will return an Error.
179    ///
180    /// This function can be useful for quickly accessing a process.
181    ///
182    /// # Remarks:
183    ///
184    /// This function only returns processes whose state is not [`ProcessState::Dead`].
185    fn into_process_by_name(mut self, name: &str) -> Result<Self::IntoProcessType>
186    where
187        Self: Sized,
188    {
189        self.process_info_by_name(name)
190            .and_then(|i| self.into_process_by_info(i))
191    }
192
193    /// Creates a process by its ID, consuming the OS
194    ///
195    /// It will consume the OS and not affect memory usage
196    ///
197    /// If no process with the specified ID can be found this function will return an Error.
198    ///
199    /// This function can be useful for quickly accessing a process.
200    fn into_process_by_pid(mut self, pid: Pid) -> Result<Self::IntoProcessType>
201    where
202        Self: Sized,
203    {
204        self.process_info_by_pid(pid)
205            .and_then(|i| self.into_process_by_info(i))
206    }
207
208    /// Walks the OS module list and calls the provided callback for each module structure
209    /// address
210    ///
211    /// # Arguments
212    /// * `callback` - where to pass each matching module to. This is an opaque callback.
213    fn module_address_list_callback(&mut self, callback: AddressCallback) -> Result<()>;
214
215    /// Walks the OS module list and calls the provided callback for each module
216    ///
217    /// # Arguments
218    /// * `callback` - where to pass each matching module to. This is an opaque callback.
219    fn module_list_callback(&mut self, mut callback: ModuleInfoCallback) -> Result<()> {
220        // This is safe, because control will flow back to the callback.
221        let sptr = self as *mut Self;
222        let inner_callback =
223            &mut |address: Address| match unsafe { &mut *sptr }.module_by_address(address) {
224                Ok(info) => callback.call(info),
225                Err(e) => {
226                    log::trace!("Error when reading module {:x} {:?}", address, e);
227                    true // continue iteration
228                }
229            };
230        unsafe { sptr.as_mut().unwrap() }.module_address_list_callback(inner_callback.into())
231    }
232
233    /// Retrieves a module by its structure address
234    ///
235    /// # Arguments
236    /// * `address` - address where module's information resides in
237    fn module_by_address(&mut self, address: Address) -> Result<ModuleInfo>;
238
239    /// Finds a OS module by its name
240    ///
241    /// This function can be useful for quickly accessing a specific module
242    fn module_by_name(&mut self, name: &str) -> Result<ModuleInfo> {
243        let mut ret = Err(Error(ErrorOrigin::OsLayer, ErrorKind::ProcessNotFound));
244        let callback = &mut |data: ModuleInfo| {
245            if data.name.as_ref() == name {
246                ret = Ok(data);
247                false
248            } else {
249                true
250            }
251        };
252        self.module_list_callback(callback.into())?;
253        ret
254    }
255
256    /// Retrieves a module list for the OS
257    #[skip_func]
258    fn module_list(&mut self) -> Result<Vec<ModuleInfo>> {
259        let mut ret = vec![];
260        self.module_list_callback((&mut ret).into())?;
261        Ok(ret)
262    }
263
264    /// Retrieves address of the primary module of the OS
265    ///
266    /// This will generally be for the main kernel process/module
267    fn primary_module_address(&mut self) -> Result<Address>;
268
269    /// Retrieves information for the primary module of the OS
270    ///
271    /// This will generally be for the main kernel process/module
272    fn primary_module(&mut self) -> Result<ModuleInfo> {
273        let addr = self.primary_module_address()?;
274        self.module_by_address(addr)
275    }
276
277    /// Retrieves a list of all imports of a given module
278    fn module_import_list_callback(
279        &mut self,
280        info: &ModuleInfo,
281        callback: ImportCallback,
282    ) -> Result<()>;
283
284    /// Retrieves a list of all exports of a given module
285    fn module_export_list_callback(
286        &mut self,
287        info: &ModuleInfo,
288        callback: ExportCallback,
289    ) -> Result<()>;
290
291    /// Retrieves a list of all sections of a given module
292    fn module_section_list_callback(
293        &mut self,
294        info: &ModuleInfo,
295        callback: SectionCallback,
296    ) -> Result<()>;
297
298    /// Retrieves a list of all imports of a given module
299    #[skip_func]
300    fn module_import_list(&mut self, info: &ModuleInfo) -> Result<Vec<ImportInfo>> {
301        let mut ret = vec![];
302        self.module_import_list_callback(info, (&mut ret).into())?;
303        Ok(ret)
304    }
305
306    /// Retrieves a list of all exports of a given module
307    #[skip_func]
308    fn module_export_list(&mut self, info: &ModuleInfo) -> Result<Vec<ExportInfo>> {
309        let mut ret = vec![];
310        self.module_export_list_callback(info, (&mut ret).into())?;
311        Ok(ret)
312    }
313
314    /// Retrieves a list of all sections of a given module
315    #[skip_func]
316    fn module_section_list(&mut self, info: &ModuleInfo) -> Result<Vec<SectionInfo>> {
317        let mut ret = vec![];
318        self.module_section_list_callback(info, (&mut ret).into())?;
319        Ok(ret)
320    }
321
322    /// Finds a single import of a given module by its name
323    fn module_import_by_name(&mut self, info: &ModuleInfo, name: &str) -> Result<ImportInfo> {
324        let mut ret = Err(Error(ErrorOrigin::OsLayer, ErrorKind::ImportNotFound));
325        let callback = &mut |data: ImportInfo| {
326            if data.name.as_ref() == name {
327                ret = Ok(data);
328                false
329            } else {
330                true
331            }
332        };
333        self.module_import_list_callback(info, callback.into())?;
334        ret
335    }
336
337    /// Finds a single export of a given module by its name
338    fn module_export_by_name(&mut self, info: &ModuleInfo, name: &str) -> Result<ExportInfo> {
339        let mut ret = Err(Error(ErrorOrigin::OsLayer, ErrorKind::ImportNotFound));
340        let callback = &mut |data: ExportInfo| {
341            if data.name.as_ref() == name {
342                ret = Ok(data);
343                false
344            } else {
345                true
346            }
347        };
348        self.module_export_list_callback(info, callback.into())?;
349        ret
350    }
351
352    /// Finds a single section of a given module by its name
353    fn module_section_by_name(&mut self, info: &ModuleInfo, name: &str) -> Result<SectionInfo> {
354        let mut ret = Err(Error(ErrorOrigin::OsLayer, ErrorKind::ImportNotFound));
355        let callback = &mut |data: SectionInfo| {
356            if data.name.as_ref() == name {
357                ret = Ok(data);
358                false
359            } else {
360                true
361            }
362        };
363        self.module_section_list_callback(info, callback.into())?;
364        ret
365    }
366
367    /// Retrieves the OS info
368    fn info(&self) -> &OsInfo;
369}
370
371/// Information block about OS
372///
373/// This provides some basic information about the OS in question. `base`, and `size` may be
374/// omitted in some circumstances (lack of kernel, or privileges). But architecture should always
375/// be correct.
376#[repr(C)]
377#[derive(Clone, Debug)]
378#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
379#[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))]
380pub struct OsInfo {
381    /// Base address of the OS kernel
382    pub base: Address,
383    /// Size of the OS kernel
384    pub size: umem,
385    /// System architecture
386    pub arch: ArchitectureIdent,
387}