@ -3,7 +3,11 @@ use std::{
collections ::{ HashMap , HashSet } ,
ffi ::CString ,
fs , io ,
os ::{ fd ::RawFd , raw ::c_int } ,
ops ::{ Deref , DerefMut } ,
os ::{
fd ::{ AsFd , BorrowedFd , OwnedFd , RawFd } ,
raw ::c_int ,
} ,
path ::{ Path , PathBuf } ,
} ;
@ -473,7 +477,6 @@ impl<'a> BpfLoader<'a> {
obj ,
fd : None ,
pinned : false ,
btf_fd ,
} ;
let fd = match map . obj . pinning ( ) {
PinningType ::ByName = > {
@ -488,7 +491,7 @@ impl<'a> BpfLoader<'a> {
fd as RawFd
}
Err ( _ ) = > {
let fd = map . create ( & name )? ;
let fd = map . create ( & name , btf_fd . as_ref ( ) )? ;
map . pin ( & name , path ) . map_err ( | error | MapError ::PinError {
name : Some ( name . to_string ( ) ) ,
error ,
@ -497,7 +500,7 @@ impl<'a> BpfLoader<'a> {
}
}
}
PinningType ::None = > map . create ( & name )? ,
PinningType ::None = > map . create ( & name , btf_fd . as_ref ( ) )? ,
} ;
if ! map . obj . data ( ) . is_empty ( ) & & map . obj . section_kind ( ) ! = BpfSectionKind ::Bss {
bpf_map_update_elem_ptr ( fd , & 0 as * const _ , map . obj . data_mut ( ) . as_mut_ptr ( ) , 0 )
@ -545,70 +548,69 @@ impl<'a> BpfLoader<'a> {
let program = if extensions . contains ( name . as_str ( ) ) {
Program ::Extension ( Extension {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
} )
} else {
match & section {
ProgramSection ::KProbe { .. } = > Program ::KProbe ( KProbe {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
kind : ProbeKind ::KProbe ,
} ) ,
ProgramSection ::KRetProbe { .. } = > Program ::KProbe ( KProbe {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
kind : ProbeKind ::KRetProbe ,
} ) ,
ProgramSection ::UProbe { .. } = > Program ::UProbe ( UProbe {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
kind : ProbeKind ::UProbe ,
} ) ,
ProgramSection ::URetProbe { .. } = > Program ::UProbe ( UProbe {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
kind : ProbeKind ::URetProbe ,
} ) ,
ProgramSection ::TracePoint { .. } = > Program ::TracePoint ( TracePoint {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
} ) ,
ProgramSection ::SocketFilter { .. } = > {
Program ::SocketFilter ( SocketFilter {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
} )
}
ProgramSection ::Xdp { frags , .. } = > {
let mut data =
ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ;
let mut data = ProgramData ::new ( prog_name , obj , * verifier_log_level ) ;
if * frags {
data . flags = BPF_F_XDP_HAS_FRAGS ;
}
Program ::Xdp ( Xdp { data } )
}
ProgramSection ::SkMsg { .. } = > Program ::SkMsg ( SkMsg {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
} ) ,
ProgramSection ::CgroupSysctl { .. } = > {
Program ::CgroupSysctl ( CgroupSysctl {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
} )
}
ProgramSection ::CgroupSockopt { attach_type , .. } = > {
Program ::CgroupSockopt ( CgroupSockopt {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
attach_type : * attach_type ,
} )
}
ProgramSection ::SkSkbStreamParser { .. } = > Program ::SkSkb ( SkSkb {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
kind : SkSkbKind ::StreamParser ,
} ) ,
ProgramSection ::SkSkbStreamVerdict { .. } = > Program ::SkSkb ( SkSkb {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
kind : SkSkbKind ::StreamVerdict ,
} ) ,
ProgramSection ::SockOps { .. } = > Program ::SockOps ( SockOps {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
} ) ,
ProgramSection ::SchedClassifier { .. } = > {
Program ::SchedClassifier ( SchedClassifier {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
name : unsafe {
CString ::from_vec_unchecked ( Vec ::from ( name . clone ( ) ) )
. into_boxed_c_str ( )
@ -616,37 +618,36 @@ impl<'a> BpfLoader<'a> {
} )
}
ProgramSection ::CgroupSkb { .. } = > Program ::CgroupSkb ( CgroupSkb {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
expected_attach_type : None ,
} ) ,
ProgramSection ::CgroupSkbIngress { .. } = > Program ::CgroupSkb ( CgroupSkb {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
expected_attach_type : Some ( CgroupSkbAttachType ::Ingress ) ,
} ) ,
ProgramSection ::CgroupSkbEgress { .. } = > Program ::CgroupSkb ( CgroupSkb {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
expected_attach_type : Some ( CgroupSkbAttachType ::Egress ) ,
} ) ,
ProgramSection ::CgroupSockAddr { attach_type , .. } = > {
Program ::CgroupSockAddr ( CgroupSockAddr {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
attach_type : * attach_type ,
} )
}
ProgramSection ::LircMode2 { .. } = > Program ::LircMode2 ( LircMode2 {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
} ) ,
ProgramSection ::PerfEvent { .. } = > Program ::PerfEvent ( PerfEvent {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
} ) ,
ProgramSection ::RawTracePoint { .. } = > {
Program ::RawTracePoint ( RawTracePoint {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
} )
}
ProgramSection ::Lsm { sleepable , .. } = > {
let mut data =
ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ;
let mut data = ProgramData ::new ( prog_name , obj , * verifier_log_level ) ;
if * sleepable {
data . flags = BPF_F_SLEEPABLE ;
}
@ -654,30 +655,30 @@ impl<'a> BpfLoader<'a> {
}
ProgramSection ::BtfTracePoint { .. } = > {
Program ::BtfTracePoint ( BtfTracePoint {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
} )
}
ProgramSection ::FEntry { .. } = > Program ::FEntry ( FEntry {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
} ) ,
ProgramSection ::FExit { .. } = > Program ::FExit ( FExit {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
} ) ,
ProgramSection ::Extension { .. } = > Program ::Extension ( Extension {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
} ) ,
ProgramSection ::SkLookup { .. } = > Program ::SkLookup ( SkLookup {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
} ) ,
ProgramSection ::CgroupSock { attach_type , .. } = > {
Program ::CgroupSock ( CgroupSock {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
attach_type : * attach_type ,
} )
}
ProgramSection ::CgroupDevice { .. } = > {
Program ::CgroupDevice ( CgroupDevice {
data : ProgramData ::new ( prog_name , obj , btf_fd , * verifier_log_level ) ,
data : ProgramData ::new ( prog_name , obj , * verifier_log_level ) ,
} )
}
}
@ -699,7 +700,11 @@ impl<'a> BpfLoader<'a> {
} ) ? ;
} ;
Ok ( Bpf { maps , programs } )
Ok ( Bpf {
maps ,
programs ,
btf_fd ,
} )
}
}
@ -741,11 +746,53 @@ impl<'a> Default for BpfLoader<'a> {
}
}
/// A program with a BTF file descriptor
pub struct WithBtfFd < ' p , P > {
/// The program underneath
pub program : & ' p mut P ,
pub ( crate ) btf_fd : Option < BorrowedFd < ' p > > ,
}
impl < ' f , P > Deref for WithBtfFd < ' f , P > {
type Target = P ;
fn deref ( & self ) -> & Self ::Target {
& * self . program
}
}
impl < ' f , P > DerefMut for WithBtfFd < ' f , P > {
fn deref_mut ( & mut self ) -> & mut Self ::Target {
self . program
}
}
impl < ' p , P , T > AsRef < T > for WithBtfFd < ' p , P >
where
T : ? Sized ,
< WithBtfFd < ' p , P > as Deref > ::Target : AsRef < T > ,
{
fn as_ref ( & self ) -> & T {
self . deref ( ) . as_ref ( )
}
}
impl < ' p , P , T > AsMut < T > for WithBtfFd < ' p , P >
where
< WithBtfFd < ' p , P > as Deref > ::Target : AsMut < T > ,
{
fn as_mut ( & mut self ) -> & mut T {
self . deref_mut ( ) . as_mut ( )
}
}
/// The main entry point into the library, used to work with eBPF programs and maps.
#[ derive(Debug) ]
#[ non_exhaustive ]
pub struct Bpf {
maps : HashMap < String , Map > ,
programs : HashMap < String , Program > ,
btf_fd : Option < OwnedFd > ,
}
impl Bpf {
@ -882,13 +929,16 @@ impl Bpf {
/// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::programs::UProbe;
///
/// let program: &mut UProbe = bpf.program_mut("SSL_read").unwrap().try_into()?;
/// let mut program: aya::WithBtfFd<UProbe> = bpf.program_mut("SSL_read").unwrap().try_into()?;
/// program.load()?;
/// program.attach(Some("SSL_read"), 0, "libssl", None)?;
/// # Ok::<(), aya::BpfError>(())
/// ```
pub fn program_mut ( & mut self , name : & str ) -> Option < & mut Program > {
self . programs . get_mut ( name )
pub fn program_mut ( & mut self , name : & str ) -> Option < WithBtfFd < ' _ , Program > > {
self . programs . get_mut ( name ) . map ( | program | WithBtfFd {
program ,
btf_fd : self . btf_fd . as_ref ( ) . map ( | p | p . as_fd ( ) ) ,
} )
}
/// An iterator over all the programs.
@ -993,12 +1043,12 @@ pub enum BpfError {
ProgramError ( #[ from ] ProgramError ) ,
}
fn load_btf ( raw_btf : Vec < u8 > , verifier_log_level : VerifierLogLevel ) -> Result < Raw Fd, BtfError > {
fn load_btf ( raw_btf : Vec < u8 > , verifier_log_level : VerifierLogLevel ) -> Result < Owned Fd, BtfError > {
let ( ret , verifier_log ) = retry_with_verifier_logs ( 10 , | logger | {
bpf_load_btf ( raw_btf . as_slice ( ) , logger , verifier_log_level )
} ) ;
match ret {
Ok ( fd ) = > Ok ( fd as RawFd ) ,
Ok ( fd ) = > Ok ( fd ) ,
Err ( ( _ , io_error ) ) = > Err ( BtfError ::LoadError {
io_error ,
verifier_log ,