Skip to content

Commit

Permalink
Read the auxv in library constructor
Browse files Browse the repository at this point in the history
Having `putenv()` called overwrites the auxiliary vector, giving garbage
values for the vDSO base address and the page size.

Reading these values from the auxiliary constructor during the
startup phase, before any actual program code executes prevents the
issue.

The auxiliary vector is only read once and stored as a static variable.
  • Loading branch information
DavidVentura committed Jan 4, 2024
1 parent a9ca342 commit 29d4791
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 6 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ path = "src/lib.rs"
name = "tpom"
path = "src/bin.rs"
[dependencies]
ctor = "0.2.6"
goblin = "0.6.0"
libc = "0.2.137"
libc = "0.2.151"

[dev-dependencies]
serial_test = "0.9.0"
Expand Down
19 changes: 14 additions & 5 deletions src/auxv.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::error::Error;
use ctor::ctor;

#[derive(Debug)]
#[derive(Debug, Copy, Clone)]
pub struct AuxVecValues {
pub(crate) vdso_base: usize,
pub(crate) page_size: usize,
Expand All @@ -25,6 +26,11 @@ unsafe fn get_auxv_ptr() -> *const usize {
}

pub(crate) fn read_aux_vec() -> Result<AuxVecValues, Box<dyn Error>> {
Ok(*AUX)
}
//#[cfg_attr(any(target_os = "linux"), link_section = ".init_array")]
#[ctor]
static AUX: AuxVecValues = {
// The auxiliary vector is an array of key:value tuples, represented as [usize, usize]
// The end is delimited by having the key == AT_NULL
let mut out = unsafe { get_auxv_ptr() };
Expand All @@ -43,9 +49,12 @@ pub(crate) fn read_aux_vec() -> Result<AuxVecValues, Box<dyn Error>> {
out = out.offset(2);
}
}
if ptr == 0 || pagesize == 0 {
panic!("wtf");
if ptr == 0 {
panic!("Could not find vDSO base");
}
Ok(AuxVecValues {vdso_base: ptr, page_size: pagesize})
}
if pagesize == 0 {
panic!("Could not find page size");
}
AuxVecValues {vdso_base: ptr, page_size: pagesize}
};

20 changes: 20 additions & 0 deletions tests/pub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,24 @@ mod tests {
backup.restore();
assert_eq!(time_a, time_b);
}

#[test]
#[serial]
fn it_works_after_putenv() {
unsafe {
libc::putenv(b"SOMETHING=VALUE\0".as_ptr() as *mut _);
}
let v = vdso::vDSO::read().unwrap();
let og = v
.entry(Kind::GetTime)
.ok_or("Could not find clock")
.unwrap();
let backup = og.overwrite(myclock);

let time_a = SystemTime::now();
std::thread::sleep(std::time::Duration::from_millis(1)); // clock in github actions is coarse
let time_b = SystemTime::now();
backup.restore();
assert_eq!(time_a, time_b);
}
}

0 comments on commit 29d4791

Please sign in to comment.