From d0321bd1ee92ce7157ce948eebe54845b447c378 Mon Sep 17 00:00:00 2001 From: Dan Everton Date: Thu, 18 Nov 2021 08:59:41 +1000 Subject: [PATCH] Attempt auto detach of probe for debugfs --- aya/src/programs/kprobe.rs | 6 +--- aya/src/programs/perf_attach.rs | 38 ++++++++++++++++++++- aya/src/programs/probe.rs | 58 +++++++++++++-------------------- aya/src/programs/uprobe.rs | 6 +--- 4 files changed, 62 insertions(+), 46 deletions(-) diff --git a/aya/src/programs/kprobe.rs b/aya/src/programs/kprobe.rs index 5bea9c36..9dddf6f8 100644 --- a/aya/src/programs/kprobe.rs +++ b/aya/src/programs/kprobe.rs @@ -6,7 +6,7 @@ use crate::{ generated::bpf_prog_type::BPF_PROG_TYPE_KPROBE, programs::{ load_program, - probe::{attach, detach, ProbeKind}, + probe::{attach, ProbeKind}, LinkRef, ProgramData, ProgramError, }, }; @@ -73,10 +73,6 @@ impl KProbe { pub fn attach(&mut self, fn_name: &str, offset: u64) -> Result { attach(&mut self.data, self.kind, fn_name, offset, None) } - - pub fn detach(&mut self, fn_name: &str) -> Result<(), ProgramError> { - detach(&mut self.data, self.kind, fn_name) - } } /// The type returned when attaching a [`KProbe`] fails. diff --git a/aya/src/programs/perf_attach.rs b/aya/src/programs/perf_attach.rs index 1085d272..ae0b2f3c 100644 --- a/aya/src/programs/perf_attach.rs +++ b/aya/src/programs/perf_attach.rs @@ -3,6 +3,7 @@ use std::os::unix::io::RawFd; use crate::{ sys::perf_event_ioctl, PERF_EVENT_IOC_DISABLE, PERF_EVENT_IOC_ENABLE, PERF_EVENT_IOC_SET_BPF, + programs::ProbeKind, programs::probe::detach_debug_fs }; use super::{Link, LinkRef, ProgramData, ProgramError}; @@ -10,6 +11,8 @@ use super::{Link, LinkRef, ProgramData, ProgramError}; #[derive(Debug)] struct PerfLink { perf_fd: Option, + probe_kind: Option, + event_alias: Option, } impl Link for PerfLink { @@ -17,6 +20,13 @@ impl Link for PerfLink { if let Some(fd) = self.perf_fd.take() { let _ = perf_event_ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); unsafe { close(fd) }; + + if let Some(probe_kind) = self.probe_kind.take() { + if let Some(event_alias) = self.event_alias.take() { + let _ = detach_debug_fs(probe_kind, &event_alias); + } + } + Ok(()) } else { Err(ProgramError::AlreadyDetached) @@ -45,5 +55,31 @@ pub(crate) fn perf_attach(data: &mut ProgramData, fd: RawFd) -> Result Result { + let prog_fd = data.fd_or_err()?; + perf_event_ioctl(fd, PERF_EVENT_IOC_SET_BPF, prog_fd).map_err(|(_, io_error)| { + ProgramError::SyscallError { + call: "PERF_EVENT_IOC_SET_BPF".to_owned(), + io_error, + } + })?; + perf_event_ioctl(fd, PERF_EVENT_IOC_ENABLE, 0).map_err(|(_, io_error)| { + ProgramError::SyscallError { + call: "PERF_EVENT_IOC_ENABLE".to_owned(), + io_error, + } + })?; + + Ok(data.link(PerfLink { + perf_fd: Some(fd), + probe_kind: Some(probe_kind), + event_alias: Some(event_alias), + })) } diff --git a/aya/src/programs/probe.rs b/aya/src/programs/probe.rs index 0d11eacb..2770f6d4 100644 --- a/aya/src/programs/probe.rs +++ b/aya/src/programs/probe.rs @@ -7,7 +7,7 @@ use std::{ use crate::{ programs::{ - kprobe::KProbeError, perf_attach, trace_point::read_sys_fs_trace_point_id, + kprobe::KProbeError, perf_attach, perf_attach_debugfs, trace_point::read_sys_fs_trace_point_id, uprobe::UProbeError, LinkRef, ProgramData, ProgramError, }, sys::{kernel_version, perf_event_open_probe, perf_event_open_trace_point}, @@ -32,22 +32,22 @@ pub(crate) fn attach( offset: u64, pid: Option, ) -> Result { + // https://github.com/torvalds/linux/commit/e12f03d7031a977356e3d7b75a68c2185ff8d155 + // Use debugfs to create probe let k_ver = kernel_version().unwrap(); - let fd = if k_ver >= (4, 17, 0) { - create_as_probe(kind, fn_name, offset, pid)? - } else { - create_as_trace_point(kind, fn_name, offset, pid)? + if k_ver < (4, 17, 0) { + let (fd, event_alias) = create_as_trace_point(kind, fn_name, offset, pid)?; + + return perf_attach_debugfs(program_data, fd, kind, event_alias); }; + + let fd = create_as_probe(kind, fn_name, offset, pid)?; perf_attach(program_data, fd) } -pub(crate) fn detach( - program_data: &mut ProgramData, - kind: ProbeKind, - fn_name: &str, -) -> Result<(), ProgramError> { +pub(crate) fn detach_debug_fs(kind: ProbeKind, event_alias: &str) -> Result<(), ProgramError> { use ProbeKind::*; /* @@ -64,27 +64,15 @@ pub(crate) fn detach( UProbe | URetProbe => "uprobe", }; - let probe_type_prefix = match kind { - KProbe | UProbe => 'p', - KRetProbe | URetProbe => 'r', - }; - let events_file_name = format!("/sys/kernel/debug/tracing/{}_events", event_type); - let event_name = format!( - "{}s/{}_{}_aya_{}", - probe_type_prefix, - event_type, - program_data.name, - process::id() - ); let found = match kind { KProbe | KRetProbe => { - find_in_sys_kernel_debug_tracing_events(&events_file_name, event_name.clone()) + find_in_sys_kernel_debug_tracing_events(&events_file_name, event_alias) .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })? } UProbe | URetProbe => { - find_in_sys_kernel_debug_tracing_events(&events_file_name, event_name.clone()) + find_in_sys_kernel_debug_tracing_events(&events_file_name, event_alias) .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })? } }; @@ -92,11 +80,11 @@ pub(crate) fn detach( if found { match kind { KProbe | KRetProbe => { - delete_in_sys_kernel_debug_tracing_events(&events_file_name, &event_name) + delete_in_sys_kernel_debug_tracing_events(&events_file_name, event_alias) .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })? } UProbe | URetProbe => { - delete_in_sys_kernel_debug_tracing_events(&events_file_name, &event_name) + delete_in_sys_kernel_debug_tracing_events(&events_file_name, event_alias) .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })? } }; @@ -147,7 +135,7 @@ fn create_as_trace_point( name: &str, offset: u64, pid: Option, -) -> Result { +) -> Result<(i32, String), ProgramError> { use ProbeKind::*; let (event_type, event_alias) = match kind { @@ -172,7 +160,7 @@ fn create_as_trace_point( } })? as i32; - Ok(fd) + Ok((fd, event_alias)) } fn create_probe_event( @@ -223,13 +211,13 @@ fn create_probe_event( } fn find_in_sys_kernel_debug_tracing_events( - events_file_name: &String, - event_name: String, + events_file_name: &str, + event_name: &str, ) -> Result { use std::io::BufRead; let events_file = - fs::File::open(events_file_name).map_err(|e| (events_file_name.clone(), e))?; + fs::File::open(events_file_name).map_err(|e| (events_file_name.to_string(), e))?; Ok(io::BufReader::new(events_file) .lines() @@ -238,17 +226,17 @@ fn find_in_sys_kernel_debug_tracing_events( } fn delete_in_sys_kernel_debug_tracing_events( - events_file_name: &String, - event_name: &String, + events_file_name: &str, + event_name: &str, ) -> Result<(), (String, io::Error)> { let mut events_file = fs::OpenOptions::new() .append(true) .open(events_file_name) - .map_err(|e| (events_file_name.clone(), e))?; + .map_err(|e| (events_file_name.to_string(), e))?; events_file .write_fmt(format_args!("-:{}", event_name)) - .map_err(|e| (events_file_name.clone(), e))?; + .map_err(|e| (events_file_name.to_string(), e))?; Ok(()) } diff --git a/aya/src/programs/uprobe.rs b/aya/src/programs/uprobe.rs index 65963c17..2444be86 100644 --- a/aya/src/programs/uprobe.rs +++ b/aya/src/programs/uprobe.rs @@ -17,7 +17,7 @@ use crate::{ generated::bpf_prog_type::BPF_PROG_TYPE_KPROBE, programs::{ load_program, - probe::{attach, detach, ProbeKind}, + probe::{attach, ProbeKind}, LinkRef, ProgramData, ProgramError, }, }; @@ -126,10 +126,6 @@ impl UProbe { attach(&mut self.data, self.kind, &path, sym_offset + offset, pid) } - - pub fn detach(&mut self, fn_name: &str) -> Result<(), ProgramError> { - detach(&mut self.data, self.kind, fn_name) - } } /// The type returned when attaching an [`UProbe`] fails.