Attempt auto detach of probe for debugfs

pull/108/head
Dan Everton 3 years ago
parent 34aa790a91
commit d0321bd1ee
No known key found for this signature in database
GPG Key ID: 2AF33A2B189A11B3

@ -6,7 +6,7 @@ use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_KPROBE, generated::bpf_prog_type::BPF_PROG_TYPE_KPROBE,
programs::{ programs::{
load_program, load_program,
probe::{attach, detach, ProbeKind}, probe::{attach, ProbeKind},
LinkRef, ProgramData, ProgramError, LinkRef, ProgramData, ProgramError,
}, },
}; };
@ -73,10 +73,6 @@ impl KProbe {
pub fn attach(&mut self, fn_name: &str, offset: u64) -> Result<LinkRef, ProgramError> { pub fn attach(&mut self, fn_name: &str, offset: u64) -> Result<LinkRef, ProgramError> {
attach(&mut self.data, self.kind, fn_name, offset, None) 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. /// The type returned when attaching a [`KProbe`] fails.

@ -3,6 +3,7 @@ use std::os::unix::io::RawFd;
use crate::{ use crate::{
sys::perf_event_ioctl, PERF_EVENT_IOC_DISABLE, PERF_EVENT_IOC_ENABLE, PERF_EVENT_IOC_SET_BPF, 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}; use super::{Link, LinkRef, ProgramData, ProgramError};
@ -10,6 +11,8 @@ use super::{Link, LinkRef, ProgramData, ProgramError};
#[derive(Debug)] #[derive(Debug)]
struct PerfLink { struct PerfLink {
perf_fd: Option<RawFd>, perf_fd: Option<RawFd>,
probe_kind: Option<ProbeKind>,
event_alias: Option<String>,
} }
impl Link for PerfLink { impl Link for PerfLink {
@ -17,6 +20,13 @@ impl Link for PerfLink {
if let Some(fd) = self.perf_fd.take() { if let Some(fd) = self.perf_fd.take() {
let _ = perf_event_ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); let _ = perf_event_ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
unsafe { close(fd) }; 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(()) Ok(())
} else { } else {
Err(ProgramError::AlreadyDetached) Err(ProgramError::AlreadyDetached)
@ -45,5 +55,31 @@ pub(crate) fn perf_attach(data: &mut ProgramData, fd: RawFd) -> Result<LinkRef,
} }
})?; })?;
Ok(data.link(PerfLink { perf_fd: Some(fd) })) Ok(data.link(PerfLink {
perf_fd: Some(fd),
probe_kind: None,
event_alias: None,
}))
}
pub(crate) fn perf_attach_debugfs(data: &mut ProgramData, fd: RawFd, probe_kind: ProbeKind, event_alias: String) -> Result<LinkRef, ProgramError> {
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),
}))
} }

