From c6c4ac7eeaf7e6cfa31ab0b949aa93b136eda91b Mon Sep 17 00:00:00 2001 From: banditopazzo Date: Thu, 22 Dec 2022 01:51:13 +0100 Subject: [PATCH 1/2] feat: get_tracefs function --- aya/src/programs/mod.rs | 4 ++++ aya/src/programs/probe.rs | 42 ++++++++++++++++++++------------- aya/src/programs/trace_point.rs | 14 +++++++---- aya/src/programs/utils.rs | 24 ++++++++++++++++++- 4 files changed, 62 insertions(+), 22 deletions(-) diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index a2a459694..828de7ba4 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -206,6 +206,10 @@ pub enum ProgramError { /// program name name: String, }, + + /// TraceFS not found. + #[error("tracefs non found")] + TraceFsNotFound, } /// A [`Program`] file descriptor. diff --git a/aya/src/programs/probe.rs b/aya/src/programs/probe.rs index e41ea6034..f5b0f9391 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::get_tracefs, 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 = get_tracefs()?; + 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 = get_tracefs()?; + 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 a3480c271..a5f25e1d2 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::{ @@ -12,6 +12,8 @@ use crate::{ sys::perf_event_open_trace_point, }; +use super::utils::get_tracefs; + /// The type returned when attaching a [`TracePoint`] fails. #[derive(Debug, Error)] pub enum TracePointError { @@ -77,7 +79,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 = get_tracefs()?; + 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 +117,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 56af2a0f3..e9c431b0b 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, os::unix::io::RawFd, path::Path}; use crate::{ programs::{FdLink, Link, ProgramData, ProgramError}, @@ -22,3 +22,25 @@ pub(crate) fn attach_raw_tracepoint>( program_data.links.insert(FdLink::new(pfd).into()) } + +// Get tracefs filesystem +pub(crate) fn get_tracefs() -> Result<&'static Path, ProgramError> { + lazy_static::lazy_static! { + static ref TRACE_FS: Option<&'static Path> = { + let mounts = [ + Path::new("/sys/kernel/tracing"), + Path::new("/sys/kernel/debug/tracing"), + ]; + + for mount in mounts { + if mount.exists() { + return Some(mount); + } + } + None + + }; + } + + TRACE_FS.as_deref().ok_or(ProgramError::TraceFsNotFound) +} From 48fdf5a250ce74516a02c0f34b0f359f7f9a4d63 Mon Sep 17 00:00:00 2001 From: banditopazzo Date: Tue, 10 Jan 2023 10:57:52 +0100 Subject: [PATCH 2/2] chore: tracefs review fixes --- aya/src/programs/mod.rs | 6 +++--- aya/src/programs/probe.rs | 8 ++++---- aya/src/programs/trace_point.rs | 5 ++--- aya/src/programs/utils.rs | 15 ++++++++------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 828de7ba4..4454fcc33 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -207,9 +207,9 @@ pub enum ProgramError { name: String, }, - /// TraceFS not found. - #[error("tracefs non found")] - TraceFsNotFound, + /// 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 f5b0f9391..f595ca53b 100644 --- a/aya/src/programs/probe.rs +++ b/aya/src/programs/probe.rs @@ -9,8 +9,8 @@ use std::{ use crate::{ programs::{ kprobe::KProbeError, perf_attach, perf_attach::PerfLink, perf_attach_debugfs, - trace_point::read_sys_fs_trace_point_id, uprobe::UProbeError, utils::get_tracefs, 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}, }; @@ -61,7 +61,7 @@ pub(crate) fn attach>( pub(crate) fn detach_debug_fs(kind: ProbeKind, event_alias: &str) -> Result<(), ProgramError> { use ProbeKind::*; - let tracefs = get_tracefs()?; + let tracefs = find_tracefs_path()?; match kind { KProbe | KRetProbe => delete_probe_event(tracefs, kind, event_alias) @@ -118,7 +118,7 @@ fn create_as_trace_point( ) -> Result<(i32, String), ProgramError> { use ProbeKind::*; - let tracefs = get_tracefs()?; + let tracefs = find_tracefs_path()?; let event_alias = match kind { KProbe | KRetProbe => create_probe_event(tracefs, kind, name, offset) diff --git a/aya/src/programs/trace_point.rs b/aya/src/programs/trace_point.rs index a5f25e1d2..d4bf158d4 100644 --- a/aya/src/programs/trace_point.rs +++ b/aya/src/programs/trace_point.rs @@ -7,13 +7,12 @@ 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, }; -use super::utils::get_tracefs; - /// The type returned when attaching a [`TracePoint`] fails. #[derive(Debug, Error)] pub enum TracePointError { @@ -79,7 +78,7 @@ impl TracePoint { /// /// The returned value can be used to detach, see [TracePoint::detach]. pub fn attach(&mut self, category: &str, name: &str) -> Result { - let tracefs = get_tracefs()?; + 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 { diff --git a/aya/src/programs/utils.rs b/aya/src/programs/utils.rs index e9c431b0b..143e8664d 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, path::Path}; +use std::{ffi::CStr, io, os::unix::io::RawFd, path::Path}; use crate::{ programs::{FdLink, Link, ProgramData, ProgramError}, @@ -23,24 +23,25 @@ pub(crate) fn attach_raw_tracepoint>( program_data.links.insert(FdLink::new(pfd).into()) } -// Get tracefs filesystem -pub(crate) fn get_tracefs() -> Result<&'static Path, ProgramError> { +/// 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 mounts = [ + let known_mounts = [ Path::new("/sys/kernel/tracing"), Path::new("/sys/kernel/debug/tracing"), ]; - for mount in mounts { + for mount in known_mounts { if mount.exists() { return Some(mount); } } None - }; } - TRACE_FS.as_deref().ok_or(ProgramError::TraceFsNotFound) + TRACE_FS + .as_deref() + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "tracefs not found").into()) }