use crate::{
api::{
messages::{CbAction, Event, EventInner, RegEvent},
ArgsBuilder, Client, Command, Response,
},
ctx,
plugin::Plugin,
utils, Error, Result, TargetPtr,
};
use std::collections::HashMap;
struct State {
name: String,
_fd: isize,
mmapped: usize,
}
impl State {
pub fn new(name: String, fd: isize) -> Self {
Self {
name,
_fd: fd,
mmapped: 0,
}
}
pub fn is_so(&self) -> bool {
self.name.ends_with(".so")
|| self.name.ends_with(".so.0")
|| self.name.ends_with(".so.1")
|| self.name.ends_with(".so.2")
|| self.name.ends_with(".so.3")
|| self.name.ends_with(".so.4")
|| self.name.ends_with(".so.5")
|| self.name.ends_with(".so.6")
|| self.name.ends_with(".so.7")
|| self.name.ends_with(".so.8")
|| self.name.ends_with(".so.9")
}
}
pub(crate) struct DlopenDetect {
mmapped: HashMap<isize, State>,
}
impl DlopenDetect {
fn new() -> Self {
let mmapped = HashMap::new();
Self { mmapped }
}
pub fn dependecies() -> &'static [Plugin] {
&[Plugin::Files]
}
pub fn init(client: crate::Client) -> Result<ctx::Secondary<DlopenDetect, Error>> {
let data = Self::new();
let mut ctx = ctx::Secondary::new_second(client, data)?;
let client = ctx.client_mut();
let mmap = client.resolve_syscall("mmap")?;
ctx.set_syscall_hook_entry(mmap, |cl, sys| {
if sys.is_entry() {
let fd = sys.args[4].raw_value();
let fd = fd.as_isize();
if let Some(r) = cl.data_mut().mmapped.get_mut(&fd) {
r.mmapped += 1;
}
} else {
}
Ok(CbAction::None)
});
ctx.set_event_handler(|cl, event| {
match event.event {
EventInner::FileOpened { fname, fd } => {
let ins = State::new(fname, fd);
if ins.is_so() {
cl.data_mut().mmapped.insert(fd, ins);
}
}
EventInner::FileClosed { fname, fd } => {
if let Some(r) = cl.data_mut().mmapped.remove(&fd) {
if r.mmapped > 0 {
let tid = event.tid.unwrap_or(0);
let event = EventInner::Dlopen { fname };
let event = Event::new_attached(tid, event);
log::debug!("sending dlopen event {event:?}");
cl.client_mut().send_event(event)?;
}
}
}
_ => {}
}
Ok(())
});
Ok(ctx)
}
}