aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Stoelp <johannes.stoelp@gmail.com>2021-08-21 23:53:02 +0200
committerJohannes Stoelp <johannes.stoelp@gmail.com>2021-08-21 23:53:02 +0200
commitf484179454761d3a35f6d98751d62ccebbc986aa (patch)
tree08688d9ef0a1eabd7ea942280649fd7ef90df21e
parent225e2d46b64d84aa08959036a1a6d03f1a22ef56 (diff)
downloadvdso-proxy-poc-f484179454761d3a35f6d98751d62ccebbc986aa.tar.gz
vdso-proxy-poc-f484179454761d3a35f6d98751d62ccebbc986aa.zip
add check for symbol version
-rw-r--r--Cargo.lock3
-rw-r--r--Cargo.toml8
-rw-r--r--src/lib.rs2
-rw-r--r--src/main.rs46
4 files changed, 46 insertions, 13 deletions
diff --git a/Cargo.lock b/Cargo.lock
index bdbb878..24f632e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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",
diff --git a/Cargo.toml b/Cargo.toml
index d7eb41d..a8975b2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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"]
diff --git a/src/lib.rs b/src/lib.rs
index 18c1b74..e20207d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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(&copy_vdso.as_ref(), "__vdso_gettimeofday")?;
+ let copy = get_vdso_sym(&copy_vdso.as_ref(), "__vdso_gettimeofday", "LINUX_2.6")?;
(orig, copy)
};