diff options
-rw-r--r-- | Cargo.lock | 3 | ||||
-rw-r--r-- | Cargo.toml | 8 | ||||
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/main.rs | 46 |
4 files changed, 46 insertions, 13 deletions
@@ -11,8 +11,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "goblin" version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b1800b95efee8ad4ef04517d4d69f8e209e763b1668f1179aeeedd0e454da55" +source = "git+https://github.com/johannst/goblin?branch=elf-gnu-symbol-versioning-utils#8716406638b4bd8da1751352678ea9aa749c534d" dependencies = [ "log", "plain", @@ -6,4 +6,10 @@ edition = "2018" [dependencies] libc = "0.2" -goblin = { version = "0.4", default-features = false, features = ["std", "elf32", "elf64", "endian_fd"] } + +[dependencies.goblin] +#version = "0.4" +git = "https://github.com/johannst/goblin" +branch = "elf-gnu-symbol-versioning-utils" +default-features = false +features = ["std", "elf32", "elf64", "endian_fd"] @@ -17,6 +17,8 @@ pub enum Error { /// Requested symbol not found in the ELF file. /// Captures the name of the requested symbol. SymbolNotFound(String), + /// Error during symbol version lookup. + SymbolVersionError(String), } /// Representation of an 64-bit virtual address. diff --git a/src/main.rs b/src/main.rs index b82abdc..2ee1d66 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,12 +44,12 @@ unsafe fn copy_vdso(vdso: &MapEntry) -> Option<Mmap> { /// # Safety: /// The caller must guarantee that the `vdso` argument describes a valid virtual address range by /// its `address` and `length` fields. -/// -/// # Note: -/// Currently the version of the symbol is not checked, technically this is an error which can be -/// fatal in case of a binary incompatibility, but that's accepted for this PoC. #[allow(unused_unsafe)] -unsafe fn get_vdso_sym(vdso: &MapEntry, symbol_name: &str) -> Result<VirtAddr, Error> { +unsafe fn get_vdso_sym( + vdso: &MapEntry, + symbol_name: &str, + symbol_version: &str, +) -> Result<VirtAddr, Error> { // Turn `vdso` maps entry into slice of bytes. let bytes = { let ptr = vdso.addr as *const u8; @@ -75,13 +75,39 @@ unsafe fn get_vdso_sym(vdso: &MapEntry, symbol_name: &str) -> Result<VirtAddr, E assert_ne!(dso_base, 0, "If the dso base address is 0 that means the symbols contain absolute addresses, we don't want to support that!"); // Try to find the requested symbol. - let sym = elf + let (idx, sym) = elf .dynsyms .iter() - .filter(|sym| sym.is_function()) - .find(|sym| matches!(elf.dynstrtab.get_at(sym.st_name), Some(sym) if sym == symbol_name)) + .enumerate() + .filter(|(_, sym)| sym.is_function()) + .find( + |(_, sym)| matches!(elf.dynstrtab.get_at(sym.st_name), Some(sym) if sym == symbol_name), + ) .ok_or(Error::SymbolNotFound(symbol_name.into()))?; + let found_symbol_version = elf + .versym + .ok_or(Error::SymbolVersionError( + "Missing ELF section Versym".into(), + ))? + .get_at(idx) + .ok_or(Error::SymbolVersionError(format!( + "No Versym entry for symbol with idx {} found", + idx + )))? + .find_version(elf.verdef.as_ref(), elf.verneed.as_ref()) + .ok_or(Error::SymbolVersionError(format!( + "No symbol version string found for symbol with idx {}", + idx + )))?; + + if found_symbol_version != symbol_version { + return Err(Error::SymbolVersionError(format!( + "Symbol version missmatch, want {} but found {}", + symbol_version, found_symbol_version + ))); + }; + // Compute the absolute virtual address of the requested symbol. Ok(VirtAddr(dso_base + sym.st_value)) } @@ -105,9 +131,9 @@ fn main() -> Result<(), Error> { let (orig_sym_addr, copy_sym_addr) = unsafe { // SAFETY: orig_vdso describes a valid memory region as we got it from /proc/self/maps. - let orig = get_vdso_sym(&orig_vdso, "__vdso_gettimeofday")?; + let orig = get_vdso_sym(&orig_vdso, "__vdso_gettimeofday", "LINUX_2.6")?; // SAFETY: copy_vdso describes a valid and owned memory allocation. - let copy = get_vdso_sym(©_vdso.as_ref(), "__vdso_gettimeofday")?; + let copy = get_vdso_sym(©_vdso.as_ref(), "__vdso_gettimeofday", "LINUX_2.6")?; (orig, copy) }; |