diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index a2a45969..4454fcc3 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -206,6 +206,10 @@ pub enum ProgramError { /// program name name: String, }, + + /// An error occurred while working with IO. + #[error(transparent)] + IOError(#[from] io::Error), } /// A [`Program`] file descriptor. diff --git a/aya/src/programs/probe.rs b/aya/src/programs/probe.rs index e41ea603..f595ca53 100644 --- a/aya/src/programs/probe.rs +++ b/aya/src/programs/probe.rs @@ -2,14 +2,15 @@ use libc::pid_t; use std::{ fs::{self, OpenOptions}, io::{self, Write}, + path::Path, process, }; use crate::{ programs::{ kprobe::KProbeError, perf_attach, perf_attach::PerfLink, perf_attach_debugfs, - trace_point::read_sys_fs_trace_point_id, uprobe::UProbeError, Link, ProgramData, - ProgramError, + trace_point::read_sys_fs_trace_point_id, uprobe::UProbeError, utils::find_tracefs_path, + Link, ProgramData, ProgramError, }, sys::{kernel_version, perf_event_open_probe, perf_event_open_trace_point}, }; @@ -60,10 +61,12 @@ pub(crate) fn attach>( pub(crate) fn detach_debug_fs(kind: ProbeKind, event_alias: &str) -> Result<(), ProgramError> { use ProbeKind::*; + let tracefs = find_tracefs_path()?; + match kind { - KProbe | KRetProbe => delete_probe_event(kind, event_alias) + KProbe | KRetProbe => delete_probe_event(tracefs, kind, event_alias) .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?, - UProbe | URetProbe => delete_probe_event(kind, event_alias) + UProbe | URetProbe => delete_probe_event(tracefs, kind, event_alias) .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?, }; @@ -115,15 +118,17 @@ fn create_as_trace_point( ) -> Result<(i32, String), ProgramError> { use ProbeKind::*; + let tracefs = find_tracefs_path()?; + let event_alias = match kind { - KProbe | KRetProbe => create_probe_event(kind, name, offset) + KProbe | KRetProbe => create_probe_event(tracefs, kind, name, offset) .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?, - UProbe | URetProbe => create_probe_event(kind, name, offset) + UProbe | URetProbe => create_probe_event(tracefs, kind, name, offset) .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?, }; let category = format!("{}s", kind.pmu()); - let tpid = read_sys_fs_trace_point_id(&category, &event_alias)?; + let tpid = read_sys_fs_trace_point_id(tracefs, &category, &event_alias)?; let fd = perf_event_open_trace_point(tpid, pid).map_err(|(_code, io_error)| { ProgramError::SyscallError { call: "perf_event_open".to_owned(), @@ -135,13 +140,14 @@ fn create_as_trace_point( } fn create_probe_event( + tracefs: &Path, kind: ProbeKind, fn_name: &str, offset: u64, ) -> Result { use ProbeKind::*; - let events_file_name = format!("/sys/kernel/debug/tracing/{}_events", kind.pmu()); + let events_file_name = tracefs.join(format!("{}_events", kind.pmu())); let probe_type_prefix = match kind { KProbe | UProbe => 'p', KRetProbe | URetProbe => 'r', @@ -170,20 +176,24 @@ fn create_probe_event( let mut events_file = OpenOptions::new() .append(true) .open(&events_file_name) - .map_err(|e| (events_file_name.clone(), e))?; + .map_err(|e| (events_file_name.display().to_string(), e))?; events_file .write_all(probe.as_bytes()) - .map_err(|e| (events_file_name.clone(), e))?; + .map_err(|e| (events_file_name.display().to_string(), e))?; Ok(event_alias) } -fn delete_probe_event(kind: ProbeKind, event_alias: &str) -> Result<(), (String, io::Error)> { - let events_file_name = format!("/sys/kernel/debug/tracing/{}_events", kind.pmu()); +fn delete_probe_event( + tracefs: &Path, + kind: ProbeKind, + event_alias: &str, +) -> Result<(), (String, io::Error)> { + let events_file_name = tracefs.join(format!("{}_events", kind.pmu())); - let events = - fs::read_to_string(&events_file_name).map_err(|e| (events_file_name.clone(), e))?; + let events = fs::read_to_string(&events_file_name) + .map_err(|e| (events_file_name.display().to_string(), e))?; let found = events.lines().any(|line| line.contains(event_alias)); @@ -191,13 +201,13 @@ fn delete_probe_event(kind: ProbeKind, event_alias: &str) -> Result<(), (String, let mut events_file = OpenOptions::new() .append(true) .open(&events_file_name) - .map_err(|e| (events_file_name.to_string(), e))?; + .map_err(|e| (events_file_name.display().to_string(), e))?; let rm = format!("-:{event_alias}\n"); events_file .write_all(rm.as_bytes()) - .map_err(|e| (events_file_name.to_string(), e))?; + .map_err(|e| (events_file_name.display().to_string(), e))?; } Ok(()) diff --git a/aya/src/programs/trace_point.rs b/aya/src/programs/trace_point.rs index a3480c27..d4bf158d 100644 --- a/aya/src/programs/trace_point.rs +++ b/aya/src/programs/trace_point.rs @@ -1,5 +1,5 @@ //! Tracepoint programs. -use std::{fs, io}; +use std::{fs, io, path::Path}; use thiserror::Error; use crate::{ @@ -7,6 +7,7 @@ use crate::{ programs::{ define_link_wrapper, load_program, perf_attach::{perf_attach, PerfLink, PerfLinkId}, + utils::find_tracefs_path, ProgramData, ProgramError, }, sys::perf_event_open_trace_point, @@ -77,7 +78,8 @@ impl TracePoint { /// /// The returned value can be used to detach, see [TracePoint::detach]. pub fn attach(&mut self, category: &str, name: &str) -> Result { - let id = read_sys_fs_trace_point_id(category, name)?; + let tracefs = find_tracefs_path()?; + let id = read_sys_fs_trace_point_id(tracefs, category, name)?; let fd = perf_event_open_trace_point(id, None).map_err(|(_code, io_error)| { ProgramError::SyscallError { call: "perf_event_open".to_owned(), @@ -114,20 +116,21 @@ define_link_wrapper!( ); pub(crate) fn read_sys_fs_trace_point_id( + tracefs: &Path, category: &str, name: &str, ) -> Result { - let file = format!("/sys/kernel/debug/tracing/events/{category}/{name}/id"); + let file = tracefs.join("events").join(category).join(name).join("id"); let id = fs::read_to_string(&file).map_err(|io_error| TracePointError::FileError { - filename: file.clone(), + filename: file.display().to_string(), io_error, })?; let id = id .trim() .parse::() .map_err(|error| TracePointError::FileError { - filename: file.clone(), + filename: file.display().to_string(), io_error: io::Error::new(io::ErrorKind::Other, error), })?; diff --git a/aya/src/programs/utils.rs b/aya/src/programs/utils.rs index 56af2a0f..143e8664 100644 --- a/aya/src/programs/utils.rs +++ b/aya/src/programs/utils.rs @@ -1,5 +1,5 @@ //! Common functions shared between multiple eBPF program types. -use std::{ffi::CStr, os::unix::io::RawFd}; +use std::{ffi::CStr, io, os::unix::io::RawFd, path::Path}; use crate::{ programs::{FdLink, Link, ProgramData, ProgramError}, @@ -22,3 +22,26 @@ pub(crate) fn attach_raw_tracepoint>( program_data.links.insert(FdLink::new(pfd).into()) } + +/// Find tracefs filesystem path +pub(crate) fn find_tracefs_path() -> Result<&'static Path, ProgramError> { + lazy_static::lazy_static! { + static ref TRACE_FS: Option<&'static Path> = { + let known_mounts = [ + Path::new("/sys/kernel/tracing"), + Path::new("/sys/kernel/debug/tracing"), + ]; + + for mount in known_mounts { + if mount.exists() { + return Some(mount); + } + } + None + }; + } + + TRACE_FS + .as_deref() + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "tracefs not found").into()) +}