memflow_native/linux/
mod.rs1use memflow::os::process::*;
2use memflow::prelude::v1::*;
3
4use libc::pid_t;
5use log::error;
6
7use procfs::KernelModule;
8
9use itertools::Itertools;
10
11pub mod mem;
12use mem::ProcessVirtualMemory;
13
14pub mod process;
15pub use process::LinuxProcess;
16
17pub struct LinuxOs {
18 info: OsInfo,
19 cached_modules: Vec<KernelModule>,
20}
21
22impl LinuxOs {
23 pub fn new(_: &OsArgs) -> Result<Self> {
24 Ok(Default::default())
25 }
26}
27
28impl Clone for LinuxOs {
29 fn clone(&self) -> Self {
30 Self {
31 info: self.info.clone(),
32 cached_modules: vec![],
33 }
34 }
35}
36
37impl Default for LinuxOs {
38 fn default() -> Self {
39 let info = OsInfo {
40 base: Address::NULL,
41 size: 0,
42 arch: ArchitectureIdent::X86(64, false),
43 };
44
45 Self {
46 info,
47 cached_modules: vec![],
48 }
49 }
50}
51
52impl Os for LinuxOs {
53 type ProcessType<'a> = LinuxProcess;
54 type IntoProcessType = LinuxProcess;
55
56 fn process_address_list_callback(&mut self, mut callback: AddressCallback) -> Result<()> {
60 procfs::process::all_processes()
61 .map_err(|e| {
62 error!("{e}");
63 Error(ErrorOrigin::OsLayer, ErrorKind::UnableToReadDir)
64 })?
65 .filter_map(|p| p.map(|p| p.pid() as usize).ok())
66 .map(Address::from)
67 .take_while(|a| callback.call(*a))
68 .for_each(|_| {});
69
70 Ok(())
71 }
72
73 fn process_info_by_address(&mut self, address: Address) -> Result<ProcessInfo> {
75 self.process_info_by_pid(address.to_umem() as _)
76 }
77
78 fn process_info_by_pid(&mut self, pid: Pid) -> Result<ProcessInfo> {
79 let proc = procfs::process::Process::new(pid as pid_t)
80 .map_err(|_| Error(ErrorOrigin::OsLayer, ErrorKind::UnableToReadDir))?;
81
82 let command_line = proc
83 .cmdline()
84 .ok()
85 .map(|v| v.join(" ").split('\0').collect_vec().join(" "))
86 .unwrap_or_else(String::new)
87 .into();
88
89 let path = proc
90 .cmdline()
91 .ok()
92 .and_then(|l| {
93 l.first()
94 .map(|s| s.split('\0').next().unwrap_or("").to_string())
95 })
96 .unwrap_or_else(|| {
97 proc.status()
98 .ok()
99 .map(|s| s.name)
100 .unwrap_or_else(|| "unknown".to_string())
101 });
102
103 let name = path.split(&['/', '\\'][..]).last().unwrap().into();
104
105 let path = path.into();
106
107 Ok(ProcessInfo {
108 address: (proc.pid() as umem).into(),
109 pid,
110 command_line,
111 path,
112 name,
113 sys_arch: ArchitectureIdent::X86(64, false),
114 proc_arch: ArchitectureIdent::X86(64, false),
115 state: ProcessState::Alive,
116 dtb1: Address::invalid(),
118 dtb2: Address::invalid(),
119 })
120 }
121
122 fn process_by_info(&mut self, info: ProcessInfo) -> Result<Self::ProcessType<'_>> {
126 LinuxProcess::try_new(info)
127 }
128
129 fn into_process_by_info(mut self, info: ProcessInfo) -> Result<Self::IntoProcessType> {
133 self.process_by_info(info)
134 }
135
136 fn module_address_list_callback(&mut self, mut callback: AddressCallback) -> Result<()> {
142 self.cached_modules = procfs::modules()
143 .map_err(|_| Error(ErrorOrigin::OsLayer, ErrorKind::UnableToReadDir))?
144 .into_values()
145 .collect();
146
147 (0..self.cached_modules.len())
148 .map(Address::from)
149 .take_while(|a| callback.call(*a))
150 .for_each(|_| {});
151
152 Ok(())
153 }
154
155 fn module_by_address(&mut self, address: Address) -> Result<ModuleInfo> {
160 self.cached_modules
161 .get(address.to_umem() as usize)
162 .map(|km| ModuleInfo {
163 address,
164 size: km.size as umem,
165 base: Address::NULL,
166 name: km
167 .name
168 .split('/')
169 .last()
170 .or(Some(""))
171 .map(ReprCString::from)
172 .unwrap(),
173 arch: self.info.arch,
174 path: km.name.clone().into(),
175 parent_process: Address::INVALID,
176 })
177 .ok_or(Error(ErrorOrigin::OsLayer, ErrorKind::NotFound))
178 }
179
180 fn primary_module_address(&mut self) -> Result<Address> {
184 Ok(Address::from(0))
186 }
187
188 fn module_import_list_callback(
190 &mut self,
191 _info: &ModuleInfo,
192 _callback: ImportCallback,
193 ) -> Result<()> {
194 Err(Error(ErrorOrigin::OsLayer, ErrorKind::NotImplemented))
196 }
197
198 fn module_export_list_callback(
200 &mut self,
201 _info: &ModuleInfo,
202 _callback: ExportCallback,
203 ) -> Result<()> {
204 Err(Error(ErrorOrigin::OsLayer, ErrorKind::NotImplemented))
206 }
207
208 fn module_section_list_callback(
210 &mut self,
211 _info: &ModuleInfo,
212 _callback: SectionCallback,
213 ) -> Result<()> {
214 Err(Error(ErrorOrigin::OsLayer, ErrorKind::NotImplemented))
216 }
217
218 fn info(&self) -> &OsInfo {
220 &self.info
221 }
222}