1pub(crate) mod trampolines;
42pub(crate) mod vdso;
43
44use libc;
45use std::collections::HashMap;
46
47use crate::trampolines::*;
48use crate::vdso::vDSO;
49
50#[derive(Debug, Clone, Copy)]
51struct Range {
52 start: usize,
53 end: usize,
54 writable: bool,
55}
56
57pub(crate) type Time = libc::time_t; pub struct TimeSpec {
62 pub seconds: Time,
63 pub nanos: i64, }
65
66pub struct TimeVal {
69 pub seconds: Time,
70 pub micros: i64, }
72
73pub type TimeCb = fn() -> Time;
74
75pub type ClockGetTimeCb = fn(clockid: i32) -> TimeSpec;
77
78pub type ClockGetResCb = fn(i32) -> TimeSpec;
80
81pub type ClockGetTimeOfDayCb = fn() -> TimeVal; pub struct ClockController {}
85
86impl ClockController {
87 pub fn is_overwritten() -> bool {
88 let r = vDSO::find().unwrap();
90 r.writable
91 }
92 pub fn restore() {
93 let r = vDSO::find().unwrap();
95 if !r.writable {
96 return;
97 }
98 if let Ok(b) = BACKUP_VDSO.lock() {
99 if b.len() == 0 {
100 return;
101 }
102 unsafe {
103 std::ptr::copy_nonoverlapping(b.as_ptr(), r.start as *mut u8, b.len());
104 libc::mprotect(
105 r.start as *mut libc::c_void,
106 r.end - r.start,
107 libc::PROT_EXEC | libc::PROT_READ,
108 );
109 }
110 }
111 }
112
113 pub fn overwrite(
114 clockgettime_cb: Option<ClockGetTimeCb>,
115 time_cb: Option<TimeCb>,
116 clock_getres: Option<ClockGetResCb>,
117 gettimeofday: Option<ClockGetTimeOfDayCb>,
118 ) {
119 let mut mapping: HashMap<&'static str, u64> = HashMap::new();
121 if let Some(g) = clockgettime_cb {
122 let mut w = CLOCK_GT_CB.write().unwrap();
123 *w = Some(g);
124 let addr = my_clockgettime as *const () as u64;
125 mapping.insert("clock_gettime", addr);
126 mapping.insert("__vdso_clock_gettime", addr);
127 }
128 if let Some(g) = time_cb {
129 let mut w = TIME_CB.write().unwrap();
130 *w = Some(g);
131 let addr = my_time as *const () as u64;
132 mapping.insert("time", addr);
133 mapping.insert("__vdso_time", addr);
134 }
135 if let Some(g) = clock_getres {
136 let mut w = CLOCK_RES_CB.write().unwrap();
137 *w = Some(g);
138 let addr = my_clockgetres as *const () as u64;
139 mapping.insert("clock_getres", addr);
140 mapping.insert("__vdso_clock_getres", addr);
141 }
142 if let Some(g) = gettimeofday {
143 let mut w = CLOCK_GTOD_CB.write().unwrap();
144 *w = Some(g);
145 let addr = my_gettimeofday as *const () as u64;
146 mapping.insert("gettimeofday", addr);
147 mapping.insert("__vdso_gettimeofday", addr);
148 }
149
150 let r = vDSO::find().unwrap();
151 unsafe {
152 libc::mprotect(
153 r.start as *mut libc::c_void,
154 r.end - r.start,
155 libc::PROT_EXEC | libc::PROT_WRITE | libc::PROT_READ,
156 );
157 }
158 let b = vDSO::read(&r);
159 BACKUP_VDSO.lock().unwrap().clear();
160 BACKUP_VDSO.lock().unwrap().append(&mut b.clone());
161 ClockController::mess_vdso(b, &r, mapping);
162 }
163 fn mess_vdso(buf: Vec<u8>, range: &Range, mapping: HashMap<&'static str, u64>) {
164 for ds in vDSO::dynsyms(buf) {
165 if let Some(dst_addr) = mapping.get(ds.name.as_str()) {
166 vDSO::overwrite(range, ds.address, *dst_addr, ds.size as usize);
168 }
169 }
170 }
171}