ソースを参照

aya: uprobe attach: use mmap instead of reading whole binaries to memory

Omri Steiner 2 ヶ月 前
コミット
90d5604877
2 ファイル変更27 行追加6 行削除
  1. 5 4
      aya/src/programs/uprobe.rs
  2. 22 2
      aya/src/util.rs

+ 5 - 4
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<u64, ResolveSymbolError> {
-    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<u64, ResolveSymbolError>
                 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)?;
 

+ 22 - 2
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<Self, io::Error> {
+        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<c_void> {
         self.ptr
     }