diff --git a/aya/src/programs/kprobe.rs b/aya/src/programs/kprobe.rs index 7a6709e5..df1ae70d 100644 --- a/aya/src/programs/kprobe.rs +++ b/aya/src/programs/kprobe.rs @@ -1,6 +1,4 @@ //! Kernel space probes. -//! -//! Kernel probes are eBPF programs that can be attached to almost any function inside the kernel. use libc::pid_t; use std::io; use thiserror::Error; @@ -14,7 +12,13 @@ use crate::{ }, }; -/// A `kprobe` program. +/// A kernel probe. +/// +/// Kernel probes are eBPF programs that can be attached to almost any function inside +/// the kernel. They can be of two kinds: +/// +/// - `kprobe`: get attached to the *start* of the target functions +/// - `kretprobe`: get attached to the *return address* of the target functions #[derive(Debug)] pub struct KProbe { pub(crate) data: ProgramData, @@ -29,10 +33,41 @@ impl KProbe { load_program(BPF_PROG_TYPE_KPROBE, &mut self.data) } + /// Returns the name of the program. pub fn name(&self) -> String { self.data.name.to_string() } + /// Returns `KProbe` if the program is a `kprobe`, or `KRetProbe` if the + /// program is a `kretprobe`. + pub fn kind(&self) -> ProbeKind { + self.kind + } + + /// Attaches the program. + /// + /// Attaches the probe to the given function name inside the kernel. If + /// `offset` is non-zero, it is added to the address of the target + /// function. If `pid` is `Some()`, the program executes only when the + /// target function is triggered by the given `pid`. + /// + /// If the program is a `kprobe`, it is attached to the *start* address of the target function. + /// Conversely if the program is a `kretprobe`, it is attached to the return address of the + /// target function. + /// + /// + /// # Example + /// + /// ```no_run + /// # let mut bpf = Bpf::load_file("ebpf_programs.o")?; + /// use aya::{Bpf, programs::KProbe}; + /// use std::convert::TryInto; + /// + /// let program: &mut KProbe = bpf.program_mut("intercept_wakeups")?.try_into()?; + /// program.attach("try_to_wake_up", 0, None)?; + /// # Ok::<(), aya::BpfError>(()) + /// ``` + /// pub fn attach( &mut self, fn_name: &str, diff --git a/aya/src/programs/uprobe.rs b/aya/src/programs/uprobe.rs index 6e51907e..f0af5c43 100644 --- a/aya/src/programs/uprobe.rs +++ b/aya/src/programs/uprobe.rs @@ -30,6 +30,13 @@ lazy_static! { } const LD_SO_CACHE_HEADER: &str = "glibc-ld.so.cache1.1"; +/// An user space probe. +/// +/// User probes are eBPF programs that can be attached to any userspace +/// function. They can be of two kinds: +/// +/// - `uprobe`: get attached to the *start* of the target functions +/// - `uretprobe`: get attached to the *return address* of the target functions #[derive(Debug)] pub struct UProbe { pub(crate) data: ProgramData, @@ -37,14 +44,38 @@ pub struct UProbe { } impl UProbe { + /// Loads the program inside the kernel. + /// + /// See also [`Program::load`](crate::programs::Program::load). pub fn load(&mut self) -> Result<(), ProgramError> { load_program(BPF_PROG_TYPE_KPROBE, &mut self.data) } + /// Returns the name of the program. pub fn name(&self) -> String { self.data.name.to_string() } + /// Returns `UProbe` if the program is a `uprobe`, or `URetProbe` if the + /// program is a `uretprobe`. + pub fn kind(&self) -> ProbeKind { + self.kind + } + + /// Attaches the program. + /// + /// Attaches the uprobe to the function `fn_name` defined in the `target`. + /// If `offset` is non-zero, it is added to the address of the target + /// function. If `pid` is `Some()`, the program executes only when the target + /// function is executed by the given `pid`. + /// + /// The `target` argument can be an absolute path to a binary or library, or + /// a library name (eg: `"libc"`). + /// + /// If the program is an `uprobe`, it is attached to the *start* address of the target + /// function. Instead if the program is a `kretprobe`, it is attached to the return address of + /// the target function. + /// pub fn attach>( &mut self, fn_name: Option<&str>, diff --git a/aya/src/programs/xdp.rs b/aya/src/programs/xdp.rs index 75b89c9e..5b84728d 100644 --- a/aya/src/programs/xdp.rs +++ b/aya/src/programs/xdp.rs @@ -32,20 +32,55 @@ bitflags! { } } +/// An XDP program. +/// +/// eXpress Data Path (XDP) programs can be attached to the very early stages of network +/// processing, where they can apply custom packet processing logic. When supported by the +/// underlying network driver, XDP programs can execute directly on network cards, greatly +/// reducing CPU load. #[derive(Debug)] pub struct Xdp { pub(crate) data: ProgramData, } impl Xdp { + /// Loads the program inside the kernel. + /// + /// See also [`Program::load`](crate::programs::Program::load). pub fn load(&mut self) -> Result<(), ProgramError> { load_program(BPF_PROG_TYPE_XDP, &mut self.data) } + /// Returns the name of the program. pub fn name(&self) -> String { self.data.name.to_string() } + /// Attaches the program. + /// + /// Attaches the program to the given `interface`. + /// + /// # Errors + /// + /// If the given `interface` does not exist + /// [`ProgramError::UnknownInterface`] is returned. + /// + /// When attaching fails, [`ProgramError::SyscallError`] is returned for + /// kernels `>= 5.9.0`, and instead + /// [`XdpError::NetlinkError`] is returned for older + /// kernels. + /// + /// # Example + /// + /// ```no_run + /// # let mut bpf = Bpf::load_file("ebpf_programs.o")?; + /// use aya::{Bpf, programs::{Xdp, XdpFlags}}; + /// use std::convert::TryInto; + /// + /// let program: &mut Xdp = bpf.program_mut("intercept_packets")?.try_into()?; + /// program.attach("eth0", XdpFlags::default())?; + /// # Ok::<(), aya::BpfError>(()) + /// ``` pub fn attach(&mut self, interface: &str, flags: XdpFlags) -> Result { let prog_fd = self.data.fd_or_err()?;