diff --git a/README.md b/README.md index de31ec77..8f154fe8 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ use aya::programs::{CgroupSkb, CgroupSkbAttachType}; let mut bpf = Bpf::load_file("bpf.o")?; // get the `ingress_filter` program compiled into `bpf.o`. -let ingress: &mut CgroupSkb = bpf.program_mut("ingress_filter")?.try_into()?; +let mut ingress: aya::WithBtfFd = bpf.program_mut("ingress_filter")?.try_into()?; // load the program into the kernel ingress.load()?; diff --git a/aya/README.md b/aya/README.md index 873612af..a24109c1 100644 --- a/aya/README.md +++ b/aya/README.md @@ -82,7 +82,7 @@ use aya::programs::{CgroupSkb, CgroupSkbAttachType}; let mut bpf = Bpf::load_file("bpf.o")?; // get the `ingress_filter` program compiled into `bpf.o`. -let ingress: &mut CgroupSkb = bpf.program_mut("ingress_filter")?.try_into()?; +let mut ingress: aya::WithBtfFd = bpf.program_mut("ingress_filter")?.try_into()?; // load the program into the kernel ingress.load()?; diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 818a063b..7fa55c6a 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -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 §ion { 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>, +} + +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 for WithBtfFd<'p, P> +where + T: ?Sized, + as Deref>::Target: AsRef, +{ + fn as_ref(&self) -> &T { + self.deref().as_ref() + } +} + +impl<'p, P, T> AsMut for WithBtfFd<'p, P> +where + as Deref>::Target: AsMut, +{ + 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, programs: HashMap, + btf_fd: Option, } 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 = 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> { + 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, verifier_log_level: VerifierLogLevel) -> Result { +fn load_btf(raw_btf: Vec, verifier_log_level: VerifierLogLevel) -> Result { 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, diff --git a/aya/src/maps/bloom_filter.rs b/aya/src/maps/bloom_filter.rs index f646c2bb..93df55fe 100644 --- a/aya/src/maps/bloom_filter.rs +++ b/aya/src/maps/bloom_filter.rs @@ -118,7 +118,6 @@ mod tests { obj: new_obj_map(), fd: None, pinned: false, - btf_fd: None, }; assert_matches!( BloomFilter::<_, u16>::new(&map), @@ -147,7 +146,6 @@ mod tests { }), fd: None, pinned: false, - btf_fd: None, }; let map = Map::PerfEventArray(map_data); @@ -164,7 +162,6 @@ mod tests { obj: new_obj_map(), fd: None, pinned: false, - btf_fd: None, }; assert_matches!( @@ -179,7 +176,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; assert!(BloomFilter::<_, u32>::new(&mut map).is_ok()); @@ -191,7 +187,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let map = Map::BloomFilter(map_data); @@ -206,7 +201,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let bloom_filter = BloomFilter::<_, u32>::new(&mut map).unwrap(); @@ -230,7 +224,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let bloom_filter = BloomFilter::<_, u32>::new(&mut map).unwrap(); @@ -244,7 +237,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let bloom_filter = BloomFilter::<_, u32>::new(&map).unwrap(); @@ -267,7 +259,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let bloom_filter = BloomFilter::<_, u32>::new(&map).unwrap(); diff --git a/aya/src/maps/hash_map/hash_map.rs b/aya/src/maps/hash_map/hash_map.rs index 2fcb1334..93b6228d 100644 --- a/aya/src/maps/hash_map/hash_map.rs +++ b/aya/src/maps/hash_map/hash_map.rs @@ -149,7 +149,6 @@ mod tests { obj: new_obj_map(), fd: None, pinned: false, - btf_fd: None, }; assert_matches!( HashMap::<_, u8, u32>::new(&map), @@ -166,7 +165,6 @@ mod tests { obj: new_obj_map(), fd: None, pinned: false, - btf_fd: None, }; assert_matches!( HashMap::<_, u32, u16>::new(&map), @@ -183,7 +181,6 @@ mod tests { obj: new_obj_map(), fd: None, pinned: false, - btf_fd: None, }; let map = Map::Array(map_data); @@ -199,7 +196,6 @@ mod tests { obj: new_obj_map(), fd: None, pinned: false, - btf_fd: None, }; let map = Map::HashMap(map_data); @@ -218,7 +214,6 @@ mod tests { obj: new_obj_map(), fd: None, pinned: false, - btf_fd: None, }; assert_matches!( @@ -233,7 +228,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; assert!(HashMap::<_, u32, u32>::new(&mut map).is_ok()); @@ -245,7 +239,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let map = Map::HashMap(map_data); @@ -270,7 +263,6 @@ mod tests { }), fd: Some(42), pinned: false, - btf_fd: None, }; let map = Map::HashMap(map_data); @@ -286,7 +278,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap(); @@ -310,7 +301,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap(); @@ -331,7 +321,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap(); @@ -346,7 +335,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap(); @@ -370,7 +358,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap(); @@ -384,7 +371,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); @@ -407,7 +393,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); @@ -444,7 +429,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let keys = hm.keys().collect::, _>>(); @@ -493,7 +477,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); @@ -526,7 +509,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); @@ -561,7 +543,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let items = hm.iter().collect::, _>>().unwrap(); @@ -599,7 +580,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); @@ -638,7 +618,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); @@ -683,7 +662,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); diff --git a/aya/src/maps/lpm_trie.rs b/aya/src/maps/lpm_trie.rs index 4adb3f47..55c7f3b9 100644 --- a/aya/src/maps/lpm_trie.rs +++ b/aya/src/maps/lpm_trie.rs @@ -237,7 +237,6 @@ mod tests { obj: new_obj_map(), fd: None, pinned: false, - btf_fd: None, }; assert_matches!( LpmTrie::<_, u16, u32>::new(&map), @@ -254,7 +253,6 @@ mod tests { obj: new_obj_map(), fd: None, pinned: false, - btf_fd: None, }; assert_matches!( LpmTrie::<_, u32, u16>::new(&map), @@ -282,7 +280,6 @@ mod tests { data: Vec::new(), }), fd: None, - btf_fd: None, pinned: false, }; @@ -300,7 +297,6 @@ mod tests { obj: new_obj_map(), fd: None, pinned: false, - btf_fd: None, }; assert_matches!( @@ -315,7 +311,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; assert!(LpmTrie::<_, u32, u32>::new(&mut map).is_ok()); @@ -327,7 +322,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let map = Map::LpmTrie(map_data); @@ -342,7 +336,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap(); let ipaddr = Ipv4Addr::new(8, 8, 8, 8); @@ -367,7 +360,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap(); @@ -384,7 +376,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap(); let ipaddr = Ipv4Addr::new(8, 8, 8, 8); @@ -409,7 +400,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap(); let ipaddr = Ipv4Addr::new(8, 8, 8, 8); @@ -424,7 +414,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let trie = LpmTrie::<_, u32, u32>::new(&map).unwrap(); let ipaddr = Ipv4Addr::new(8, 8, 8, 8); @@ -449,7 +438,6 @@ mod tests { obj: new_obj_map(), fd: Some(42), pinned: false, - btf_fd: None, }; let trie = LpmTrie::<_, u32, u32>::new(&map).unwrap(); let ipaddr = Ipv4Addr::new(8, 8, 8, 8); diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index fca42110..d4f2fac0 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -24,7 +24,7 @@ //! //! let intercept_egress = SockMap::try_from(bpf.map_mut("INTERCEPT_EGRESS").unwrap())?; //! let map_fd = intercept_egress.fd()?; -//! let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; +//! let mut prog: aya::WithBtfFd = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; //! prog.load()?; //! prog.attach(map_fd)?; //! @@ -42,7 +42,7 @@ use std::{ marker::PhantomData, mem, ops::Deref, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, RawFd}, path::Path, ptr, }; @@ -486,14 +486,13 @@ pub(crate) fn check_v_size(map: &MapData) -> Result<(), MapError> { pub struct MapData { pub(crate) obj: obj::Map, pub(crate) fd: Option, - pub(crate) btf_fd: Option, /// Indicates if this map has been pinned to bpffs pub pinned: bool, } impl MapData { /// Creates a new map with the provided `name` - pub fn create(&mut self, name: &str) -> Result { + pub fn create(&mut self, name: &str, btf_fd: Option) -> Result { if self.fd.is_some() { return Err(MapError::AlreadyCreated { name: name.into() }); } @@ -504,7 +503,7 @@ impl MapData { let kernel_version = KernelVersion::current().unwrap(); #[cfg(test)] let kernel_version = KernelVersion::new(0xff, 0xff, 0xff); - let fd = bpf_create_map(&c_name, &self.obj, self.btf_fd, kernel_version).map_err( + let fd = bpf_create_map(&c_name, &self.obj, btf_fd, kernel_version).map_err( |(code, io_error)| { if kernel_version < KernelVersion::new(5, 11, 0) { maybe_warn_rlimit(); @@ -568,7 +567,6 @@ impl MapData { Ok(MapData { obj: parse_map_info(info, PinningType::ByName), fd: Some(fd), - btf_fd: None, pinned: true, }) } @@ -587,7 +585,6 @@ impl MapData { Ok(MapData { obj: parse_map_info(info, PinningType::None), fd: Some(fd), - btf_fd: None, pinned: false, }) } @@ -639,7 +636,6 @@ impl Clone for MapData { MapData { obj: self.obj.clone(), fd: self.fd.map(|fd| unsafe { libc::dup(fd) }), - btf_fd: self.btf_fd, pinned: self.pinned, } } @@ -842,6 +838,8 @@ impl Deref for PerCpuValues { #[cfg(test)] mod tests { + use std::os::fd::BorrowedFd; + use assert_matches::assert_matches; use libc::EFAULT; @@ -876,7 +874,6 @@ mod tests { obj: new_obj_map(), fd: None, pinned: false, - btf_fd: None, } } @@ -891,9 +888,12 @@ mod tests { }); let mut map = new_map(); - assert_matches!(map.create("foo"), Ok(42)); + assert_matches!(map.create("foo", Option::::None), Ok(42)); assert_eq!(map.fd, Some(42)); - assert_matches!(map.create("foo"), Err(MapError::AlreadyCreated { .. })); + assert_matches!( + map.create("foo", Option::::None), + Err(MapError::AlreadyCreated { .. }) + ); } #[test] @@ -901,7 +901,7 @@ mod tests { override_syscall(|_| Err((-42, io::Error::from_raw_os_error(EFAULT)))); let mut map = new_map(); - let ret = map.create("foo"); + let ret = map.create("foo", Option::::None); assert_matches!(ret, Err(MapError::CreateError { .. })); if let Err(MapError::CreateError { name, diff --git a/aya/src/maps/sock/sock_hash.rs b/aya/src/maps/sock/sock_hash.rs index be78e386..360b0b38 100644 --- a/aya/src/maps/sock/sock_hash.rs +++ b/aya/src/maps/sock/sock_hash.rs @@ -49,7 +49,7 @@ use crate::{ /// let mut intercept_egress = SockHash::<_, u32>::try_from(bpf.map("INTERCEPT_EGRESS").unwrap())?; /// let map_fd = intercept_egress.fd()?; /// -/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; +/// let mut prog: aya::WithBtfFd = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; /// prog.load()?; /// prog.attach(map_fd)?; /// diff --git a/aya/src/maps/sock/sock_map.rs b/aya/src/maps/sock/sock_map.rs index d34f658b..2e6b27e2 100644 --- a/aya/src/maps/sock/sock_map.rs +++ b/aya/src/maps/sock/sock_map.rs @@ -17,7 +17,7 @@ use crate::{ /// sockets. /// /// A `SockMap` can also be used to redirect packets to sockets contained by the -/// map using `bpf_redirect_map()`, `bpf_sk_redirect_map()` etc. +/// map using `bpf_redirect_map()`, `bpf_sk_redirect_map()` etc. /// /// # Minimum kernel version /// @@ -33,7 +33,7 @@ use crate::{ /// let intercept_ingress = SockMap::try_from(bpf.map("INTERCEPT_INGRESS").unwrap())?; /// let map_fd = intercept_ingress.fd()?; /// -/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?; +/// let mut prog: aya::WithBtfFd = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?; /// prog.load()?; /// prog.attach(map_fd)?; /// diff --git a/aya/src/programs/cgroup_device.rs b/aya/src/programs/cgroup_device.rs index e3580b28..78a504ee 100644 --- a/aya/src/programs/cgroup_device.rs +++ b/aya/src/programs/cgroup_device.rs @@ -1,7 +1,7 @@ //! Cgroup device programs. -use crate::util::KernelVersion; -use std::os::fd::{AsRawFd, RawFd}; +use crate::{util::KernelVersion, WithBtfFd}; +use std::os::fd::{AsFd, AsRawFd, RawFd}; use crate::{ generated::{bpf_attach_type::BPF_CGROUP_DEVICE, bpf_prog_type::BPF_PROG_TYPE_CGROUP_DEVICE}, @@ -40,7 +40,7 @@ use crate::{ /// use aya::programs::CgroupDevice; /// /// let cgroup = std::fs::File::open("/sys/fs/cgroup/unified")?; -/// let program: &mut CgroupDevice = bpf.program_mut("cgroup_dev").unwrap().try_into()?; +/// let mut program: aya::WithBtfFd = bpf.program_mut("cgroup_dev").unwrap().try_into()?; /// program.load()?; /// program.attach(cgroup)?; /// # Ok::<(), Error>(()) @@ -51,10 +51,17 @@ pub struct CgroupDevice { pub(crate) data: ProgramData, } +impl<'p> WithBtfFd<'p, CgroupDevice> { + /// Loads the program inside the kernel. + pub fn load(&mut self) -> Result<(), ProgramError> { + self.program.load(self.btf_fd) + } +} + impl CgroupDevice { /// Loads the program inside the kernel - pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_CGROUP_DEVICE, &mut self.data) + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { + load_program(BPF_PROG_TYPE_CGROUP_DEVICE, &mut self.data, btf_fd) } /// Attaches the program to the given cgroup. diff --git a/aya/src/programs/cgroup_skb.rs b/aya/src/programs/cgroup_skb.rs index f67b56fe..6ce5aca7 100644 --- a/aya/src/programs/cgroup_skb.rs +++ b/aya/src/programs/cgroup_skb.rs @@ -1,9 +1,9 @@ //! Cgroup skb programs. -use crate::util::KernelVersion; +use crate::{util::KernelVersion, WithBtfFd}; use std::{ hash::Hash, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, RawFd}, path::Path, }; @@ -50,7 +50,7 @@ use crate::{ /// use aya::programs::{CgroupSkb, CgroupSkbAttachType}; /// /// let file = File::open("/sys/fs/cgroup/unified")?; -/// let egress: &mut CgroupSkb = bpf.program_mut("egress_filter").unwrap().try_into()?; +/// let mut egress: aya::WithBtfFd = bpf.program_mut("egress_filter").unwrap().try_into()?; /// egress.load()?; /// egress.attach(file, CgroupSkbAttachType::Egress)?; /// # Ok::<(), Error>(()) @@ -62,16 +62,23 @@ pub struct CgroupSkb { pub(crate) expected_attach_type: Option, } -impl CgroupSkb { +impl<'p> WithBtfFd<'p, CgroupSkb> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { + self.program.load(self.btf_fd) + } +} + +impl CgroupSkb { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { self.data.expected_attach_type = self.expected_attach_type .map(|attach_type| match attach_type { CgroupSkbAttachType::Ingress => BPF_CGROUP_INET_INGRESS, CgroupSkbAttachType::Egress => BPF_CGROUP_INET_EGRESS, }); - load_program(BPF_PROG_TYPE_CGROUP_SKB, &mut self.data) + load_program(BPF_PROG_TYPE_CGROUP_SKB, &mut self.data, btf_fd) } /// Returns the expected attach type of the program. diff --git a/aya/src/programs/cgroup_sock.rs b/aya/src/programs/cgroup_sock.rs index 9d66f9aa..4288e64b 100644 --- a/aya/src/programs/cgroup_sock.rs +++ b/aya/src/programs/cgroup_sock.rs @@ -2,10 +2,10 @@ pub use aya_obj::programs::CgroupSockAttachType; -use crate::util::KernelVersion; +use crate::{util::KernelVersion, WithBtfFd}; use std::{ hash::Hash, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, RawFd}, path::Path, }; @@ -48,7 +48,7 @@ use crate::{ /// use aya::programs::{CgroupSock, CgroupSockAttachType}; /// /// let file = File::open("/sys/fs/cgroup/unified")?; -/// let bind: &mut CgroupSock = bpf.program_mut("bind").unwrap().try_into()?; +/// let mut bind: aya::WithBtfFd = bpf.program_mut("bind").unwrap().try_into()?; /// bind.load()?; /// bind.attach(file)?; /// # Ok::<(), Error>(()) @@ -60,11 +60,18 @@ pub struct CgroupSock { pub(crate) attach_type: CgroupSockAttachType, } -impl CgroupSock { +impl<'p> WithBtfFd<'p, CgroupSock> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { + self.program.load(self.btf_fd) + } +} + +impl CgroupSock { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { self.data.expected_attach_type = Some(self.attach_type.into()); - load_program(BPF_PROG_TYPE_CGROUP_SOCK, &mut self.data) + load_program(BPF_PROG_TYPE_CGROUP_SOCK, &mut self.data, btf_fd) } /// Attaches the program to the given cgroup. diff --git a/aya/src/programs/cgroup_sock_addr.rs b/aya/src/programs/cgroup_sock_addr.rs index 045a40d2..c51110f2 100644 --- a/aya/src/programs/cgroup_sock_addr.rs +++ b/aya/src/programs/cgroup_sock_addr.rs @@ -2,10 +2,10 @@ pub use aya_obj::programs::CgroupSockAddrAttachType; -use crate::util::KernelVersion; +use crate::{util::KernelVersion, WithBtfFd}; use std::{ hash::Hash, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, RawFd}, path::Path, }; @@ -49,7 +49,7 @@ use crate::{ /// use aya::programs::{CgroupSockAddr, CgroupSockAddrAttachType}; /// /// let file = File::open("/sys/fs/cgroup/unified")?; -/// let egress: &mut CgroupSockAddr = bpf.program_mut("connect4").unwrap().try_into()?; +/// let mut egress: aya::WithBtfFd = bpf.program_mut("connect4").unwrap().try_into()?; /// egress.load()?; /// egress.attach(file)?; /// # Ok::<(), Error>(()) @@ -61,11 +61,18 @@ pub struct CgroupSockAddr { pub(crate) attach_type: CgroupSockAddrAttachType, } -impl CgroupSockAddr { +impl<'p> WithBtfFd<'p, CgroupSockAddr> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { + self.program.load(self.btf_fd) + } +} + +impl CgroupSockAddr { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { self.data.expected_attach_type = Some(self.attach_type.into()); - load_program(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, &mut self.data) + load_program(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, &mut self.data, btf_fd) } /// Attaches the program to the given cgroup. diff --git a/aya/src/programs/cgroup_sockopt.rs b/aya/src/programs/cgroup_sockopt.rs index 95b89dd7..7b4dbb3a 100644 --- a/aya/src/programs/cgroup_sockopt.rs +++ b/aya/src/programs/cgroup_sockopt.rs @@ -2,10 +2,10 @@ pub use aya_obj::programs::CgroupSockoptAttachType; -use crate::util::KernelVersion; +use crate::{util::KernelVersion, WithBtfFd}; use std::{ hash::Hash, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, RawFd}, path::Path, }; @@ -46,7 +46,7 @@ use crate::{ /// use aya::programs::CgroupSockopt; /// /// let file = File::open("/sys/fs/cgroup/unified")?; -/// let program: &mut CgroupSockopt = bpf.program_mut("cgroup_sockopt").unwrap().try_into()?; +/// let mut program: aya::WithBtfFd = bpf.program_mut("cgroup_sockopt").unwrap().try_into()?; /// program.load()?; /// program.attach(file)?; /// # Ok::<(), Error>(()) @@ -58,11 +58,18 @@ pub struct CgroupSockopt { pub(crate) attach_type: CgroupSockoptAttachType, } -impl CgroupSockopt { +impl<'p> WithBtfFd<'p, CgroupSockopt> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { + self.program.load(self.btf_fd) + } +} + +impl CgroupSockopt { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { self.data.expected_attach_type = Some(self.attach_type.into()); - load_program(BPF_PROG_TYPE_CGROUP_SOCKOPT, &mut self.data) + load_program(BPF_PROG_TYPE_CGROUP_SOCKOPT, &mut self.data, btf_fd) } /// Attaches the program to the given cgroup. diff --git a/aya/src/programs/cgroup_sysctl.rs b/aya/src/programs/cgroup_sysctl.rs index 3cd20195..2990c1d5 100644 --- a/aya/src/programs/cgroup_sysctl.rs +++ b/aya/src/programs/cgroup_sysctl.rs @@ -1,9 +1,9 @@ //! Cgroup sysctl programs. -use crate::util::KernelVersion; +use crate::{util::KernelVersion, WithBtfFd}; use std::{ hash::Hash, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, RawFd}, }; use crate::{ @@ -42,7 +42,7 @@ use crate::{ /// use aya::programs::CgroupSysctl; /// /// let file = File::open("/sys/fs/cgroup/unified")?; -/// let program: &mut CgroupSysctl = bpf.program_mut("cgroup_sysctl").unwrap().try_into()?; +/// let mut program: aya::WithBtfFd = bpf.program_mut("cgroup_sysctl").unwrap().try_into()?; /// program.load()?; /// program.attach(file)?; /// # Ok::<(), Error>(()) @@ -53,10 +53,17 @@ pub struct CgroupSysctl { pub(crate) data: ProgramData, } -impl CgroupSysctl { +impl<'p> WithBtfFd<'p, CgroupSysctl> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_CGROUP_SYSCTL, &mut self.data) + self.program.load(self.btf_fd) + } +} + +impl CgroupSysctl { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { + load_program(BPF_PROG_TYPE_CGROUP_SYSCTL, &mut self.data, btf_fd) } /// Attaches the program to the given cgroup. diff --git a/aya/src/programs/extension.rs b/aya/src/programs/extension.rs index 682d14ad..0dbe3aeb 100644 --- a/aya/src/programs/extension.rs +++ b/aya/src/programs/extension.rs @@ -1,5 +1,5 @@ //! Extension programs. -use std::os::fd::{AsRawFd, RawFd}; +use std::os::fd::{AsFd, AsRawFd, RawFd}; use thiserror::Error; use object::Endianness; @@ -11,7 +11,7 @@ use crate::{ define_link_wrapper, load_program, FdLink, FdLinkId, ProgramData, ProgramError, ProgramFd, }, sys::{self, bpf_link_create}, - Btf, + Btf, WithBtfFd, }; /// The type returned when loading or attaching an [`Extension`] fails. @@ -37,12 +37,12 @@ pub enum ExtensionError { /// use aya::{BpfLoader, programs::{Xdp, XdpFlags, Extension}}; /// /// let mut bpf = BpfLoader::new().extension("extension").load_file("app.o")?; -/// let prog: &mut Xdp = bpf.program_mut("main").unwrap().try_into()?; +/// let mut prog: aya::WithBtfFd = bpf.program_mut("main").unwrap().try_into()?; /// prog.load()?; /// prog.attach("eth0", XdpFlags::default())?; /// /// let prog_fd = prog.fd().unwrap(); -/// let ext: &mut Extension = bpf.program_mut("extension").unwrap().try_into()?; +/// let mut ext: aya::WithBtfFd = bpf.program_mut("extension").unwrap().try_into()?; /// ext.load(prog_fd, "function_to_replace")?; /// ext.attach()?; /// Ok::<(), aya::BpfError>(()) @@ -53,6 +53,13 @@ pub struct Extension { pub(crate) data: ProgramData, } +impl<'p> WithBtfFd<'p, Extension> { + /// Loads the program inside the kernel. + pub fn load(&mut self, program: ProgramFd, func_name: &str) -> Result<(), ProgramError> { + self.program.load(program, func_name, self.btf_fd) + } +} + impl Extension { /// Loads the extension inside the kernel. /// @@ -68,14 +75,19 @@ impl Extension { /// The extension code will be loaded but inactive until it's attached. /// There are no restrictions on what functions may be replaced, so you could replace /// the main entry point of your program with an extension. - pub fn load(&mut self, program: ProgramFd, func_name: &str) -> Result<(), ProgramError> { + pub fn load( + &mut self, + program: ProgramFd, + func_name: &str, + btf_fd: Option, + ) -> Result<(), ProgramError> { let target_prog_fd = program.as_raw_fd(); - let (btf_fd, btf_id) = get_btf_info(target_prog_fd, func_name)?; + let (prog_btf_fd, prog_btf_id) = get_btf_info(target_prog_fd, func_name)?; - self.data.attach_btf_obj_fd = Some(btf_fd as u32); + self.data.attach_btf_obj_fd = Some(prog_btf_fd as u32); self.data.attach_prog_fd = Some(target_prog_fd); - self.data.attach_btf_id = Some(btf_id); - load_program(BPF_PROG_TYPE_EXT, &mut self.data) + self.data.attach_btf_id = Some(prog_btf_id); + load_program(BPF_PROG_TYPE_EXT, &mut self.data, btf_fd) } /// Attaches the extension. diff --git a/aya/src/programs/fentry.rs b/aya/src/programs/fentry.rs index 8f59061a..adaa130f 100644 --- a/aya/src/programs/fentry.rs +++ b/aya/src/programs/fentry.rs @@ -1,5 +1,7 @@ //! Fentry programs. +use std::os::fd::AsFd; + use crate::{ generated::{bpf_attach_type::BPF_TRACE_FENTRY, bpf_prog_type::BPF_PROG_TYPE_TRACING}, obj::btf::{Btf, BtfKind}, @@ -7,6 +9,7 @@ use crate::{ define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId, ProgramData, ProgramError, }, + WithBtfFd, }; /// A program that can be attached to the entry point of (almost) any kernel @@ -37,7 +40,7 @@ use crate::{ /// use aya::{Bpf, programs::FEntry, BtfError, Btf}; /// /// let btf = Btf::from_sys_fs()?; -/// let program: &mut FEntry = bpf.program_mut("filename_lookup").unwrap().try_into()?; +/// let mut program: aya::WithBtfFd = bpf.program_mut("filename_lookup").unwrap().try_into()?; /// program.load("filename_lookup", &btf)?; /// program.attach()?; /// # Ok::<(), Error>(()) @@ -49,16 +52,28 @@ pub struct FEntry { pub(crate) data: ProgramData, } +impl<'p> WithBtfFd<'p, FEntry> { + /// Loads the program inside the kernel. + pub fn load(&mut self, fn_name: &str, btf: &Btf) -> Result<(), ProgramError> { + self.program.load(fn_name, btf, self.btf_fd) + } +} + impl FEntry { /// Loads the program inside the kernel. /// /// Loads the program so it's executed when the kernel function `fn_name` /// is entered. The `btf` argument must contain the BTF info for the /// running kernel. - pub fn load(&mut self, fn_name: &str, btf: &Btf) -> Result<(), ProgramError> { + pub fn load( + &mut self, + fn_name: &str, + btf: &Btf, + btf_fd: Option, + ) -> Result<(), ProgramError> { self.data.expected_attach_type = Some(BPF_TRACE_FENTRY); self.data.attach_btf_id = Some(btf.id_by_type_name_kind(fn_name, BtfKind::Func)?); - load_program(BPF_PROG_TYPE_TRACING, &mut self.data) + load_program(BPF_PROG_TYPE_TRACING, &mut self.data, btf_fd) } /// Attaches the program. diff --git a/aya/src/programs/fexit.rs b/aya/src/programs/fexit.rs index ba2e1f1b..50213a5a 100644 --- a/aya/src/programs/fexit.rs +++ b/aya/src/programs/fexit.rs @@ -1,5 +1,7 @@ //! Fexit programs. +use std::os::fd::AsFd; + use crate::{ generated::{bpf_attach_type::BPF_TRACE_FEXIT, bpf_prog_type::BPF_PROG_TYPE_TRACING}, obj::btf::{Btf, BtfKind}, @@ -7,6 +9,7 @@ use crate::{ define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId, ProgramData, ProgramError, }, + WithBtfFd, }; /// A program that can be attached to the exit point of (almost) anny kernel @@ -37,7 +40,7 @@ use crate::{ /// use aya::{Bpf, programs::FExit, BtfError, Btf}; /// /// let btf = Btf::from_sys_fs()?; -/// let program: &mut FExit = bpf.program_mut("filename_lookup").unwrap().try_into()?; +/// let mut program: aya::WithBtfFd = bpf.program_mut("filename_lookup").unwrap().try_into()?; /// program.load("filename_lookup", &btf)?; /// program.attach()?; /// # Ok::<(), Error>(()) @@ -49,16 +52,28 @@ pub struct FExit { pub(crate) data: ProgramData, } +impl<'p> WithBtfFd<'p, FExit> { + /// Loads the program inside the kernel. + pub fn load(&mut self, fn_name: &str, btf: &Btf) -> Result<(), ProgramError> { + self.program.load(fn_name, btf, self.btf_fd) + } +} + impl FExit { /// Loads the program inside the kernel. /// /// Loads the program so it's executed when the kernel function `fn_name` /// is exited. The `btf` argument must contain the BTF info for the running /// kernel. - pub fn load(&mut self, fn_name: &str, btf: &Btf) -> Result<(), ProgramError> { + pub fn load( + &mut self, + fn_name: &str, + btf: &Btf, + btf_fd: Option, + ) -> Result<(), ProgramError> { self.data.expected_attach_type = Some(BPF_TRACE_FEXIT); self.data.attach_btf_id = Some(btf.id_by_type_name_kind(fn_name, BtfKind::Func)?); - load_program(BPF_PROG_TYPE_TRACING, &mut self.data) + load_program(BPF_PROG_TYPE_TRACING, &mut self.data, btf_fd) } /// Attaches the program. diff --git a/aya/src/programs/kprobe.rs b/aya/src/programs/kprobe.rs index a61f084f..0509238b 100644 --- a/aya/src/programs/kprobe.rs +++ b/aya/src/programs/kprobe.rs @@ -1,5 +1,5 @@ //! Kernel space probes. -use std::{io, path::Path}; +use std::{io, os::fd::AsFd, path::Path}; use thiserror::Error; use crate::{ @@ -11,7 +11,7 @@ use crate::{ FdLink, LinkError, ProgramData, ProgramError, }, sys::bpf_link_get_info_by_fd, - VerifierLogLevel, + VerifierLogLevel, WithBtfFd, }; /// A kernel probe. @@ -32,7 +32,7 @@ use crate::{ /// # let mut bpf = Bpf::load_file("ebpf_programs.o")?; /// use aya::{Bpf, programs::KProbe}; /// -/// let program: &mut KProbe = bpf.program_mut("intercept_wakeups").unwrap().try_into()?; +/// let mut program: aya::WithBtfFd = bpf.program_mut("intercept_wakeups").unwrap().try_into()?; /// program.load()?; /// program.attach("try_to_wake_up", 0)?; /// # Ok::<(), aya::BpfError>(()) @@ -44,10 +44,17 @@ pub struct KProbe { pub(crate) kind: ProbeKind, } -impl KProbe { +impl<'p> WithBtfFd<'p, KProbe> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_KPROBE, &mut self.data) + self.program.load(self.btf_fd) + } +} + +impl KProbe { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { + load_program(BPF_PROG_TYPE_KPROBE, &mut self.data, btf_fd) } /// Returns `KProbe` if the program is a `kprobe`, or `KRetProbe` if the diff --git a/aya/src/programs/links.rs b/aya/src/programs/links.rs index debe7b49..4052449d 100644 --- a/aya/src/programs/links.rs +++ b/aya/src/programs/links.rs @@ -97,7 +97,7 @@ pub struct FdLinkId(pub(crate) RawFd); /// # let mut bpf = Bpf::load_file("ebpf_programs.o")?; /// use aya::{Bpf, programs::{links::FdLink, KProbe}}; /// -/// let program: &mut KProbe = bpf.program_mut("intercept_wakeups").unwrap().try_into()?; +/// let mut program: aya::WithBtfFd = bpf.program_mut("intercept_wakeups").unwrap().try_into()?; /// program.load()?; /// let link_id = program.attach("try_to_wake_up", 0)?; /// let link = program.take_link(link_id).unwrap(); @@ -138,7 +138,7 @@ impl FdLink { /// # Program(#[from] aya::programs::ProgramError) /// # } /// # let mut bpf = aya::Bpf::load(&[])?; - /// # let prog: &mut Extension = bpf.program_mut("example").unwrap().try_into()?; + /// # let mut prog: aya::WithBtfFd = bpf.program_mut("example").unwrap().try_into()?; /// let link_id = prog.attach()?; /// let owned_link = prog.take_link(link_id)?; /// let fd_link: FdLink = owned_link.into(); diff --git a/aya/src/programs/lirc_mode2.rs b/aya/src/programs/lirc_mode2.rs index ce40eaaa..2361955d 100644 --- a/aya/src/programs/lirc_mode2.rs +++ b/aya/src/programs/lirc_mode2.rs @@ -1,10 +1,11 @@ //! Lirc programs. -use std::os::fd::{AsRawFd, IntoRawFd as _, RawFd}; +use std::os::fd::{AsFd, AsRawFd, IntoRawFd as _, RawFd}; use crate::{ generated::{bpf_attach_type::BPF_LIRC_MODE2, bpf_prog_type::BPF_PROG_TYPE_LIRC_MODE2}, programs::{load_program, query, Link, ProgramData, ProgramError, ProgramInfo}, sys::{bpf_prog_attach, bpf_prog_detach, bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd}, + WithBtfFd, }; use libc::{close, dup}; @@ -40,7 +41,7 @@ use libc::{close, dup}; /// /// let file = File::open("/dev/lirc0")?; /// let mut bpf = aya::Bpf::load_file("imon_rsc.o")?; -/// let decoder: &mut LircMode2 = bpf.program_mut("imon_rsc").unwrap().try_into().unwrap(); +/// let mut decoder: aya::WithBtfFd = bpf.program_mut("imon_rsc").unwrap().try_into().unwrap(); /// decoder.load()?; /// decoder.attach(file)?; /// # Ok::<(), Error>(()) @@ -51,10 +52,17 @@ pub struct LircMode2 { pub(crate) data: ProgramData, } -impl LircMode2 { +impl<'p> WithBtfFd<'p, LircMode2> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_LIRC_MODE2, &mut self.data) + self.program.load(self.btf_fd) + } +} + +impl LircMode2 { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { + load_program(BPF_PROG_TYPE_LIRC_MODE2, &mut self.data, btf_fd) } /// Attaches the program to the given lirc device. diff --git a/aya/src/programs/lsm.rs b/aya/src/programs/lsm.rs index 3a455707..d1c409ab 100644 --- a/aya/src/programs/lsm.rs +++ b/aya/src/programs/lsm.rs @@ -1,5 +1,7 @@ //! LSM probes. +use std::os::fd::AsFd; + use crate::{ generated::{bpf_attach_type::BPF_LSM_MAC, bpf_prog_type::BPF_PROG_TYPE_LSM}, obj::btf::{Btf, BtfKind}, @@ -7,6 +9,7 @@ use crate::{ define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId, ProgramData, ProgramError, }, + WithBtfFd, }; /// A program that attaches to Linux LSM hooks. Used to implement security policy and @@ -39,7 +42,7 @@ use crate::{ /// use aya::{Bpf, programs::Lsm, BtfError, Btf}; /// /// let btf = Btf::from_sys_fs()?; -/// let program: &mut Lsm = bpf.program_mut("lsm_prog").unwrap().try_into()?; +/// let mut program: aya::WithBtfFd = bpf.program_mut("lsm_prog").unwrap().try_into()?; /// program.load("security_bprm_exec", &btf)?; /// program.attach()?; /// # Ok::<(), LsmError>(()) @@ -52,6 +55,13 @@ pub struct Lsm { pub(crate) data: ProgramData, } +impl<'p> WithBtfFd<'p, Lsm> { + /// Loads the program inside the kernel. + pub fn load(&mut self, lsm_hook_name: &str, btf: &Btf) -> Result<(), ProgramError> { + self.program.load(lsm_hook_name, btf, self.btf_fd) + } +} + impl Lsm { /// Loads the program inside the kernel. /// @@ -59,12 +69,17 @@ impl Lsm { /// /// * `lsm_hook_name` - full name of the LSM hook that the program should /// be attached to - pub fn load(&mut self, lsm_hook_name: &str, btf: &Btf) -> Result<(), ProgramError> { + pub fn load( + &mut self, + lsm_hook_name: &str, + btf: &Btf, + btf_fd: Option, + ) -> Result<(), ProgramError> { self.data.expected_attach_type = Some(BPF_LSM_MAC); let type_name = format!("bpf_lsm_{lsm_hook_name}"); self.data.attach_btf_id = Some(btf.id_by_type_name_kind(type_name.as_str(), BtfKind::Func)?); - load_program(BPF_PROG_TYPE_LSM, &mut self.data) + load_program(BPF_PROG_TYPE_LSM, &mut self.data, btf_fd) } /// Attaches the program. diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index f868dfc8..46bbf7d7 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -18,7 +18,7 @@ //! //! let mut bpf = Bpf::load_file("ebpf_programs.o")?; //! // intercept_wakeups is the name of the program we want to load -//! let program: &mut KProbe = bpf.program_mut("intercept_wakeups").unwrap().try_into()?; +//! let mut program: aya::WithBtfFd = bpf.program_mut("intercept_wakeups").unwrap().try_into()?; //! program.load()?; //! // intercept_wakeups will be called every time try_to_wake_up() is called //! // inside the kernel @@ -69,7 +69,7 @@ use libc::ENOSPC; use std::{ ffi::CString, io, - os::fd::{AsRawFd, IntoRawFd as _, RawFd}, + os::fd::{AsFd, AsRawFd, IntoRawFd as _, RawFd}, path::{Path, PathBuf}, }; use thiserror::Error; @@ -413,7 +413,6 @@ pub(crate) struct ProgramData { pub(crate) attach_btf_obj_fd: Option, pub(crate) attach_btf_id: Option, pub(crate) attach_prog_fd: Option, - pub(crate) btf_fd: Option, pub(crate) verifier_log_level: VerifierLogLevel, pub(crate) path: Option, pub(crate) flags: u32, @@ -423,7 +422,6 @@ impl ProgramData { pub(crate) fn new( name: Option, obj: (obj::Program, obj::Function), - btf_fd: Option, verifier_log_level: VerifierLogLevel, ) -> ProgramData { ProgramData { @@ -435,7 +433,6 @@ impl ProgramData { attach_btf_obj_fd: None, attach_btf_id: None, attach_prog_fd: None, - btf_fd, verifier_log_level, path: None, flags: 0, @@ -475,7 +472,6 @@ impl ProgramData { attach_btf_obj_fd, attach_btf_id, attach_prog_fd: None, - btf_fd: None, verifier_log_level, path: Some(path.to_path_buf()), flags: 0, @@ -546,6 +542,7 @@ fn pin_program>(data: &ProgramData, path: P) -> Resul fn load_program( prog_type: bpf_prog_type, data: &mut ProgramData, + btf_fd: Option, ) -> Result<(), ProgramError> { let ProgramData { name, @@ -556,7 +553,6 @@ fn load_program( attach_btf_obj_fd, attach_btf_id, attach_prog_fd, - btf_fd, verifier_log_level, path: _, flags, @@ -613,7 +609,7 @@ fn load_program( license, kernel_version: target_kernel_version, expected_attach_type: *expected_attach_type, - prog_btf_fd: *btf_fd, + prog_btf_fd: btf_fd.as_ref().map(|f| f.as_fd()), attach_btf_obj_fd: *attach_btf_obj_fd, attach_btf_id: *attach_btf_id, attach_prog_fd: *attach_prog_fd, @@ -885,6 +881,17 @@ macro_rules! impl_try_from_program { } } } + + impl<'a> TryFrom<$crate::WithBtfFd<'a, Program>> for $crate::bpf::WithBtfFd<'a, $ty> { + type Error = ProgramError; + + fn try_from(program: $crate::WithBtfFd<'a, Program>) -> Result<$crate::WithBtfFd<'a, $ty>, ProgramError> { + Ok($crate::bpf::WithBtfFd { + program: program.program.try_into()?, + btf_fd: program.btf_fd + }) + } + } )+ } } diff --git a/aya/src/programs/perf_event.rs b/aya/src/programs/perf_event.rs index 5de7eeef..9e0fb12b 100644 --- a/aya/src/programs/perf_event.rs +++ b/aya/src/programs/perf_event.rs @@ -1,5 +1,7 @@ //! Perf event programs. +use std::os::fd::AsFd; + pub use crate::generated::{ perf_hw_cache_id, perf_hw_cache_op_id, perf_hw_cache_op_result_id, perf_hw_id, perf_sw_ids, }; @@ -20,6 +22,7 @@ use crate::{ FdLink, LinkError, ProgramData, ProgramError, }, sys::{bpf_link_get_info_by_fd, perf_event_open}, + WithBtfFd, }; /// The type of perf event @@ -105,7 +108,7 @@ pub enum PerfEventScope { /// perf_sw_ids::PERF_COUNT_SW_CPU_CLOCK, PerfEvent, PerfEventScope, PerfTypeId, SamplePolicy, /// }; /// -/// let prog: &mut PerfEvent = bpf.program_mut("observe_cpu_clock").unwrap().try_into()?; +/// let mut prog: aya::WithBtfFd = bpf.program_mut("observe_cpu_clock").unwrap().try_into()?; /// prog.load()?; /// /// for cpu in online_cpus()? { @@ -124,10 +127,17 @@ pub struct PerfEvent { pub(crate) data: ProgramData, } -impl PerfEvent { +impl<'p> WithBtfFd<'p, PerfEvent> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_PERF_EVENT, &mut self.data) + self.program.load(self.btf_fd) + } +} + +impl PerfEvent { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { + load_program(BPF_PROG_TYPE_PERF_EVENT, &mut self.data, btf_fd) } /// Attaches to the given perf event. diff --git a/aya/src/programs/raw_trace_point.rs b/aya/src/programs/raw_trace_point.rs index af451e59..f1c3654c 100644 --- a/aya/src/programs/raw_trace_point.rs +++ b/aya/src/programs/raw_trace_point.rs @@ -1,5 +1,5 @@ //! Raw tracepoints. -use std::ffi::CString; +use std::{ffi::CString, os::fd::AsFd}; use crate::{ generated::bpf_prog_type::BPF_PROG_TYPE_RAW_TRACEPOINT, @@ -7,6 +7,7 @@ use crate::{ define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId, ProgramData, ProgramError, }, + WithBtfFd, }; /// A program that can be attached at a pre-defined kernel trace point, but also @@ -27,7 +28,7 @@ use crate::{ /// # let mut bpf = Bpf::load_file("ebpf_programs.o")?; /// use aya::{Bpf, programs::RawTracePoint}; /// -/// let program: &mut RawTracePoint = bpf.program_mut("sys_enter").unwrap().try_into()?; +/// let mut program: aya::WithBtfFd = bpf.program_mut("sys_enter").unwrap().try_into()?; /// program.load()?; /// program.attach("sys_enter")?; /// # Ok::<(), aya::BpfError>(()) @@ -38,10 +39,17 @@ pub struct RawTracePoint { pub(crate) data: ProgramData, } -impl RawTracePoint { +impl<'p> WithBtfFd<'p, RawTracePoint> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_RAW_TRACEPOINT, &mut self.data) + self.program.load(self.btf_fd) + } +} + +impl RawTracePoint { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { + load_program(BPF_PROG_TYPE_RAW_TRACEPOINT, &mut self.data, btf_fd) } /// Attaches the program to the given tracepoint. diff --git a/aya/src/programs/sk_lookup.rs b/aya/src/programs/sk_lookup.rs index 27d60b8f..837b9c17 100644 --- a/aya/src/programs/sk_lookup.rs +++ b/aya/src/programs/sk_lookup.rs @@ -1,9 +1,10 @@ -use std::os::fd::{AsRawFd, RawFd}; +use std::os::fd::{AsFd, AsRawFd, RawFd}; use crate::{ generated::{bpf_attach_type::BPF_SK_LOOKUP, bpf_prog_type::BPF_PROG_TYPE_SK_LOOKUP}, programs::{define_link_wrapper, load_program, FdLinkId, ProgramData, ProgramError}, sys::bpf_link_create, + WithBtfFd, }; use super::links::FdLink; @@ -39,7 +40,7 @@ use super::links::FdLink; /// use aya::programs::SkLookup; /// /// let file = File::open("/var/run/netns/test")?; -/// let program: &mut SkLookup = bpf.program_mut("sk_lookup").unwrap().try_into()?; +/// let mut program: aya::WithBtfFd = bpf.program_mut("sk_lookup").unwrap().try_into()?; /// program.load()?; /// program.attach(file)?; /// # Ok::<(), Error>(()) @@ -50,11 +51,18 @@ pub struct SkLookup { pub(crate) data: ProgramData, } -impl SkLookup { +impl<'p> WithBtfFd<'p, SkLookup> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { + self.program.load(self.btf_fd) + } +} + +impl SkLookup { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { self.data.expected_attach_type = Some(BPF_SK_LOOKUP); - load_program(BPF_PROG_TYPE_SK_LOOKUP, &mut self.data) + load_program(BPF_PROG_TYPE_SK_LOOKUP, &mut self.data, btf_fd) } /// Attaches the program to the given network namespace. diff --git a/aya/src/programs/sk_msg.rs b/aya/src/programs/sk_msg.rs index fc6202ba..c5fdaac4 100644 --- a/aya/src/programs/sk_msg.rs +++ b/aya/src/programs/sk_msg.rs @@ -1,6 +1,6 @@ //! Skmsg programs. -use std::os::fd::AsRawFd; +use std::os::fd::{AsFd, AsRawFd}; use crate::{ generated::{bpf_attach_type::BPF_SK_MSG_VERDICT, bpf_prog_type::BPF_PROG_TYPE_SK_MSG}, @@ -10,6 +10,7 @@ use crate::{ ProgramError, }, sys::bpf_prog_attach, + WithBtfFd, }; /// A program used to intercept messages sent with `sendmsg()`/`sendfile()`. @@ -46,7 +47,7 @@ use crate::{ /// let intercept_egress: SockHash<_, u32> = bpf.map("INTERCEPT_EGRESS").unwrap().try_into()?; /// let map_fd = intercept_egress.fd()?; /// -/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; +/// let mut prog: aya::WithBtfFd = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; /// prog.load()?; /// prog.attach(map_fd)?; /// @@ -69,10 +70,17 @@ pub struct SkMsg { pub(crate) data: ProgramData, } -impl SkMsg { +impl<'p> WithBtfFd<'p, SkMsg> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_SK_MSG, &mut self.data) + self.program.load(self.btf_fd) + } +} + +impl SkMsg { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { + load_program(BPF_PROG_TYPE_SK_MSG, &mut self.data, btf_fd) } /// Attaches the program to the given sockmap. diff --git a/aya/src/programs/sk_skb.rs b/aya/src/programs/sk_skb.rs index 162d74d0..f23707cc 100644 --- a/aya/src/programs/sk_skb.rs +++ b/aya/src/programs/sk_skb.rs @@ -1,6 +1,9 @@ //! Skskb programs. -use std::{os::fd::AsRawFd, path::Path}; +use std::{ + os::fd::{AsFd, AsRawFd}, + path::Path, +}; use crate::{ generated::{ @@ -13,7 +16,7 @@ use crate::{ ProgramError, }, sys::bpf_prog_attach, - VerifierLogLevel, + VerifierLogLevel, WithBtfFd, }; /// The kind of [`SkSkb`] program. @@ -45,7 +48,7 @@ pub enum SkSkbKind { /// let intercept_ingress: SockMap<_> = bpf.map("INTERCEPT_INGRESS").unwrap().try_into()?; /// let map_fd = intercept_ingress.fd()?; /// -/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?; +/// let mut prog: aya::WithBtfFd = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?; /// prog.load()?; /// prog.attach(map_fd)?; /// @@ -62,10 +65,17 @@ pub struct SkSkb { pub(crate) kind: SkSkbKind, } -impl SkSkb { +impl<'p> WithBtfFd<'p, SkSkb> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_SK_SKB, &mut self.data) + self.program.load(self.btf_fd) + } +} + +impl SkSkb { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { + load_program(BPF_PROG_TYPE_SK_SKB, &mut self.data, btf_fd) } /// Attaches the program to the given socket map. diff --git a/aya/src/programs/sock_ops.rs b/aya/src/programs/sock_ops.rs index fe8dccc0..847c68f1 100644 --- a/aya/src/programs/sock_ops.rs +++ b/aya/src/programs/sock_ops.rs @@ -1,5 +1,5 @@ //! Socket option programs. -use std::os::fd::AsRawFd; +use std::os::fd::{AsFd, AsRawFd}; use crate::{ generated::{bpf_attach_type::BPF_CGROUP_SOCK_OPS, bpf_prog_type::BPF_PROG_TYPE_SOCK_OPS}, @@ -8,6 +8,7 @@ use crate::{ ProgramError, }, sys::bpf_prog_attach, + WithBtfFd, }; /// A program used to work with sockets. @@ -39,7 +40,7 @@ use crate::{ /// use aya::programs::SockOps; /// /// let file = File::open("/sys/fs/cgroup/unified")?; -/// let prog: &mut SockOps = bpf.program_mut("intercept_active_sockets").unwrap().try_into()?; +/// let mut prog: aya::WithBtfFd = bpf.program_mut("intercept_active_sockets").unwrap().try_into()?; /// prog.load()?; /// prog.attach(file)?; /// # Ok::<(), Error>(()) @@ -49,10 +50,17 @@ pub struct SockOps { pub(crate) data: ProgramData, } -impl SockOps { +impl<'p> WithBtfFd<'p, SockOps> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_SOCK_OPS, &mut self.data) + self.program.load(self.btf_fd) + } +} + +impl SockOps { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { + load_program(BPF_PROG_TYPE_SOCK_OPS, &mut self.data, btf_fd) } /// Attaches the program to the given cgroup. diff --git a/aya/src/programs/socket_filter.rs b/aya/src/programs/socket_filter.rs index 5ff9a301..41daa799 100644 --- a/aya/src/programs/socket_filter.rs +++ b/aya/src/programs/socket_filter.rs @@ -2,13 +2,14 @@ use libc::{setsockopt, SOL_SOCKET}; use std::{ io, mem, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, RawFd}, }; use thiserror::Error; use crate::{ generated::{bpf_prog_type::BPF_PROG_TYPE_SOCKET_FILTER, SO_ATTACH_BPF, SO_DETACH_BPF}, programs::{load_program, Link, ProgramData, ProgramError}, + WithBtfFd, }; /// The type returned when attaching a [`SocketFilter`] fails. @@ -52,7 +53,7 @@ pub enum SocketFilterError { /// use aya::programs::SocketFilter; /// /// let mut client = TcpStream::connect("127.0.0.1:1234")?; -/// let prog: &mut SocketFilter = bpf.program_mut("filter_packets").unwrap().try_into()?; +/// let mut prog: aya::WithBtfFd = bpf.program_mut("filter_packets").unwrap().try_into()?; /// prog.load()?; /// prog.attach(client.as_raw_fd())?; /// # Ok::<(), Error>(()) @@ -63,10 +64,17 @@ pub struct SocketFilter { pub(crate) data: ProgramData, } -impl SocketFilter { +impl<'p> WithBtfFd<'p, SocketFilter> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_SOCKET_FILTER, &mut self.data) + self.program.load(self.btf_fd) + } +} + +impl SocketFilter { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { + load_program(BPF_PROG_TYPE_SOCKET_FILTER, &mut self.data, btf_fd) } /// Attaches the filter on the given socket. diff --git a/aya/src/programs/tc.rs b/aya/src/programs/tc.rs index fad633a3..63b7e49f 100644 --- a/aya/src/programs/tc.rs +++ b/aya/src/programs/tc.rs @@ -4,6 +4,7 @@ use thiserror::Error; use std::{ ffi::{CStr, CString}, io, + os::fd::AsFd, path::Path, }; @@ -17,7 +18,7 @@ use crate::{ netlink_qdisc_detach, }, util::{ifindex_from_ifname, tc_handler_make}, - VerifierLogLevel, + VerifierLogLevel, WithBtfFd, }; /// Traffic control attach type. @@ -63,7 +64,7 @@ pub enum TcAttachType { /// // attached /// tc::qdisc_add_clsact("eth0")?; /// -/// let prog: &mut SchedClassifier = bpf.program_mut("redirect_ingress").unwrap().try_into()?; +/// let mut prog: aya::WithBtfFd = bpf.program_mut("redirect_ingress").unwrap().try_into()?; /// prog.load()?; /// prog.attach("eth0", TcAttachType::Ingress)?; /// @@ -112,10 +113,17 @@ pub struct TcOptions { pub handle: u32, } -impl SchedClassifier { +impl<'p> WithBtfFd<'p, SchedClassifier> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_SCHED_CLS, &mut self.data) + self.program.load(self.btf_fd) + } +} + +impl SchedClassifier { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { + load_program(BPF_PROG_TYPE_SCHED_CLS, &mut self.data, btf_fd) } /// Attaches the program to the given `interface` using the default options. diff --git a/aya/src/programs/tp_btf.rs b/aya/src/programs/tp_btf.rs index eb419ab1..92025b88 100644 --- a/aya/src/programs/tp_btf.rs +++ b/aya/src/programs/tp_btf.rs @@ -1,5 +1,7 @@ //! BTF-enabled raw tracepoints. +use std::os::fd::AsFd; + use crate::{ generated::{bpf_attach_type::BPF_TRACE_RAW_TP, bpf_prog_type::BPF_PROG_TYPE_TRACING}, obj::btf::{Btf, BtfKind}, @@ -7,6 +9,7 @@ use crate::{ define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId, ProgramData, ProgramError, }, + WithBtfFd, }; /// Marks a function as a [BTF-enabled raw tracepoint][1] eBPF program that can be attached at @@ -36,7 +39,7 @@ use crate::{ /// use aya::{Bpf, programs::BtfTracePoint, BtfError, Btf}; /// /// let btf = Btf::from_sys_fs()?; -/// let program: &mut BtfTracePoint = bpf.program_mut("sched_process_fork").unwrap().try_into()?; +/// let mut program: aya::WithBtfFd = bpf.program_mut("sched_process_fork").unwrap().try_into()?; /// program.load("sched_process_fork", &btf)?; /// program.attach()?; /// # Ok::<(), Error>(()) @@ -50,6 +53,13 @@ pub struct BtfTracePoint { pub(crate) data: ProgramData, } +impl<'p> WithBtfFd<'p, BtfTracePoint> { + /// Loads the program inside the kernel. + pub fn load(&mut self, tracepoint: &str, btf: &Btf) -> Result<(), ProgramError> { + self.program.load(tracepoint, btf, self.btf_fd) + } +} + impl BtfTracePoint { /// Loads the program inside the kernel. /// @@ -57,12 +67,17 @@ impl BtfTracePoint { /// /// * `tracepoint` - full name of the tracepoint that we should attach to /// * `btf` - btf information for the target system - pub fn load(&mut self, tracepoint: &str, btf: &Btf) -> Result<(), ProgramError> { + pub fn load( + &mut self, + tracepoint: &str, + btf: &Btf, + btf_fd: Option, + ) -> Result<(), ProgramError> { self.data.expected_attach_type = Some(BPF_TRACE_RAW_TP); let type_name = format!("btf_trace_{tracepoint}"); self.data.attach_btf_id = Some(btf.id_by_type_name_kind(type_name.as_str(), BtfKind::Typedef)?); - load_program(BPF_PROG_TYPE_TRACING, &mut self.data) + load_program(BPF_PROG_TYPE_TRACING, &mut self.data, btf_fd) } /// Attaches the program. diff --git a/aya/src/programs/trace_point.rs b/aya/src/programs/trace_point.rs index b23594b7..82462103 100644 --- a/aya/src/programs/trace_point.rs +++ b/aya/src/programs/trace_point.rs @@ -1,5 +1,5 @@ //! Tracepoint programs. -use std::{fs, io, path::Path}; +use std::{fs, io, os::fd::AsFd, path::Path}; use thiserror::Error; use crate::{ @@ -11,6 +11,7 @@ use crate::{ FdLink, LinkError, ProgramData, ProgramError, }, sys::{bpf_link_get_info_by_fd, perf_event_open_trace_point}, + WithBtfFd, }; /// The type returned when attaching a [`TracePoint`] fails. @@ -54,7 +55,7 @@ pub enum TracePointError { /// # let mut bpf = aya::Bpf::load(&[])?; /// use aya::programs::TracePoint; /// -/// let prog: &mut TracePoint = bpf.program_mut("trace_context_switch").unwrap().try_into()?; +/// let mut prog: aya::WithBtfFd = bpf.program_mut("trace_context_switch").unwrap().try_into()?; /// prog.load()?; /// prog.attach("sched", "sched_switch")?; /// # Ok::<(), Error>(()) @@ -65,10 +66,17 @@ pub struct TracePoint { pub(crate) data: ProgramData, } -impl TracePoint { +impl<'p> WithBtfFd<'p, TracePoint> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_TRACEPOINT, &mut self.data) + self.program.load(self.btf_fd) + } +} + +impl TracePoint { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { + load_program(BPF_PROG_TYPE_TRACEPOINT, &mut self.data, btf_fd) } /// Attaches to a given trace point. diff --git a/aya/src/programs/uprobe.rs b/aya/src/programs/uprobe.rs index bab82d4b..5f8e558c 100644 --- a/aya/src/programs/uprobe.rs +++ b/aya/src/programs/uprobe.rs @@ -7,7 +7,7 @@ use std::{ fs, io::{self, BufRead, Cursor, Read}, mem, - os::raw::c_char, + os::{fd::AsFd, raw::c_char}, path::{Path, PathBuf}, sync::Arc, }; @@ -22,7 +22,7 @@ use crate::{ FdLink, LinkError, ProgramData, ProgramError, }, sys::bpf_link_get_info_by_fd, - VerifierLogLevel, + VerifierLogLevel, WithBtfFd, }; const LD_SO_CACHE_FILE: &str = "/etc/ld.so.cache"; @@ -48,10 +48,17 @@ pub struct UProbe { pub(crate) kind: ProbeKind, } -impl UProbe { +impl<'p> WithBtfFd<'p, UProbe> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_KPROBE, &mut self.data) + self.program.load(self.btf_fd) + } +} + +impl UProbe { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { + load_program(BPF_PROG_TYPE_KPROBE, &mut self.data, btf_fd) } /// Returns `UProbe` if the program is a `uprobe`, or `URetProbe` if the diff --git a/aya/src/programs/xdp.rs b/aya/src/programs/xdp.rs index 9372b281..993c4ae0 100644 --- a/aya/src/programs/xdp.rs +++ b/aya/src/programs/xdp.rs @@ -1,9 +1,15 @@ //! eXpress Data Path (XDP) programs. -use crate::util::KernelVersion; +use crate::{util::KernelVersion, WithBtfFd}; use bitflags; use libc::if_nametoindex; -use std::{convert::TryFrom, ffi::CString, hash::Hash, io, mem, os::fd::RawFd}; +use std::{ + convert::TryFrom, + ffi::CString, + hash::Hash, + io, mem, + os::fd::{AsFd, RawFd}, +}; use thiserror::Error; use crate::{ @@ -66,7 +72,7 @@ bitflags! { /// # let mut bpf = Bpf::load_file("ebpf_programs.o")?; /// use aya::{Bpf, programs::{Xdp, XdpFlags}}; /// -/// let program: &mut Xdp = bpf.program_mut("intercept_packets").unwrap().try_into()?; +/// let mut program: aya::WithBtfFd = bpf.program_mut("intercept_packets").unwrap().try_into()?; /// program.attach("eth0", XdpFlags::default())?; /// # Ok::<(), aya::BpfError>(()) /// ``` @@ -76,11 +82,18 @@ pub struct Xdp { pub(crate) data: ProgramData, } -impl Xdp { +impl<'f> WithBtfFd<'f, Xdp> { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { + self.program.load(self.btf_fd) + } +} + +impl Xdp { + /// Loads the program inside the kernel. + pub fn load(&mut self, btf_fd: Option) -> Result<(), ProgramError> { self.data.expected_attach_type = Some(bpf_attach_type::BPF_XDP); - load_program(BPF_PROG_TYPE_XDP, &mut self.data) + load_program(BPF_PROG_TYPE_XDP, &mut self.data, btf_fd) } /// Attaches the program to the given `interface`. diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index 5a26c57f..1b0c9a17 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -3,7 +3,7 @@ use std::{ ffi::{CStr, CString}, io, mem::{self, MaybeUninit}, - os::fd::{FromRawFd as _, OwnedFd, RawFd}, + os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd as _, OwnedFd, RawFd}, slice, }; @@ -35,7 +35,7 @@ use crate::{ pub(crate) fn bpf_create_map( name: &CStr, def: &obj::Map, - btf_fd: Option, + btf_fd: Option, kernel_version: KernelVersion, ) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; @@ -75,7 +75,7 @@ pub(crate) fn bpf_create_map( _ => { u.btf_key_type_id = m.def.btf_key_type_id; u.btf_value_type_id = m.def.btf_value_type_id; - u.btf_fd = btf_fd.unwrap_or_default() as u32; + u.btf_fd = btf_fd.map(|fd| fd.as_fd().as_raw_fd()).unwrap_or_default() as u32; } } } @@ -115,7 +115,7 @@ pub(crate) struct BpfLoadProgramAttrs<'a> { pub(crate) license: &'a CStr, pub(crate) kernel_version: u32, pub(crate) expected_attach_type: Option, - pub(crate) prog_btf_fd: Option, + pub(crate) prog_btf_fd: Option>, pub(crate) attach_btf_obj_fd: Option, pub(crate) attach_btf_id: Option, pub(crate) attach_prog_fd: Option, @@ -161,7 +161,7 @@ pub(crate) fn bpf_load_program( let func_info_buf = aya_attr.func_info.func_info_bytes(); if let Some(btf_fd) = aya_attr.prog_btf_fd { - u.prog_btf_fd = btf_fd as u32; + u.prog_btf_fd = btf_fd.as_raw_fd() as u32; if aya_attr.line_info_rec_size > 0 { u.line_info = line_info_buf.as_ptr() as *const _ as u64; u.line_info_cnt = aya_attr.line_info.len() as u32; @@ -561,7 +561,7 @@ pub(crate) fn bpf_load_btf( raw_btf: &[u8], log_buf: &mut [u8], verifier_log_level: VerifierLogLevel, -) -> SysResult { +) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_7 }; u.btf = raw_btf.as_ptr() as *const _ as u64; @@ -571,7 +571,9 @@ pub(crate) fn bpf_load_btf( u.btf_log_buf = log_buf.as_mut_ptr() as u64; u.btf_log_size = log_buf.len() as u32; } - sys_bpf(bpf_cmd::BPF_BTF_LOAD, &attr) + let raw_fd = sys_bpf(bpf_cmd::BPF_BTF_LOAD, &attr)? as RawFd; + // SAFETY: BPF_BTF_LOAD returns a newly created file descriptor + Ok(unsafe { OwnedFd::from_raw_fd(raw_fd) }) } pub(crate) fn bpf_btf_get_fd_by_id(id: u32) -> Result { @@ -711,10 +713,9 @@ pub(crate) fn is_bpf_global_data_supported() -> bool { }), fd: None, pinned: false, - btf_fd: None, }; - if let Ok(map_fd) = map_data.create("aya_global") { + if let Ok(map_fd) = map_data.create("aya_global", Option::::None) { insns[0].imm = map_fd; let gpl = b"GPL\0"; diff --git a/test/integration-test/src/tests/bpf_probe_read.rs b/test/integration-test/src/tests/bpf_probe_read.rs index 22c3e9b1..cd6a8d8f 100644 --- a/test/integration-test/src/tests/bpf_probe_read.rs +++ b/test/integration-test/src/tests/bpf_probe_read.rs @@ -1,4 +1,4 @@ -use aya::{maps::Array, programs::UProbe, Bpf}; +use aya::{maps::Array, programs::UProbe, Bpf, WithBtfFd}; const RESULT_BUF_LEN: usize = 1024; @@ -104,8 +104,7 @@ fn result_bytes(bpf: &Bpf) -> Vec { fn load_and_attach_uprobe(prog_name: &str, func_name: &str, bytes: &[u8]) -> Bpf { let mut bpf = Bpf::load(bytes).unwrap(); - - let prog: &mut UProbe = bpf.program_mut(prog_name).unwrap().try_into().unwrap(); + let mut prog: WithBtfFd = bpf.program_mut(prog_name).unwrap().try_into().unwrap(); prog.load().unwrap(); prog.attach(Some(func_name), 0, "/proc/self/exe", None) diff --git a/test/integration-test/src/tests/btf_relocations.rs b/test/integration-test/src/tests/btf_relocations.rs index 75f36223..2a286885 100644 --- a/test/integration-test/src/tests/btf_relocations.rs +++ b/test/integration-test/src/tests/btf_relocations.rs @@ -5,7 +5,9 @@ use std::{ time::Duration, }; -use aya::{maps::Array, programs::TracePoint, util::KernelVersion, BpfLoader, Btf, Endianness}; +use aya::{ + maps::Array, programs::TracePoint, util::KernelVersion, BpfLoader, Btf, Endianness, WithBtfFd, +}; // In the tests below we often use values like 0xAAAAAAAA or -0x7AAAAAAA. Those values have no // special meaning, they just have "nice" bit patterns that can be helpful while debugging. @@ -384,7 +386,7 @@ impl RelocationTestRunner { loader.btf(None); } let mut bpf = loader.load(&self.ebpf).context("Loading eBPF failed")?; - let program: &mut TracePoint = bpf + let mut program: WithBtfFd = bpf .program_mut("bpf_prog") .context("bpf_prog not found")? .try_into() diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 8958ae59..92ea99c6 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -7,7 +7,7 @@ use aya::{ loaded_programs, KProbe, TracePoint, UProbe, Xdp, XdpFlags, }, util::KernelVersion, - Bpf, + Bpf, WithBtfFd, }; const MAX_RETRIES: u32 = 100; @@ -16,7 +16,7 @@ const RETRY_DURATION_MS: u64 = 10; #[test] fn long_name() { let mut bpf = Bpf::load(crate::NAME_TEST).unwrap(); - let name_prog: &mut Xdp = bpf + let mut name_prog: WithBtfFd = bpf .program_mut("ihaveaverylongname") .unwrap() .try_into() @@ -36,7 +36,8 @@ fn multiple_btf_maps() { let map_1: Array<_, u64> = bpf.take_map("map_1").unwrap().try_into().unwrap(); let map_2: Array<_, u64> = bpf.take_map("map_2").unwrap().try_into().unwrap(); - let prog: &mut TracePoint = bpf.program_mut("tracepoint").unwrap().try_into().unwrap(); + let mut prog: WithBtfFd = + bpf.program_mut("tracepoint").unwrap().try_into().unwrap(); prog.load().unwrap(); prog.attach("sched", "sched_switch").unwrap(); @@ -110,7 +111,7 @@ macro_rules! assert_loaded { #[test] fn unload_xdp() { let mut bpf = Bpf::load(crate::TEST).unwrap(); - let prog: &mut Xdp = bpf.program_mut("test_xdp").unwrap().try_into().unwrap(); + let mut prog: WithBtfFd = bpf.program_mut("test_xdp").unwrap().try_into().unwrap(); prog.load().unwrap(); assert_loaded!("test_xdp", true); let link = prog.attach("lo", XdpFlags::default()).unwrap(); @@ -135,7 +136,7 @@ fn unload_xdp() { #[test] fn unload_kprobe() { let mut bpf = Bpf::load(crate::TEST).unwrap(); - let prog: &mut KProbe = bpf.program_mut("test_kprobe").unwrap().try_into().unwrap(); + let mut prog: WithBtfFd = bpf.program_mut("test_kprobe").unwrap().try_into().unwrap(); prog.load().unwrap(); assert_loaded!("test_kprobe", true); let link = prog.attach("try_to_wake_up", 0).unwrap(); @@ -160,7 +161,7 @@ fn unload_kprobe() { #[test] fn basic_tracepoint() { let mut bpf = Bpf::load(crate::TEST).unwrap(); - let prog: &mut TracePoint = bpf + let mut prog: WithBtfFd = bpf .program_mut("test_tracepoint") .unwrap() .try_into() @@ -191,7 +192,7 @@ fn basic_tracepoint() { #[test] fn basic_uprobe() { let mut bpf = Bpf::load(crate::TEST).unwrap(); - let prog: &mut UProbe = bpf.program_mut("test_uprobe").unwrap().try_into().unwrap(); + let mut prog: WithBtfFd = bpf.program_mut("test_uprobe").unwrap().try_into().unwrap(); prog.load().unwrap(); assert_loaded!("test_uprobe", true); @@ -224,7 +225,7 @@ fn pin_link() { } let mut bpf = Bpf::load(crate::TEST).unwrap(); - let prog: &mut Xdp = bpf.program_mut("test_xdp").unwrap().try_into().unwrap(); + let mut prog: WithBtfFd = bpf.program_mut("test_xdp").unwrap().try_into().unwrap(); prog.load().unwrap(); let link_id = prog.attach("lo", XdpFlags::default()).unwrap(); let link = prog.take_link(link_id).unwrap(); @@ -257,7 +258,7 @@ fn pin_lifecycle() { // 1. Load Program and Pin { let mut bpf = Bpf::load(crate::PASS).unwrap(); - let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); + let mut prog: WithBtfFd = bpf.program_mut("pass").unwrap().try_into().unwrap(); prog.load().unwrap(); prog.pin("/sys/fs/bpf/aya-xdp-test-prog").unwrap(); } @@ -291,7 +292,7 @@ fn pin_lifecycle() { // 4. Load a new version of the program, unpin link, and atomically replace old program { let mut bpf = Bpf::load(crate::PASS).unwrap(); - let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); + let mut prog: WithBtfFd = bpf.program_mut("pass").unwrap().try_into().unwrap(); prog.load().unwrap(); let link = PinnedLink::from_pin("/sys/fs/bpf/aya-xdp-test-lo") @@ -311,7 +312,7 @@ fn pin_lifecycle_tracepoint() { // 1. Load Program and Pin { let mut bpf = Bpf::load(crate::TEST).unwrap(); - let prog: &mut TracePoint = bpf + let mut prog: WithBtfFd = bpf .program_mut("test_tracepoint") .unwrap() .try_into() @@ -365,7 +366,8 @@ fn pin_lifecycle_kprobe() { // 1. Load Program and Pin { let mut bpf = Bpf::load(crate::TEST).unwrap(); - let prog: &mut KProbe = bpf.program_mut("test_kprobe").unwrap().try_into().unwrap(); + let mut prog: WithBtfFd = + bpf.program_mut("test_kprobe").unwrap().try_into().unwrap(); prog.load().unwrap(); prog.pin("/sys/fs/bpf/aya-kprobe-test-prog").unwrap(); } @@ -423,7 +425,8 @@ fn pin_lifecycle_uprobe() { // 1. Load Program and Pin { let mut bpf = Bpf::load(crate::TEST).unwrap(); - let prog: &mut UProbe = bpf.program_mut("test_uprobe").unwrap().try_into().unwrap(); + let mut prog: WithBtfFd = + bpf.program_mut("test_uprobe").unwrap().try_into().unwrap(); prog.load().unwrap(); prog.pin("/sys/fs/bpf/aya-uprobe-test-prog").unwrap(); } diff --git a/test/integration-test/src/tests/log.rs b/test/integration-test/src/tests/log.rs index 8645762b..f62e0bea 100644 --- a/test/integration-test/src/tests/log.rs +++ b/test/integration-test/src/tests/log.rs @@ -3,7 +3,7 @@ use std::{ sync::{Arc, Mutex}, }; -use aya::{programs::UProbe, Bpf}; +use aya::{programs::UProbe, Bpf, WithBtfFd}; use aya_log::BpfLogger; use log::{Level, Log, Record}; @@ -60,7 +60,7 @@ async fn log() { .unwrap(); } - let prog: &mut UProbe = bpf.program_mut("test_log").unwrap().try_into().unwrap(); + let mut prog: WithBtfFd = bpf.program_mut("test_log").unwrap().try_into().unwrap(); prog.load().unwrap(); prog.attach(Some("trigger_ebpf_program"), 0, "/proc/self/exe", None) .unwrap(); diff --git a/test/integration-test/src/tests/relocations.rs b/test/integration-test/src/tests/relocations.rs index 1b550e9f..d8636fac 100644 --- a/test/integration-test/src/tests/relocations.rs +++ b/test/integration-test/src/tests/relocations.rs @@ -1,6 +1,6 @@ use std::time::Duration; -use aya::{programs::UProbe, Bpf}; +use aya::{programs::UProbe, Bpf, WithBtfFd}; #[test] fn relocations() { @@ -32,8 +32,7 @@ fn text_64_64_reloc() { fn load_and_attach(name: &str, bytes: &[u8]) -> Bpf { let mut bpf = Bpf::load(bytes).unwrap(); - - let prog: &mut UProbe = bpf.program_mut(name).unwrap().try_into().unwrap(); + let mut prog: WithBtfFd = bpf.program_mut(name).unwrap().try_into().unwrap(); prog.load().unwrap(); prog.attach( diff --git a/test/integration-test/src/tests/smoke.rs b/test/integration-test/src/tests/smoke.rs index 8b09ac92..bc055f27 100644 --- a/test/integration-test/src/tests/smoke.rs +++ b/test/integration-test/src/tests/smoke.rs @@ -1,7 +1,7 @@ use aya::{ programs::{Extension, Xdp, XdpFlags}, util::KernelVersion, - Bpf, BpfLoader, + Bpf, BpfLoader, WithBtfFd, }; #[test] @@ -13,7 +13,7 @@ fn xdp() { } let mut bpf = Bpf::load(crate::PASS).unwrap(); - let dispatcher: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); + let mut dispatcher: WithBtfFd = bpf.program_mut("pass").unwrap().try_into().unwrap(); dispatcher.load().unwrap(); dispatcher.attach("lo", XdpFlags::default()).unwrap(); } @@ -26,11 +26,11 @@ fn extension() { return; } let mut bpf = Bpf::load(crate::MAIN).unwrap(); - let pass: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); + let mut pass: WithBtfFd = bpf.program_mut("pass").unwrap().try_into().unwrap(); pass.load().unwrap(); pass.attach("lo", XdpFlags::default()).unwrap(); let mut bpf = BpfLoader::new().extension("drop").load(crate::EXT).unwrap(); - let drop_: &mut Extension = bpf.program_mut("drop").unwrap().try_into().unwrap(); + let mut drop_: WithBtfFd = bpf.program_mut("drop").unwrap().try_into().unwrap(); drop_.load(pass.fd().unwrap(), "xdp_pass").unwrap(); }