From 90d56048777ff571293a99450201562532fcaa7f Mon Sep 17 00:00:00 2001 From: Omri Steiner Date: Fri, 2 May 2025 18:24:30 +0200 Subject: [PATCH] aya: uprobe attach: use mmap instead of reading whole binaries to memory --- aya/src/programs/uprobe.rs | 9 +++++---- aya/src/util.rs | 24 ++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/aya/src/programs/uprobe.rs b/aya/src/programs/uprobe.rs index df936aae..e733e3f4 100644 --- a/aya/src/programs/uprobe.rs +++ b/aya/src/programs/uprobe.rs @@ -24,6 +24,7 @@ use crate::{ probe::{OsStringExt as _, ProbeKind, attach}, }, sys::bpf_link_get_info_by_fd, + util::MMap, }; const LD_SO_CACHE_FILE: &str = "/etc/ld.so.cache"; @@ -686,15 +687,15 @@ fn find_symbol_in_object<'a>(obj: &'a object::File<'a>, symbol: &str) -> Option< } fn resolve_symbol(path: &Path, symbol: &str) -> Result { - let data = fs::read(path)?; - let obj = object::read::File::parse(&*data)?; + let data = MMap::map_copy_read_only(path)?; + let obj = object::read::File::parse(data.as_ref())?; if let Some(sym) = find_symbol_in_object(&obj, symbol) { symbol_translated_address(&obj, sym, symbol) } else { // Only search in the debug object if the symbol was not found in the main object let debug_path = find_debug_path_in_object(&obj, path, symbol)?; - let debug_data = fs::read(&debug_path).map_err(|e| { + let debug_data = MMap::map_copy_read_only(&debug_path).map_err(|e| { ResolveSymbolError::DebuglinkAccessError( debug_path .to_str() @@ -703,7 +704,7 @@ fn resolve_symbol(path: &Path, symbol: &str) -> Result e, ) })?; - let debug_obj = object::read::File::parse(&*debug_data)?; + let debug_obj = object::read::File::parse(debug_data.as_ref())?; verify_build_ids(&obj, &debug_obj, symbol)?; diff --git a/aya/src/util.rs b/aya/src/util.rs index 30fdb112..428f1a35 100644 --- a/aya/src/util.rs +++ b/aya/src/util.rs @@ -8,14 +8,16 @@ use std::{ io::{self, BufRead, BufReader}, mem, num::ParseIntError, - os::fd::BorrowedFd, + os::fd::{AsFd as _, BorrowedFd}, + path::Path, ptr, slice, str::{FromStr, Utf8Error}, }; use aya_obj::generated::{TC_H_MAJ_MASK, TC_H_MIN_MASK}; use libc::{ - _SC_PAGESIZE, MAP_FAILED, c_int, c_void, if_nametoindex, off_t, sysconf, uname, utsname, + _SC_PAGESIZE, MAP_FAILED, MAP_PRIVATE, PROT_READ, c_int, c_void, if_nametoindex, off_t, + sysconf, uname, utsname, }; use log::warn; @@ -478,6 +480,24 @@ impl MMap { } } + /// Maps the file at `path` for reading, using `mmap` with `MAP_PRIVATE`. + pub(crate) fn map_copy_read_only(path: &Path) -> Result { + let file = fs::File::open(path)?; + Self::new( + file.as_fd(), + file.metadata()?.len().try_into().map_err(|e| { + io::Error::new( + io::ErrorKind::FileTooLarge, + format!("file too large to mmap: {e}"), + ) + })?, + PROT_READ, + MAP_PRIVATE, + 0, + ) + .map_err(|SyscallError { io_error, call: _ }| io_error) + } + pub(crate) fn ptr(&self) -> ptr::NonNull { self.ptr }