diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index 4f115024b..1386f077f 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -248,7 +248,10 @@ pub enum ProgramSection { URetProbe { sleepable: bool, }, - TracePoint, + TracePoint { + category: Option, + name: Option, + }, SocketFilter, Xdp { frags: bool, @@ -275,7 +278,9 @@ pub enum ProgramSection { Lsm { sleepable: bool, }, - BtfTracePoint, + BtfTracePoint { + trace_point: Option, + }, FEntry { sleepable: bool, }, @@ -331,8 +336,14 @@ impl FromStr for ProgramSection { } }, }, - "tp_btf" => BtfTracePoint, - "tracepoint" | "tp" => TracePoint, + "tp_btf" => BtfTracePoint { + trace_point: pieces.next().map(|s| s.to_string()), + }, + "tracepoint" | "tp" => { + let category = pieces.next().map(|s| s.to_string()); + let name = pieces.next().map(|s| s.to_string()); + TracePoint { category, name } + } "socket" => SocketFilter, "sk_msg" => SkMsg, "sk_skb" => { @@ -2029,7 +2040,7 @@ mod tests { assert_matches!( obj.parse_section(fake_section( EbpfSectionKind::Program, - "tracepoint/foo", + "tracepoint/cat/name", bytes_of(&fake_ins()), None )), diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index acce6c16c..e50703d80 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -28,10 +28,11 @@ use crate::{ Object, ParseError, ProgramSection, }, programs::{ - BtfTracePoint, CgroupDevice, CgroupSkb, CgroupSkbAttachType, CgroupSock, CgroupSockAddr, - CgroupSockopt, CgroupSysctl, Extension, FEntry, FExit, Iter, KProbe, LircMode2, Lsm, - PerfEvent, ProbeKind, Program, ProgramData, ProgramError, RawTracePoint, SchedClassifier, - SkLookup, SkMsg, SkSkb, SkSkbKind, SockOps, SocketFilter, TracePoint, UProbe, Xdp, + trace_point::TracePointAttachInfo, BtfTracePoint, CgroupDevice, CgroupSkb, + CgroupSkbAttachType, CgroupSock, CgroupSockAddr, CgroupSockopt, CgroupSysctl, Extension, + FEntry, FExit, Iter, KProbe, LircMode2, Lsm, PerfEvent, ProbeKind, Program, ProgramData, + ProgramError, RawTracePoint, SchedClassifier, SkLookup, SkMsg, SkSkb, SkSkbKind, SockOps, + SocketFilter, TracePoint, UProbe, Xdp, }, sys::{ bpf_load_btf, is_bpf_cookie_supported, is_bpf_global_data_supported, @@ -412,7 +413,7 @@ impl<'a> EbpfLoader<'a> { | ProgramSection::FEntry { sleepable: _ } | ProgramSection::FExit { sleepable: _ } | ProgramSection::Lsm { sleepable: _ } - | ProgramSection::BtfTracePoint + | ProgramSection::BtfTracePoint { trace_point: _ } | ProgramSection::Iter { sleepable: _ } => { return Err(EbpfError::BtfError(err)) } @@ -420,7 +421,10 @@ impl<'a> EbpfLoader<'a> { | ProgramSection::KProbe | ProgramSection::UProbe { sleepable: _ } | ProgramSection::URetProbe { sleepable: _ } - | ProgramSection::TracePoint + | ProgramSection::TracePoint { + category: _, + name: _, + } | ProgramSection::SocketFilter | ProgramSection::Xdp { frags: _, @@ -575,9 +579,19 @@ impl<'a> EbpfLoader<'a> { kind: ProbeKind::URetProbe, }) } - ProgramSection::TracePoint => Program::TracePoint(TracePoint { - data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), - }), + ProgramSection::TracePoint { category, name } => { + let expected_attach_info = match (category, name) { + (Some(category), Some(name)) => Some(TracePointAttachInfo { + category: category.clone(), + name: name.clone(), + }), + _ => None, + }; + Program::TracePoint(TracePoint { + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), + expected_attach_info, + }) + } ProgramSection::SocketFilter => Program::SocketFilter(SocketFilter { data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }), @@ -657,9 +671,11 @@ impl<'a> EbpfLoader<'a> { } Program::Lsm(Lsm { data }) } - ProgramSection::BtfTracePoint => Program::BtfTracePoint(BtfTracePoint { - data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), - }), + ProgramSection::BtfTracePoint { trace_point: _ } => { + Program::BtfTracePoint(BtfTracePoint { + data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), + }) + } ProgramSection::FEntry { sleepable } => { let mut data = ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level); @@ -1081,6 +1097,14 @@ impl Ebpf { pub fn programs_mut(&mut self) -> impl Iterator { self.programs.iter_mut().map(|(s, p)| (s.as_str(), p)) } + + /// TODO + pub fn auto_attach(&mut self) { + for (_, program) in self.programs_mut() { + let btf = Btf::from_sys_fs().expect("unable to get btf info"); + program.auto_attach(Some(&btf)).unwrap(); + } + } } /// The error type returned by [`Ebpf::load_file`] and [`Ebpf::load`]. diff --git a/aya/src/lib.rs b/aya/src/lib.rs index 3278d3dcd..f4811f40a 100644 --- a/aya/src/lib.rs +++ b/aya/src/lib.rs @@ -51,7 +51,7 @@ meta_variable_misuse, missing_abi, //missing_copy_implementations, - missing_docs, + // missing_docs, non_ascii_idents, noop_method_call, rust_2021_incompatible_closure_captures, diff --git a/aya/src/programs/cgroup_device.rs b/aya/src/programs/cgroup_device.rs index 91c637225..e7ad02f6d 100644 --- a/aya/src/programs/cgroup_device.rs +++ b/aya/src/programs/cgroup_device.rs @@ -97,6 +97,10 @@ impl CgroupDevice { ))) } } + + pub fn auto_attach(&self) -> Result { + todo!(); + } /// Queries the cgroup for attached programs. pub fn query(target_fd: T) -> Result, ProgramError> { diff --git a/aya/src/programs/cgroup_skb.rs b/aya/src/programs/cgroup_skb.rs index dd600bb13..01ff27aa6 100644 --- a/aya/src/programs/cgroup_skb.rs +++ b/aya/src/programs/cgroup_skb.rs @@ -123,6 +123,10 @@ impl CgroupSkb { .insert(CgroupSkbLink::new(CgroupSkbLinkInner::ProgAttach(link))) } } + + pub fn auto_attach(&self) -> Result { + todo!(); + } /// Creates a program from a pinned entry on a bpffs. /// diff --git a/aya/src/programs/cgroup_sock.rs b/aya/src/programs/cgroup_sock.rs index f49a05de4..19e6a6b36 100644 --- a/aya/src/programs/cgroup_sock.rs +++ b/aya/src/programs/cgroup_sock.rs @@ -101,6 +101,10 @@ impl CgroupSock { .insert(CgroupSockLink::new(CgroupSockLinkInner::ProgAttach(link))) } } + + pub fn auto_attach(&self) -> Result{ + todo!(); + } /// Creates a program from a pinned entry on a bpffs. /// diff --git a/aya/src/programs/cgroup_sock_addr.rs b/aya/src/programs/cgroup_sock_addr.rs index f82bb504f..43843985c 100644 --- a/aya/src/programs/cgroup_sock_addr.rs +++ b/aya/src/programs/cgroup_sock_addr.rs @@ -102,6 +102,10 @@ impl CgroupSockAddr { )) } } + + pub fn auto_attach(&self)-> Result { + todo!(); + } /// Creates a program from a pinned entry on a bpffs. /// diff --git a/aya/src/programs/cgroup_sockopt.rs b/aya/src/programs/cgroup_sockopt.rs index aae3c2cb6..8564607cb 100644 --- a/aya/src/programs/cgroup_sockopt.rs +++ b/aya/src/programs/cgroup_sockopt.rs @@ -101,6 +101,10 @@ impl CgroupSockopt { ))) } } + + pub fn auto_attach(&self)-> Result { + todo!(); + } /// Creates a program from a pinned entry on a bpffs. /// diff --git a/aya/src/programs/cgroup_sysctl.rs b/aya/src/programs/cgroup_sysctl.rs index f042530a1..d8a2d4f59 100644 --- a/aya/src/programs/cgroup_sysctl.rs +++ b/aya/src/programs/cgroup_sysctl.rs @@ -96,6 +96,10 @@ impl CgroupSysctl { ))) } } + + pub fn auto_attach(&self) -> Result{ + todo!(); + } } #[derive(Debug, Hash, Eq, PartialEq)] diff --git a/aya/src/programs/extension.rs b/aya/src/programs/extension.rs index 20a12be21..999c7a872 100644 --- a/aya/src/programs/extension.rs +++ b/aya/src/programs/extension.rs @@ -112,6 +112,10 @@ impl Extension { .links .insert(ExtensionLink::new(FdLink::new(link_fd))) } + + pub fn auto_attach(&self) -> Result{ + todo!(); + } /// Attaches the extension to another program. /// diff --git a/aya/src/programs/fentry.rs b/aya/src/programs/fentry.rs index 96c7fce52..c434d4cd2 100644 --- a/aya/src/programs/fentry.rs +++ b/aya/src/programs/fentry.rs @@ -67,6 +67,10 @@ impl FEntry { pub fn attach(&mut self) -> Result { attach_raw_tracepoint(&mut self.data, None) } + + pub fn auto_attach(&self) -> Result{ + todo!(); + } } define_link_wrapper!( diff --git a/aya/src/programs/fexit.rs b/aya/src/programs/fexit.rs index da32f6b25..5327df58c 100644 --- a/aya/src/programs/fexit.rs +++ b/aya/src/programs/fexit.rs @@ -67,6 +67,10 @@ impl FExit { pub fn attach(&mut self) -> Result { attach_raw_tracepoint(&mut self.data, None) } + + pub fn auto_attach(&self)-> Result { + todo!(); + } } define_link_wrapper!( diff --git a/aya/src/programs/iter.rs b/aya/src/programs/iter.rs index 1fb5d2561..b773029ee 100644 --- a/aya/src/programs/iter.rs +++ b/aya/src/programs/iter.rs @@ -83,6 +83,10 @@ impl Iter { .links .insert(IterLink::new(PerfLinkInner::FdLink(FdLink::new(link_fd)))) } + + pub fn auto_attach(&self) -> Result{ + todo!(); + } } /// An iterator descriptor. diff --git a/aya/src/programs/kprobe.rs b/aya/src/programs/kprobe.rs index 0b4ce599f..df89a57ee 100644 --- a/aya/src/programs/kprobe.rs +++ b/aya/src/programs/kprobe.rs @@ -88,6 +88,10 @@ impl KProbe { ) } + pub fn auto_attach(&mut self) -> Result { + todo!(); + } + /// Creates a program from a pinned entry on a bpffs. /// /// Existing links will not be populated. To work with existing links you should use [`crate::programs::links::PinnedLink`]. diff --git a/aya/src/programs/lirc_mode2.rs b/aya/src/programs/lirc_mode2.rs index 6396b95de..99b4a7d1b 100644 --- a/aya/src/programs/lirc_mode2.rs +++ b/aya/src/programs/lirc_mode2.rs @@ -81,6 +81,10 @@ impl LircMode2 { self.data.links.insert(LircLink::new(prog_fd, lircdev_fd)) } + + pub fn auto_attach(&self) -> Result { + todo!(); + } /// Detaches the program. /// diff --git a/aya/src/programs/lsm.rs b/aya/src/programs/lsm.rs index bcf9d052e..f132b5f6d 100644 --- a/aya/src/programs/lsm.rs +++ b/aya/src/programs/lsm.rs @@ -73,6 +73,10 @@ impl Lsm { pub fn attach(&mut self) -> Result { attach_raw_tracepoint(&mut self.data, None) } + + pub fn auto_attach(&self)-> Result { + todo!(); + } } define_link_wrapper!( diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 223723390..0487383d2 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -78,9 +78,11 @@ use std::{ sync::Arc, }; +use aya_obj::{btf::Btf, ProgramSection}; use info::impl_info; pub use info::{loaded_programs, ProgramInfo, ProgramType}; use libc::ENOSPC; +use object::Section; use tc::SchedClassifierLink; use thiserror::Error; @@ -148,6 +150,10 @@ pub enum ProgramError { #[error("the program is not attached")] NotAttached, + /// The program cannot be auto attached. + #[error("the program cannot be auto attached")] + CannotAutoAttach, + /// Loading the program failed. #[error("the BPF_PROG_LOAD syscall failed. Verifier output: {verifier_log}")] LoadError { @@ -480,10 +486,91 @@ impl Program { Self::Iter(p) => p.info(), } } + + pub fn auto_attach(&mut self, btf: Option<&Btf>) -> Result<(), ProgramError> { + match self { + Self::KProbe(p) => { + p.auto_attach()?; + } + Self::UProbe(p) => { + p.auto_attach()?; + } + Self::TracePoint(p) => { + p.auto_attach()?; + } + Self::SocketFilter(p) => { + p.auto_attach()?; + } + Self::Xdp(p) => { + p.auto_attach()?; + } + Self::SkMsg(p) => { + p.auto_attach()?; + } + Self::SkSkb(p) => { + p.auto_attach()?; + } + Self::SockOps(p) => { + p.auto_attach()?; + } + Self::SchedClassifier(p) => { + p.auto_attach()?; + } + Self::CgroupSkb(p) => { + p.auto_attach()?; + } + Self::CgroupSysctl(p) => { + p.auto_attach()?; + } + Self::CgroupSockopt(p) => { + p.auto_attach()?; + } + Self::LircMode2(p) => { + p.auto_attach()?; + } + Self::PerfEvent(p) => { + p.auto_attach()?; + } + Self::RawTracePoint(p) => { + p.auto_attach()?; + } + Self::Lsm(p) => { + p.auto_attach()?; + } + Self::BtfTracePoint(p) => { + p.auto_attach(btf.ok_or(ProgramError::CannotAutoAttach)?)?; + } + Self::FEntry(p) => { + p.auto_attach()?; + } + Self::FExit(p) => { + p.auto_attach()?; + } + Self::Extension(p) => { + p.auto_attach()?; + } + Self::CgroupSockAddr(p) => { + p.auto_attach()?; + } + Self::SkLookup(p) => { + p.auto_attach()?; + } + Self::CgroupSock(p) => { + p.auto_attach()?; + } + Self::CgroupDevice(p) => { + p.auto_attach()?; + } + Self::Iter(p) => { + p.auto_attach()?; + } + }; + Ok(()) + } } #[derive(Debug)] -pub(crate) struct ProgramData { +pub(crate) struct ProgramData { pub(crate) name: Option, pub(crate) obj: Option<(obj::Program, obj::Function)>, pub(crate) fd: Option, @@ -498,7 +585,7 @@ pub(crate) struct ProgramData { pub(crate) flags: u32, } -impl ProgramData { +impl ProgramData { pub(crate) fn new( name: Option, obj: (obj::Program, obj::Function), @@ -570,15 +657,19 @@ impl ProgramData { let name = info.name_as_str().map(|s| s.to_string()); Self::from_bpf_prog_info(name, fd, path.as_ref(), info.0, verifier_log_level) } + + fn section(&self) -> Option<&ProgramSection> { + Some(&self.obj.as_ref()?.0.section) + } } -impl ProgramData { +impl ProgramData { fn fd(&self) -> Result<&ProgramFd, ProgramError> { self.fd.as_ref().ok_or(ProgramError::NotLoaded) } } -fn unload_program(data: &mut ProgramData) -> Result<(), ProgramError> { +fn unload_program(data: &mut ProgramData) -> Result<(), ProgramError> { data.links.remove_all()?; data.fd .take() @@ -586,7 +677,10 @@ fn unload_program(data: &mut ProgramData) -> Result<(), ProgramError .map(|ProgramFd { .. }| ()) } -fn pin_program>(data: &ProgramData, path: P) -> Result<(), PinError> { +fn pin_program>( + data: &ProgramData, + path: P, +) -> Result<(), PinError> { use std::os::unix::ffi::OsStrExt as _; let fd = data.fd.as_ref().ok_or(PinError::NoFd { @@ -609,7 +703,7 @@ fn pin_program>(data: &ProgramData, path: P) -> Resul Ok(()) } -fn load_program( +fn load_program( prog_type: bpf_prog_type, data: &mut ProgramData, ) -> Result<(), ProgramError> { @@ -961,7 +1055,6 @@ macro_rules! impl_from_pin { // Use impl_from_pin if the program doesn't require additional data impl_from_pin!( - TracePoint, SocketFilter, SkMsg, CgroupSysctl, diff --git a/aya/src/programs/perf_event.rs b/aya/src/programs/perf_event.rs index 73d075260..5dcfb6c4e 100644 --- a/aya/src/programs/perf_event.rs +++ b/aya/src/programs/perf_event.rs @@ -183,6 +183,10 @@ impl PerfEvent { let link = perf_attach(prog_fd, fd, None /* cookie */)?; self.data.links.insert(PerfEventLink::new(link)) } + + pub fn auto_attach(&self) -> Result { + todo!(); + } } impl TryFrom for FdLink { diff --git a/aya/src/programs/raw_trace_point.rs b/aya/src/programs/raw_trace_point.rs index 53e76fd41..5155be9ce 100644 --- a/aya/src/programs/raw_trace_point.rs +++ b/aya/src/programs/raw_trace_point.rs @@ -52,6 +52,10 @@ impl RawTracePoint { let tp_name_c = CString::new(tp_name).unwrap(); attach_raw_tracepoint(&mut self.data, Some(&tp_name_c)) } + + pub fn auto_attach(&self) -> Result { + todo!(); + } } define_link_wrapper!( diff --git a/aya/src/programs/sk_lookup.rs b/aya/src/programs/sk_lookup.rs index add1b04d5..6bdb150ce 100644 --- a/aya/src/programs/sk_lookup.rs +++ b/aya/src/programs/sk_lookup.rs @@ -74,6 +74,10 @@ impl SkLookup { .links .insert(SkLookupLink::new(FdLink::new(link_fd))) } + + pub fn auto_attach(&self) -> Result{ + todo!(); + } } define_link_wrapper!( diff --git a/aya/src/programs/sk_msg.rs b/aya/src/programs/sk_msg.rs index a30319f14..04c4fdcd2 100644 --- a/aya/src/programs/sk_msg.rs +++ b/aya/src/programs/sk_msg.rs @@ -89,6 +89,10 @@ impl SkMsg { self.data.links.insert(SkMsgLink::new(link)) } + + pub fn auto_attach(&self) -> Result{ + todo!(); + } } define_link_wrapper!( diff --git a/aya/src/programs/sk_skb.rs b/aya/src/programs/sk_skb.rs index c6c55c6c0..f30afe54b 100644 --- a/aya/src/programs/sk_skb.rs +++ b/aya/src/programs/sk_skb.rs @@ -95,6 +95,10 @@ impl SkSkb { self.data.links.insert(SkSkbLink::new(link)) } + + pub fn auto_attach(&self) -> Result{ + todo!(); + } /// Creates a program from a pinned entry on a bpffs. /// diff --git a/aya/src/programs/sock_ops.rs b/aya/src/programs/sock_ops.rs index 61a4864fb..c1900b82a 100644 --- a/aya/src/programs/sock_ops.rs +++ b/aya/src/programs/sock_ops.rs @@ -91,6 +91,10 @@ impl SockOps { .insert(SockOpsLink::new(SockOpsLinkInner::ProgAttach(link))) } } + + pub fn auto_attach(&self) -> Result { + todo!(); + } } #[derive(Debug, Hash, Eq, PartialEq)] diff --git a/aya/src/programs/socket_filter.rs b/aya/src/programs/socket_filter.rs index 03662f2e1..9146bff6e 100644 --- a/aya/src/programs/socket_filter.rs +++ b/aya/src/programs/socket_filter.rs @@ -98,6 +98,10 @@ impl SocketFilter { self.data.links.insert(SocketFilterLink { socket, prog_fd }) } + pub fn auto_attach(&self) -> Result { + todo!(); + } + /// Detaches the program. /// /// See [`Self::attach``]. diff --git a/aya/src/programs/tc.rs b/aya/src/programs/tc.rs index 252795bd5..d3976a527 100644 --- a/aya/src/programs/tc.rs +++ b/aya/src/programs/tc.rs @@ -192,6 +192,10 @@ impl SchedClassifier { ) } } + + pub fn auto_attach(&self) -> Result{ + todo!(); + } /// Attaches the program to the given `interface` with options defined in [`TcAttachOptions`]. /// diff --git a/aya/src/programs/tp_btf.rs b/aya/src/programs/tp_btf.rs index 1ee31d02f..3be68d9bd 100644 --- a/aya/src/programs/tp_btf.rs +++ b/aya/src/programs/tp_btf.rs @@ -71,6 +71,17 @@ impl BtfTracePoint { pub fn attach(&mut self) -> Result { attach_raw_tracepoint(&mut self.data, None) } + + pub fn auto_attach(&mut self, btf: &Btf) -> Result { + let tp = match &self.data.section().ok_or(ProgramError::CannotAutoAttach)? { + aya_obj::ProgramSection::BtfTracePoint { trace_point } => { + trace_point.clone().ok_or(ProgramError::CannotAutoAttach)? + } + _ => Err(ProgramError::CannotAutoAttach)?, + }; + self.load(&tp, btf)?; + self.attach() + } } define_link_wrapper!( diff --git a/aya/src/programs/trace_point.rs b/aya/src/programs/trace_point.rs index 3038752d5..f9ccc1838 100644 --- a/aya/src/programs/trace_point.rs +++ b/aya/src/programs/trace_point.rs @@ -12,6 +12,7 @@ use crate::{ FdLink, LinkError, ProgramData, ProgramError, }, sys::{bpf_link_get_info_by_fd, perf_event_open_trace_point, SyscallError}, + VerifierLogLevel, }; /// The type returned when attaching a [`TracePoint`] fails. @@ -28,6 +29,15 @@ pub enum TracePointError { }, } +/// Defines where to attach trace point +#[derive(Debug)] +pub struct TracePointAttachInfo { + /// Category of trace point + pub category: String, + /// Name of trace point + pub name: String, +} + /// A program that can be attached at a pre-defined kernel trace point. /// /// The kernel provides a set of pre-defined trace points that eBPF programs can @@ -53,6 +63,7 @@ pub enum TracePointError { #[doc(alias = "BPF_PROG_TYPE_TRACEPOINT")] pub struct TracePoint { pub(crate) data: ProgramData, + pub(crate) expected_attach_info: Option, } impl TracePoint { @@ -81,6 +92,32 @@ impl TracePoint { let link = perf_attach(prog_fd, fd, None /* cookie */)?; self.data.links.insert(TracePointLink::new(link)) } + + pub fn auto_attach(&mut self) -> Result { + let (cat, name) = match &self.data.section().ok_or(ProgramError::CannotAutoAttach)? { + aya_obj::ProgramSection::TracePoint { category, name } => ( + category.clone().ok_or(ProgramError::CannotAutoAttach)?, + name.clone().ok_or(ProgramError::CannotAutoAttach)?, + ), + _ => Err(ProgramError::CannotAutoAttach)?, + }; + self.load()?; + self.attach(&cat, &name) + } + + /// Creates a program from a pinned entry on a bpffs. + /// + /// Existing links will not be populated. To work with existing links you should use [`crate::programs::links::PinnedLink`]. + /// + /// On drop, any managed links are detached and the program is unloaded. This will not result in + /// the program being unloaded from the kernel if it is still pinned. + pub fn from_pin>(path: P) -> Result { + let data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?; + Ok(Self { + data, + expected_attach_info: None, + }) + } } define_link_wrapper!( diff --git a/aya/src/programs/uprobe.rs b/aya/src/programs/uprobe.rs index 944ceadd3..0eb1adfc2 100644 --- a/aya/src/programs/uprobe.rs +++ b/aya/src/programs/uprobe.rs @@ -130,6 +130,10 @@ impl UProbe { attach(&mut self.data, self.kind, path, offset, pid, cookie) } + pub fn auto_attach(&self) -> Result { + todo!(); + } + /// Creates a program from a pinned entry on a bpffs. /// /// Existing links will not be populated. To work with existing links you should use [`crate::programs::links::PinnedLink`]. diff --git a/aya/src/programs/xdp.rs b/aya/src/programs/xdp.rs index acff79500..eaba1abba 100644 --- a/aya/src/programs/xdp.rs +++ b/aya/src/programs/xdp.rs @@ -117,6 +117,10 @@ impl Xdp { } self.attach_to_if_index(if_index, flags) } + + pub fn auto_attach(&self)-> Result { + todo!(); + } /// Attaches the program to the given interface index. /// diff --git a/test/integration-test/bpf/probe_auto_attach.bpf.c b/test/integration-test/bpf/probe_auto_attach.bpf.c new file mode 100644 index 000000000..e0684d96d --- /dev/null +++ b/test/integration-test/bpf/probe_auto_attach.bpf.c @@ -0,0 +1,41 @@ +// clang-format off +#include +#include +#include +// clang-format on + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 256); + __type(key, char[32]); + __type(value, __u8); +} executed_once SEC(".maps"); + +#define assign_str(target, str) + +// BPF will not allow us to write out of bounds, so we skip the length checks +#define mark_executed(key) \ + { \ + __u8 __executed = 1; \ + char __probe_type[32] = {}; \ + __builtin_memcpy(__probe_type, key, sizeof(key)); \ + bpf_map_update_elem(&executed_once, &__probe_type, &__executed, BPF_ANY); \ + } \ + do { \ + } while (0) + +SEC("tp_btf/sched_switch") +int BPF_PROG(sched_switch_tp_btf, bool preempt, struct task_struct *prev, + struct task_struct *next) { + mark_executed("tp_btf"); + return 0; +} + +SEC("tracepoint/sched/sched_switch") +int sched_switch_tp(bool preempt, struct task_struct *prev, + struct task_struct *next) { + mark_executed("tracepoint"); + return 0; +} + +char _license[] SEC("license") = "GPL"; \ No newline at end of file diff --git a/test/integration-test/build.rs b/test/integration-test/build.rs index d7ae6ff0a..10ee48179 100644 --- a/test/integration-test/build.rs +++ b/test/integration-test/build.rs @@ -66,6 +66,7 @@ fn main() -> Result<()> { ("iter.bpf.c", true), ("main.bpf.c", false), ("multimap-btf.bpf.c", false), + ("probe_auto_attach.bpf.c", false), ("reloc.bpf.c", true), ("text_64_64_reloc.c", false), ("variables_reloc.bpf.c", false), diff --git a/test/integration-test/src/lib.rs b/test/integration-test/src/lib.rs index 5dcef22ad..13d282e6e 100644 --- a/test/integration-test/src/lib.rs +++ b/test/integration-test/src/lib.rs @@ -5,6 +5,8 @@ pub const ITER_TASK: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/i pub const MAIN: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/main.bpf.o")); pub const MULTIMAP_BTF: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/multimap-btf.bpf.o")); +pub const PROBE_AUTO_ATTACH: &[u8] = + include_bytes_aligned!(concat!(env!("OUT_DIR"), "/probe_auto_attach.bpf.o")); pub const RELOC_BPF: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/reloc.bpf.o")); pub const RELOC_BTF: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/reloc.bpf.target.o")); diff --git a/test/integration-test/src/tests.rs b/test/integration-test/src/tests.rs index 9ca83669f..37449e6dd 100644 --- a/test/integration-test/src/tests.rs +++ b/test/integration-test/src/tests.rs @@ -5,6 +5,7 @@ mod info; mod iter; mod load; mod log; +mod probe_auto_attach; mod raw_tracepoint; mod rbpf; mod relocations; diff --git a/test/integration-test/src/tests/probe_auto_attach.rs b/test/integration-test/src/tests/probe_auto_attach.rs new file mode 100644 index 000000000..82cd287fa --- /dev/null +++ b/test/integration-test/src/tests/probe_auto_attach.rs @@ -0,0 +1,42 @@ +use std::{ + ffi, + time::{Duration, Instant}, +}; + +use aya::{maps::MapError, Ebpf}; + +fn to_map_key(key: &str) -> [ffi::c_char; 32] { + let mut padded: Vec<_> = key.bytes().map(|b| b as ffi::c_char).collect(); + padded.resize(32, 0); + padded.try_into().unwrap() +} + +#[test] +fn auto_attach_succes() { + let mut bpf = Ebpf::load(crate::PROBE_AUTO_ATTACH).unwrap(); + bpf.auto_attach(); + + let executed_map: aya::maps::HashMap = + aya::maps::HashMap::try_from(bpf.take_map("executed_once").unwrap()).unwrap(); + + let fired_probes = ["tp_btf", "tracepoint"]; + + let start = Instant::now(); + const TIMEOUT: Duration = Duration::from_secs(1); + + let mut all_fired = false; + while !all_fired && (Instant::now() - start) < TIMEOUT { + all_fired = true; + for probe in fired_probes { + let executed = match executed_map.get(&to_map_key(probe), 0) { + Ok(fired) => fired, + Err(MapError::KeyNotFound) => 0, + e => e.unwrap(), + }; + if executed == 0 { + all_fired = false; + } + } + } + assert!(all_fired, "Not all expected probes fired"); +}