@ -7,7 +7,7 @@ use std::{
use crate::{ use crate::{
programs::{ 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, uprobe::UProbeError, LinkRef, ProgramData, ProgramError,
}, },
sys::{kernel_version, perf_event_open_probe, perf_event_open_trace_point}, sys::{kernel_version, perf_event_open_probe, perf_event_open_trace_point},
@ -32,22 +32,22 @@ pub(crate) fn attach(
offset: u64, offset: u64,
pid: Option<pid_t>, pid: Option<pid_t>,
) -> Result<LinkRef, ProgramError> { ) -> Result<LinkRef, ProgramError> {
// https://github.com/torvalds/linux/commit/e12f03d7031a977356e3d7b75a68c2185ff8d155 // https://github.com/torvalds/linux/commit/e12f03d7031a977356e3d7b75a68c2185ff8d155
// Use debugfs to create probe
let k_ver = kernel_version().unwrap(); let k_ver = kernel_version().unwrap();
let fd = if k_ver >= (4, 17, 0) { if k_ver < (4, 17, 0) {
create_as_probe(kind, fn_name, offset, pid)? let (fd, event_alias) = create_as_trace_point(kind, fn_name, offset, pid)?;
} else {
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) perf_attach(program_data, fd)
} }
pub(crate) fn detach( pub(crate) fn detach_debug_fs(kind: ProbeKind, event_alias: &str) -> Result<(), ProgramError> {
program_data: &mut ProgramData,
kind: ProbeKind,
fn_name: &str,
) -> Result<(), ProgramError> {
use ProbeKind::*; use ProbeKind::*;
/* /*
@ -64,27 +64,15 @@ pub(crate) fn detach(
UProbe | URetProbe => "uprobe", 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 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 { let found = match kind {
KProbe | KRetProbe => { 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 })? .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?
} }
UProbe | URetProbe => { 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 })? .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?
} }
}; };
@ -92,11 +80,11 @@ pub(crate) fn detach(
if found { if found {
match kind { match kind {
KProbe | KRetProbe => { 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 })? .map_err(|(filename, io_error)| KProbeError::FileError { filename, io_error })?
} }
UProbe | URetProbe => { 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 })? .map_err(|(filename, io_error)| UProbeError::FileError { filename, io_error })?
} }
}; };
@ -147,7 +135,7 @@ fn create_as_trace_point(
name: &str, name: &str,
offset: u64, offset: u64,
pid: Option<pid_t>, pid: Option<pid_t>,
) -> Result<i32, ProgramError> { ) -> Result<(i32, String), ProgramError> {
use ProbeKind::*; use ProbeKind::*;
let (event_type, event_alias) = match kind { let (event_type, event_alias) = match kind {
@ -172,7 +160,7 @@ fn create_as_trace_point(
} }
})? as i32; })? as i32;
Ok(fd) Ok((fd, event_alias))
} }
fn create_probe_event( fn create_probe_event(
@ -223,13 +211,13 @@ fn create_probe_event(
} }
fn find_in_sys_kernel_debug_tracing_events( fn find_in_sys_kernel_debug_tracing_events(
events_file_name: &String, events_file_name: &str,
event_name: String, event_name: &str,
) -> Result<bool, (String, io::Error)> { ) -> Result<bool, (String, io::Error)> {
use std::io::BufRead; use std::io::BufRead;
let events_file = 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) Ok(io::BufReader::new(events_file)
.lines() .lines()
@ -238,17 +226,17 @@ fn find_in_sys_kernel_debug_tracing_events(
} }
fn delete_in_sys_kernel_debug_tracing_events( fn delete_in_sys_kernel_debug_tracing_events(
events_file_name: &String, events_file_name: &str,
event_name: &String, event_name: &str,
) -> Result<(), (String, io::Error)> { ) -> Result<(), (String, io::Error)> {
let mut events_file = fs::OpenOptions::new() let mut events_file = fs::OpenOptions::new()
.append(true) .append(true)
.open(events_file_name) .open(events_file_name)
.map_err(|e| (events_file_name.clone(), e))?; .map_err(|e| (events_file_name.to_string(), e))?;
events_file events_file
.write_fmt(format_args!("-:{}", event_name)) .write_fmt(format_args!("-:{}", event_name))
.map_err(|e| (events_file_name.clone(), e))?; .map_err(|e| (events_file_name.to_string(), e))?;
Ok(()) Ok(())
} }

@ -17,7 +17,7 @@ use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_KPROBE, generated::bpf_prog_type::BPF_PROG_TYPE_KPROBE,
programs::{ programs::{
load_program, load_program,
probe::{attach, detach, ProbeKind}, probe::{attach, ProbeKind},
LinkRef, ProgramData, ProgramError, LinkRef, ProgramData, ProgramError,
}, },
}; };
@ -126,10 +126,6 @@ impl UProbe {
attach(&mut self.data, self.kind, &path, sym_offset + offset, pid) 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. /// The type returned when attaching an [`UProbe`] fails.

Loading…
Cancel
Save