Skip to content

Commit cc0f17b

Browse files
committed
Make OS module handling stateless, mark kernel primary module unsupported, and harden iovec batching invariants
1 parent ebc20f0 commit cc0f17b

2 files changed

Lines changed: 26 additions & 15 deletions

File tree

src/linux/mem.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use std::ffi::c_void;
88
#[repr(transparent)]
99
struct IoSendVec(iovec);
1010

11+
// Safety: IoSendVec stores transient iovec pointers that are only constructed and
12+
// consumed within &mut self operations; no cross-thread aliasing is exposed.
1113
unsafe impl Send for IoSendVec {}
1214

1315
#[derive(Clone)]
@@ -122,7 +124,13 @@ impl ProcessVirtualMemory {
122124
let mut elem = inp.next();
123125

124126
'exit: while let Some(CTup3(a, m, b)) = elem {
125-
let (cnt, (liov, (riov, meta))) = iov_next.unwrap();
127+
let Some((cnt, (liov, (riov, meta)))) = iov_next else {
128+
debug_assert!(
129+
false,
130+
"iov_next must exist while current input element is present"
131+
);
132+
break;
133+
};
126134

127135
let iov_len = b.len();
128136

src/linux/mod.rs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,27 @@ pub use process::LinuxProcess;
1616

1717
pub struct LinuxOs {
1818
info: OsInfo,
19-
cached_modules: Vec<KernelModule>,
2019
}
2120

2221
impl LinuxOs {
2322
pub fn new(_: &OsArgs) -> Result<Self> {
2423
Ok(Default::default())
2524
}
25+
26+
fn kernel_modules_sorted(&self) -> Result<Vec<KernelModule>> {
27+
let mut modules: Vec<KernelModule> = procfs::modules()
28+
.map_err(|_| Error(ErrorOrigin::OsLayer, ErrorKind::UnableToReadDir))?
29+
.into_values()
30+
.collect();
31+
modules.sort_by(|a, b| a.name.cmp(&b.name));
32+
Ok(modules)
33+
}
2634
}
2735

2836
impl Clone for LinuxOs {
2937
fn clone(&self) -> Self {
3038
Self {
3139
info: self.info.clone(),
32-
cached_modules: vec![],
3340
}
3441
}
3542
}
@@ -42,10 +49,7 @@ impl Default for LinuxOs {
4249
arch: ArchitectureIdent::X86(64, false),
4350
};
4451

45-
Self {
46-
info,
47-
cached_modules: vec![],
48-
}
52+
Self { info }
4953
}
5054
}
5155

@@ -139,12 +143,9 @@ impl Os for LinuxOs {
139143
/// # Arguments
140144
/// * `callback` - where to pass each matching module to. This is an opaque callback.
141145
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+
let modules = self.kernel_modules_sorted()?;
146147

147-
(0..self.cached_modules.len())
148+
(0..modules.len())
148149
.map(Address::from)
149150
.take_while(|a| callback.call(*a))
150151
.for_each(|_| {});
@@ -157,7 +158,9 @@ impl Os for LinuxOs {
157158
/// # Arguments
158159
/// * `address` - address where module's information resides in
159160
fn module_by_address(&mut self, address: Address) -> Result<ModuleInfo> {
160-
self.cached_modules
161+
let modules = self.kernel_modules_sorted()?;
162+
163+
modules
161164
.get(address.to_umem() as usize)
162165
.map(|km| ModuleInfo {
163166
address,
@@ -181,8 +184,8 @@ impl Os for LinuxOs {
181184
///
182185
/// This will generally be for the initial executable that was run
183186
fn primary_module_address(&mut self) -> Result<Address> {
184-
// TODO: Is it always 0th mod?
185-
Ok(Address::from(0))
187+
// TODO: Add Linux kernel image discovery via /proc/kallsyms and/or /sys/kernel/sections.
188+
Err(Error(ErrorOrigin::OsLayer, ErrorKind::NotSupported))
186189
}
187190

188191
/// Retrieves a list of all imports of a given module

0 commit comments

Comments
 (0)