|
|
@ -1,14 +1,17 @@
|
|
|
|
//! eBPF program types.
|
|
|
|
//! eBPF program types.
|
|
|
|
//!
|
|
|
|
//!
|
|
|
|
//! eBPF programs are loaded inside the kernel and attached to one or more hook points. Whenever
|
|
|
|
//! eBPF programs are loaded inside the kernel and attached to one or more hook
|
|
|
|
//! the kernel or an application reaches those hook points, the programs are executed.
|
|
|
|
//! points. Whenever the hook points are reached, the programs are executed.
|
|
|
|
//!
|
|
|
|
//!
|
|
|
|
//! # Loading programs
|
|
|
|
//! # Loading and attaching programs
|
|
|
|
//!
|
|
|
|
//!
|
|
|
|
//! When you call [`Bpf::load_file`] or [`Bpf::load`], all the programs present in the code are
|
|
|
|
//! When you call [`Bpf::load_file`] or [`Bpf::load`], all the programs included
|
|
|
|
//! parsed and can be retrieved using the [`Bpf::program`] and [`Bpf::program_mut`] methods. In
|
|
|
|
//! in the object code are parsed and relocated. Programs are not loaded
|
|
|
|
//! order to load a program, you need to get a handle to it and call the `load()` method, for
|
|
|
|
//! automatically though, since often you will need to do some application
|
|
|
|
//! example:
|
|
|
|
//! specific setup before you can actually load them.
|
|
|
|
|
|
|
|
//!
|
|
|
|
|
|
|
|
//! In order to load and attach a program, you need to retrieve it using [`Bpf::program_mut`],
|
|
|
|
|
|
|
|
//! then call the `load()` and `attach()` methods, for example:
|
|
|
|
//!
|
|
|
|
//!
|
|
|
|
//! ```no_run
|
|
|
|
//! ```no_run
|
|
|
|
//! use aya::{Bpf, programs::KProbe};
|
|
|
|
//! use aya::{Bpf, programs::KProbe};
|
|
|
@ -18,32 +21,21 @@
|
|
|
|
//! // intercept_wakeups is the name of the program we want to load
|
|
|
|
//! // intercept_wakeups is the name of the program we want to load
|
|
|
|
//! let program: &mut KProbe = bpf.program_mut("intercept_wakeups")?.try_into()?;
|
|
|
|
//! let program: &mut KProbe = bpf.program_mut("intercept_wakeups")?.try_into()?;
|
|
|
|
//! program.load()?;
|
|
|
|
//! program.load()?;
|
|
|
|
|
|
|
|
//! // intercept_wakeups will be called every time try_to_wake_up() is called
|
|
|
|
|
|
|
|
//! // inside the kernel
|
|
|
|
|
|
|
|
//! program.attach("try_to_wake_up", 0, None)?;
|
|
|
|
//! # Ok::<(), aya::BpfError>(())
|
|
|
|
//! # Ok::<(), aya::BpfError>(())
|
|
|
|
//! ```
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//!
|
|
|
|
//! # Attaching programs
|
|
|
|
//! The signature of the `attach()` method varies depending on what kind of
|
|
|
|
//!
|
|
|
|
//! program you're trying to attach.
|
|
|
|
//! After being loaded, programs must be attached to their target hook points to be executed. The
|
|
|
|
|
|
|
|
//! eBPF platform supports many different program types, with each type providing different
|
|
|
|
|
|
|
|
//! attachment options. For example when attaching a [`KProbe`], you must provide the name of the
|
|
|
|
|
|
|
|
//! kernel function you want instrument; when loading an [`Xdp`] program, you need to specify the
|
|
|
|
|
|
|
|
//! network card name you want to hook into, and so forth.
|
|
|
|
|
|
|
|
//!
|
|
|
|
|
|
|
|
//! Currently aya supports [`KProbe`], [`UProbe`], [`SocketFilter`], [`TracePoint`] and [`Xdp`]
|
|
|
|
|
|
|
|
//! programs. To see how to attach them, see the documentation of the respective `attach()` method.
|
|
|
|
|
|
|
|
//!
|
|
|
|
|
|
|
|
//! # Interacting with programs
|
|
|
|
|
|
|
|
//!
|
|
|
|
|
|
|
|
//! eBPF programs are event-driven and execute when the hook points they are attached to are hit.
|
|
|
|
|
|
|
|
//! To communicate with user-space, programs use data structures provided by the eBPF platform,
|
|
|
|
|
|
|
|
//! which can be found in the [maps] module.
|
|
|
|
|
|
|
|
//!
|
|
|
|
//!
|
|
|
|
//! [`Bpf::load_file`]: crate::Bpf::load_file
|
|
|
|
//! [`Bpf::load_file`]: crate::Bpf::load_file
|
|
|
|
//! [`Bpf::load`]: crate::Bpf::load
|
|
|
|
//! [`Bpf::load`]: crate::Bpf::load
|
|
|
|
//! [`Bpf::programs`]: crate::Bpf::programs
|
|
|
|
//! [`Bpf::programs`]: crate::Bpf::programs
|
|
|
|
//! [`Bpf::program`]: crate::Bpf::program
|
|
|
|
//! [`Bpf::program`]: crate::Bpf::program
|
|
|
|
//! [`Bpf::program_mut`]: crate::Bpf::program_mut
|
|
|
|
//! [`Bpf::program_mut`]: crate::Bpf::program_mut
|
|
|
|
//! [maps]: crate::maps
|
|
|
|
//! [`maps`]: crate::maps
|
|
|
|
mod cgroup_skb;
|
|
|
|
mod cgroup_skb;
|
|
|
|
mod kprobe;
|
|
|
|
mod kprobe;
|
|
|
|
mod perf_attach;
|
|
|
|
mod perf_attach;
|
|
|
@ -80,61 +72,83 @@ use crate::{
|
|
|
|
obj::{self, Function},
|
|
|
|
obj::{self, Function},
|
|
|
|
sys::{bpf_load_program, bpf_prog_detach},
|
|
|
|
sys::{bpf_load_program, bpf_prog_detach},
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Error type returned when working with programs.
|
|
|
|
#[derive(Debug, Error)]
|
|
|
|
#[derive(Debug, Error)]
|
|
|
|
pub enum ProgramError {
|
|
|
|
pub enum ProgramError {
|
|
|
|
|
|
|
|
/// The program could not be found in the object code.
|
|
|
|
#[error("program `{name}` not found")]
|
|
|
|
#[error("program `{name}` not found")]
|
|
|
|
NotFound { name: String },
|
|
|
|
NotFound { name: String },
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// The program is already loaded.
|
|
|
|
#[error("the program is already loaded")]
|
|
|
|
#[error("the program is already loaded")]
|
|
|
|
AlreadyLoaded,
|
|
|
|
AlreadyLoaded,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// The program is not loaded.
|
|
|
|
#[error("the program is not loaded")]
|
|
|
|
#[error("the program is not loaded")]
|
|
|
|
NotLoaded,
|
|
|
|
NotLoaded,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// The program is already detached.
|
|
|
|
#[error("the program was already detached")]
|
|
|
|
#[error("the program was already detached")]
|
|
|
|
AlreadyDetached,
|
|
|
|
AlreadyDetached,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// The program is not attached.
|
|
|
|
#[error("the program is not attached")]
|
|
|
|
#[error("the program is not attached")]
|
|
|
|
NotAttached,
|
|
|
|
NotAttached,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Loading the program failed.
|
|
|
|
#[error("the BPF_PROG_LOAD syscall failed. Verifier output: {verifier_log}")]
|
|
|
|
#[error("the BPF_PROG_LOAD syscall failed. Verifier output: {verifier_log}")]
|
|
|
|
LoadError {
|
|
|
|
LoadError {
|
|
|
|
|
|
|
|
/// The [`io::Error`] returned by the `BPF_PROG_LOAD` syscall.
|
|
|
|
#[source]
|
|
|
|
#[source]
|
|
|
|
io_error: io::Error,
|
|
|
|
io_error: io::Error,
|
|
|
|
|
|
|
|
/// The error log produced by the kernel verifier.
|
|
|
|
verifier_log: String,
|
|
|
|
verifier_log: String,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// A syscall failed.
|
|
|
|
#[error("`{call}` failed")]
|
|
|
|
#[error("`{call}` failed")]
|
|
|
|
SyscallError {
|
|
|
|
SyscallError {
|
|
|
|
|
|
|
|
/// The name of the syscall which failed.
|
|
|
|
call: String,
|
|
|
|
call: String,
|
|
|
|
|
|
|
|
/// The [`io::Error`] returned by the syscall.
|
|
|
|
#[source]
|
|
|
|
#[source]
|
|
|
|
io_error: io::Error,
|
|
|
|
io_error: io::Error,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// The network interface does not exist.
|
|
|
|
#[error("unknown network interface {name}")]
|
|
|
|
#[error("unknown network interface {name}")]
|
|
|
|
UnknownInterface { name: String },
|
|
|
|
UnknownInterface { name: String },
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// The program is not of the expected type.
|
|
|
|
#[error("unexpected program type")]
|
|
|
|
#[error("unexpected program type")]
|
|
|
|
UnexpectedProgramType,
|
|
|
|
UnexpectedProgramType,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// A map error occurred while loading or attaching a program.
|
|
|
|
#[error(transparent)]
|
|
|
|
#[error(transparent)]
|
|
|
|
MapError(#[from] MapError),
|
|
|
|
MapError(#[from] MapError),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// An error occurred while working with a [`KProbe`].
|
|
|
|
#[error(transparent)]
|
|
|
|
#[error(transparent)]
|
|
|
|
KProbeError(#[from] KProbeError),
|
|
|
|
KProbeError(#[from] KProbeError),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// An error occurred while working with an [`UProbe`].
|
|
|
|
#[error(transparent)]
|
|
|
|
#[error(transparent)]
|
|
|
|
UProbeError(#[from] UProbeError),
|
|
|
|
UProbeError(#[from] UProbeError),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// An error occurred while working with a [`TracePoint`].
|
|
|
|
#[error(transparent)]
|
|
|
|
#[error(transparent)]
|
|
|
|
TracePointError(#[from] TracePointError),
|
|
|
|
TracePointError(#[from] TracePointError),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// An error occurred while working with a [`SocketFilter`].
|
|
|
|
#[error(transparent)]
|
|
|
|
#[error(transparent)]
|
|
|
|
SocketFilterError(#[from] SocketFilterError),
|
|
|
|
SocketFilterError(#[from] SocketFilterError),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// An error occurred while working with an [`Xdp`] program.
|
|
|
|
#[error(transparent)]
|
|
|
|
#[error(transparent)]
|
|
|
|
XdpError(#[from] XdpError),
|
|
|
|
XdpError(#[from] XdpError),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// An error occurred while working with a TC program.
|
|
|
|
#[error(transparent)]
|
|
|
|
#[error(transparent)]
|
|
|
|
TcError(#[from] TcError),
|
|
|
|
TcError(#[from] TcError),
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -353,10 +367,15 @@ fn load_program(prog_type: bpf_prog_type, data: &mut ProgramData) -> Result<(),
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Detach an attached program.
|
|
|
|
pub trait Link: std::fmt::Debug {
|
|
|
|
pub trait Link: std::fmt::Debug {
|
|
|
|
fn detach(&mut self) -> Result<(), ProgramError>;
|
|
|
|
fn detach(&mut self) -> Result<(), ProgramError>;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// The return type of `program.attach(...)`.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// [`LinkRef`] implements the [`Link`] trait and can be used to detach a
|
|
|
|
|
|
|
|
/// program.
|
|
|
|
#[derive(Debug)]
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct LinkRef {
|
|
|
|
pub struct LinkRef {
|
|
|
|
inner: Rc<RefCell<dyn Link>>,
|
|
|
|
inner: Rc<RefCell<dyn Link>>,
|
|
|
|