pub(crate) mod trampolines;
pub(crate) mod vdso;
use libc;
use std::collections::HashMap;
use crate::trampolines::*;
use crate::vdso::vDSO;
#[derive(Debug, Clone, Copy)]
struct Range {
start: usize,
end: usize,
writable: bool,
}
pub(crate) type Time = libc::time_t;
pub struct TimeSpec {
pub seconds: Time,
pub nanos: i64, }
pub struct TimeVal {
pub seconds: Time,
pub micros: i64, }
pub type TimeCb = fn() -> Time;
pub type ClockGetTimeCb = fn(clockid: i32) -> TimeSpec;
pub type ClockGetResCb = fn(i32) -> TimeSpec;
pub type ClockGetTimeOfDayCb = fn() -> TimeVal;
pub struct ClockController {}
impl ClockController {
pub fn is_overwritten() -> bool {
let r = vDSO::find().unwrap();
r.writable
}
pub fn restore() {
let r = vDSO::find().unwrap();
if !r.writable {
return;
}
if let Ok(b) = BACKUP_VDSO.lock() {
if b.len() == 0 {
return;
}
unsafe {
std::ptr::copy_nonoverlapping(b.as_ptr(), r.start as *mut u8, b.len());
libc::mprotect(
r.start as *mut libc::c_void,
r.end - r.start,
libc::PROT_EXEC | libc::PROT_READ,
);
}
}
}
pub fn overwrite(
clockgettime_cb: Option<ClockGetTimeCb>,
time_cb: Option<TimeCb>,
clock_getres: Option<ClockGetResCb>,
gettimeofday: Option<ClockGetTimeOfDayCb>,
) {
let mut mapping: HashMap<&'static str, u64> = HashMap::new();
if let Some(g) = clockgettime_cb {
let mut w = CLOCK_GT_CB.write().unwrap();
*w = Some(g);
let addr = my_clockgettime as *const () as u64;
mapping.insert("clock_gettime", addr);
mapping.insert("__vdso_clock_gettime", addr);
}
if let Some(g) = time_cb {
let mut w = TIME_CB.write().unwrap();
*w = Some(g);
let addr = my_time as *const () as u64;
mapping.insert("time", addr);
mapping.insert("__vdso_time", addr);
}
if let Some(g) = clock_getres {
let mut w = CLOCK_RES_CB.write().unwrap();
*w = Some(g);
let addr = my_clockgetres as *const () as u64;
mapping.insert("clock_getres", addr);
mapping.insert("__vdso_clock_getres", addr);
}
if let Some(g) = gettimeofday {
let mut w = CLOCK_GTOD_CB.write().unwrap();
*w = Some(g);
let addr = my_gettimeofday as *const () as u64;
mapping.insert("gettimeofday", addr);
mapping.insert("__vdso_gettimeofday", addr);
}
let r = vDSO::find().unwrap();
unsafe {
libc::mprotect(
r.start as *mut libc::c_void,
r.end - r.start,
libc::PROT_EXEC | libc::PROT_WRITE | libc::PROT_READ,
);
}
let b = vDSO::read(&r);
BACKUP_VDSO.lock().unwrap().clear();
BACKUP_VDSO.lock().unwrap().append(&mut b.clone());
ClockController::mess_vdso(b, &r, mapping);
}
fn mess_vdso(buf: Vec<u8>, range: &Range, mapping: HashMap<&'static str, u64>) {
for ds in vDSO::dynsyms(buf) {
if let Some(dst_addr) = mapping.get(ds.name.as_str()) {
vDSO::overwrite(range, ds.address, *dst_addr, ds.size as usize);
}
}
}
}