diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 818a063b..a9bd5486 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -3,7 +3,10 @@ use std::{ collections::{HashMap, HashSet}, ffi::CString, fs, io, - os::{fd::RawFd, raw::c_int}, + os::{ + fd::{OwnedFd, RawFd}, + raw::c_int, + }, path::{Path, PathBuf}, }; @@ -473,7 +476,6 @@ impl<'a> BpfLoader<'a> { obj, fd: None, pinned: false, - btf_fd, }; let fd = match map.obj.pinning() { PinningType::ByName => { @@ -488,7 +490,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 +499,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 +547,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 +617,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 +654,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 +699,11 @@ impl<'a> BpfLoader<'a> { })?; }; - Ok(Bpf { maps, programs }) + Ok(Bpf { + maps, + programs, + btf_fd, + }) } } @@ -743,9 +747,26 @@ impl<'a> Default for BpfLoader<'a> { /// 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>, + /// Maps that were loaded from the BPF object + /// + /// After the BPF object is loaded, a `Bpf` instance keeps these + /// maps to manage their lifetime during drop but otherwise does + /// not touch them. + pub maps: HashMap<String, Map>, + /// Programs that were found in the BPF object + /// + /// Unlike maps, programs do not start loaded nor attached, that + /// is a separate action. After the BPF object is loaded, a `Bpf` + /// instance keeps these programs to manage their lifetime during + /// drop but otherwise does not touch them. + pub programs: HashMap<String, Program>, + /// The file descriptor of the loaded BTF section from the BPF + /// object. + /// + /// This may be used when loading programs + pub btf_fd: Option<OwnedFd>, } impl Bpf { @@ -882,8 +903,8 @@ impl Bpf { /// # let mut bpf = aya::Bpf::load(&[])?; /// use aya::programs::UProbe; /// - /// let program: &mut UProbe = bpf.program_mut("SSL_read").unwrap().try_into()?; - /// program.load()?; + /// let program: &mut UProbe = bpf.programs.get_mut("SSL_read").unwrap().try_into()?; + /// program.load(bpf.btf_fd.as_ref())?; /// program.attach(Some("SSL_read"), 0, "libssl", None)?; /// # Ok::<(), aya::BpfError>(()) /// ``` @@ -993,12 +1014,12 @@ pub enum BpfError { ProgramError(#[from] ProgramError), } -fn load_btf(raw_btf: Vec<u8>, verifier_log_level: VerifierLogLevel) -> Result<RawFd, BtfError> { +fn load_btf(raw_btf: Vec<u8>, verifier_log_level: VerifierLogLevel) -> Result<OwnedFd, 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, 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::<Result<Vec<_>, _>>(); @@ -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::<Result<Vec<_>, _>>().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..406ff496 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -24,8 +24,8 @@ //! //! 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()?; -//! prog.load()?; +//! let prog: &mut SkMsg = bpf.programs.get_mut("intercept_egress_packet").unwrap().try_into()?; +//! prog.load(bpf.btf_fd.as_ref())?; //! prog.attach(map_fd)?; //! //! # Ok::<(), aya::BpfError>(()) @@ -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<V>(map: &MapData) -> Result<(), MapError> { pub struct MapData { pub(crate) obj: obj::Map, pub(crate) fd: Option<RawFd>, - pub(crate) btf_fd: Option<RawFd>, /// 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<RawFd, MapError> { + pub fn create(&mut self, name: &str, btf_fd: Option<impl AsFd>) -> Result<RawFd, MapError> { 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<T: Pod> Deref for PerCpuValues<T> { #[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::<BorrowedFd>::None), Ok(42)); assert_eq!(map.fd, Some(42)); - assert_matches!(map.create("foo"), Err(MapError::AlreadyCreated { .. })); + assert_matches!( + map.create("foo", Option::<BorrowedFd>::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::<BorrowedFd>::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..5e147527 100644 --- a/aya/src/maps/sock/sock_hash.rs +++ b/aya/src/maps/sock/sock_hash.rs @@ -49,8 +49,8 @@ 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()?; -/// prog.load()?; +/// let prog: &mut SkMsg = bpf.programs.get_mut("intercept_egress_packet").unwrap().try_into()?; +/// prog.load(bpf.btf_fd.as_ref())?; /// prog.attach(map_fd)?; /// /// let mut client = TcpStream::connect("127.0.0.1:1234")?; diff --git a/aya/src/maps/sock/sock_map.rs b/aya/src/maps/sock/sock_map.rs index d34f658b..39290dd5 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,8 +33,8 @@ 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()?; -/// prog.load()?; +/// let prog: &mut SkSkb = bpf.programs.get_mut("intercept_ingress_packet").unwrap().try_into()?; +/// prog.load(bpf.btf_fd.as_ref())?; /// prog.attach(map_fd)?; /// /// # Ok::<(), aya::BpfError>(()) diff --git a/aya/src/programs/cgroup_device.rs b/aya/src/programs/cgroup_device.rs index e3580b28..76d5a50e 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 std::os::fd::{AsFd, AsRawFd, RawFd}; use crate::{ generated::{bpf_attach_type::BPF_CGROUP_DEVICE, bpf_prog_type::BPF_PROG_TYPE_CGROUP_DEVICE}, @@ -40,8 +40,8 @@ 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()?; -/// program.load()?; +/// let program: &mut CgroupDevice = bpf.programs.get_mut("cgroup_dev").unwrap().try_into()?; +/// program.load(bpf.btf_fd.as_ref())?; /// program.attach(cgroup)?; /// # Ok::<(), Error>(()) /// ``` @@ -53,8 +53,8 @@ pub struct CgroupDevice { 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<impl AsFd>) -> 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..9af6a0aa 100644 --- a/aya/src/programs/cgroup_skb.rs +++ b/aya/src/programs/cgroup_skb.rs @@ -3,7 +3,7 @@ use crate::util::KernelVersion; use std::{ hash::Hash, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, RawFd}, path::Path, }; @@ -50,8 +50,8 @@ 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()?; -/// egress.load()?; +/// let egress: &mut CgroupSkb = bpf.programs.get_mut("egress_filter").unwrap().try_into()?; +/// egress.load(bpf.btf_fd.as_ref())?; /// egress.attach(file, CgroupSkbAttachType::Egress)?; /// # Ok::<(), Error>(()) /// ``` @@ -64,14 +64,14 @@ pub struct CgroupSkb { impl CgroupSkb { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..a69c51d1 100644 --- a/aya/src/programs/cgroup_sock.rs +++ b/aya/src/programs/cgroup_sock.rs @@ -5,7 +5,7 @@ pub use aya_obj::programs::CgroupSockAttachType; use crate::util::KernelVersion; use std::{ hash::Hash, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, RawFd}, path::Path, }; @@ -48,8 +48,8 @@ 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()?; -/// bind.load()?; +/// let bind: &mut CgroupSock = bpf.programs.get_mut("bind").unwrap().try_into()?; +/// bind.load(bpf.btf_fd.as_ref())?; /// bind.attach(file)?; /// # Ok::<(), Error>(()) /// ``` @@ -62,9 +62,9 @@ pub struct CgroupSock { impl CgroupSock { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..faaa1738 100644 --- a/aya/src/programs/cgroup_sock_addr.rs +++ b/aya/src/programs/cgroup_sock_addr.rs @@ -5,7 +5,7 @@ pub use aya_obj::programs::CgroupSockAddrAttachType; use crate::util::KernelVersion; use std::{ hash::Hash, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, RawFd}, path::Path, }; @@ -49,8 +49,8 @@ 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()?; -/// egress.load()?; +/// let egress: &mut CgroupSockAddr = bpf.programs.get_mut("connect4").unwrap().try_into()?; +/// egress.load(bpf.btf_fd.as_ref())?; /// egress.attach(file)?; /// # Ok::<(), Error>(()) /// ``` @@ -63,9 +63,9 @@ pub struct CgroupSockAddr { impl CgroupSockAddr { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..b6f03f72 100644 --- a/aya/src/programs/cgroup_sockopt.rs +++ b/aya/src/programs/cgroup_sockopt.rs @@ -5,7 +5,7 @@ pub use aya_obj::programs::CgroupSockoptAttachType; use crate::util::KernelVersion; use std::{ hash::Hash, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, RawFd}, path::Path, }; @@ -46,8 +46,8 @@ 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()?; -/// program.load()?; +/// let program: &mut CgroupSockopt = bpf.programs.get_mut("cgroup_sockopt").unwrap().try_into()?; +/// program.load(bpf.btf_fd.as_ref())?; /// program.attach(file)?; /// # Ok::<(), Error>(()) /// ``` @@ -60,9 +60,9 @@ pub struct CgroupSockopt { impl CgroupSockopt { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..e8c2f012 100644 --- a/aya/src/programs/cgroup_sysctl.rs +++ b/aya/src/programs/cgroup_sysctl.rs @@ -3,7 +3,7 @@ use crate::util::KernelVersion; use std::{ hash::Hash, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, RawFd}, }; use crate::{ @@ -42,8 +42,8 @@ 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()?; -/// program.load()?; +/// let program: &mut CgroupSysctl = bpf.programs.get_mut("cgroup_sysctl").unwrap().try_into()?; +/// program.load(bpf.btf_fd.as_ref())?; /// program.attach(file)?; /// # Ok::<(), Error>(()) /// ``` @@ -55,8 +55,8 @@ pub struct CgroupSysctl { impl CgroupSysctl { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_CGROUP_SYSCTL, &mut self.data) + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..7f88d471 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; @@ -37,13 +37,13 @@ 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()?; -/// prog.load()?; +/// let prog: &mut Xdp = bpf.programs.get_mut("main").unwrap().try_into()?; +/// prog.load(bpf.btf_fd.as_ref())?; /// prog.attach("eth0", XdpFlags::default())?; /// /// let prog_fd = prog.fd().unwrap(); -/// let ext: &mut Extension = bpf.program_mut("extension").unwrap().try_into()?; -/// ext.load(prog_fd, "function_to_replace")?; +/// let ext: &mut Extension = bpf.programs.get_mut("extension").unwrap().try_into()?; +/// ext.load(prog_fd, "function_to_replace", bpf.btf_fd.as_ref())?; /// ext.attach()?; /// Ok::<(), aya::BpfError>(()) /// ``` @@ -68,14 +68,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<impl AsFd>, + ) -> 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..30c3b0ee 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}, @@ -37,8 +39,8 @@ 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()?; -/// program.load("filename_lookup", &btf)?; +/// let program: &mut FEntry = bpf.programs.get_mut("filename_lookup").unwrap().try_into()?; +/// program.load("filename_lookup", &btf, bpf.btf_fd.as_ref())?; /// program.attach()?; /// # Ok::<(), Error>(()) /// ``` @@ -55,10 +57,15 @@ impl FEntry { /// 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<impl AsFd>, + ) -> 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..7091bbbb 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}, @@ -37,8 +39,8 @@ 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()?; -/// program.load("filename_lookup", &btf)?; +/// let program: &mut FExit = bpf.programs.get_mut("filename_lookup").unwrap().try_into()?; +/// program.load("filename_lookup", &btf, bpf.btf_fd.as_ref())?; /// program.attach()?; /// # Ok::<(), Error>(()) /// ``` @@ -55,10 +57,15 @@ impl FExit { /// 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<impl AsFd>, + ) -> 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..9bb8e7fd 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::{ @@ -32,8 +32,8 @@ 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()?; -/// program.load()?; +/// let program: &mut KProbe = bpf.programs.get_mut("intercept_wakeups").unwrap().try_into()?; +/// program.load(bpf.btf_fd.as_ref())?; /// program.attach("try_to_wake_up", 0)?; /// # Ok::<(), aya::BpfError>(()) /// ``` @@ -46,8 +46,8 @@ pub struct KProbe { impl KProbe { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_KPROBE, &mut self.data) + pub fn load(&mut self, btf_fd: Option<&impl AsFd>) -> 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..06639256 100644 --- a/aya/src/programs/links.rs +++ b/aya/src/programs/links.rs @@ -97,8 +97,8 @@ 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()?; -/// program.load()?; +/// let program: &mut KProbe = bpf.programs.get_mut("intercept_wakeups").unwrap().try_into()?; +/// program.load(bpf.btf_fd.as_ref())?; /// let link_id = program.attach("try_to_wake_up", 0)?; /// let link = program.take_link(link_id).unwrap(); /// let fd_link: FdLink = link.try_into().unwrap(); diff --git a/aya/src/programs/lirc_mode2.rs b/aya/src/programs/lirc_mode2.rs index 1d445eb7..8156f821 100644 --- a/aya/src/programs/lirc_mode2.rs +++ b/aya/src/programs/lirc_mode2.rs @@ -1,5 +1,5 @@ //! Lirc programs. -use std::os::fd::{AsRawFd, RawFd}; +use std::os::fd::{AsFd, AsRawFd, RawFd}; use crate::{ generated::{bpf_attach_type::BPF_LIRC_MODE2, bpf_prog_type::BPF_PROG_TYPE_LIRC_MODE2}, @@ -40,8 +40,8 @@ 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(); -/// decoder.load()?; +/// let decoder: &mut LircMode2 = bpf.programs.get_mut("imon_rsc").unwrap().try_into().unwrap(); +/// decoder.load(bpf.btf_fd.as_ref())?; /// decoder.attach(file)?; /// # Ok::<(), Error>(()) /// ``` @@ -53,8 +53,8 @@ pub struct LircMode2 { impl LircMode2 { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_LIRC_MODE2, &mut self.data) + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..4d35087e 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}, @@ -39,8 +41,8 @@ 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()?; -/// program.load("security_bprm_exec", &btf)?; +/// let program: &mut Lsm = bpf.programs.get_mut("lsm_prog").unwrap().try_into()?; +/// program.load("security_bprm_exec", &btf, bpf.btf_fd.as_ref())?; /// program.attach()?; /// # Ok::<(), LsmError>(()) /// ``` @@ -59,12 +61,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<impl AsFd>, + ) -> 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 b52f76f8..a1456c2a 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -18,8 +18,8 @@ //! //! 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()?; -//! program.load()?; +//! let program: &mut KProbe = bpf.programs.get_mut("intercept_wakeups").unwrap().try_into()?; +//! program.load(bpf.btf_fd.as_ref())?; //! // intercept_wakeups will be called every time try_to_wake_up() is called //! // inside the kernel //! program.attach("try_to_wake_up", 0)?; @@ -69,7 +69,7 @@ use libc::ENOSPC; use std::{ ffi::CString, io, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, RawFd}, path::{Path, PathBuf}, }; use thiserror::Error; @@ -413,7 +413,6 @@ pub(crate) struct ProgramData<T: Link> { pub(crate) attach_btf_obj_fd: Option<u32>, pub(crate) attach_btf_id: Option<u32>, pub(crate) attach_prog_fd: Option<RawFd>, - pub(crate) btf_fd: Option<RawFd>, pub(crate) verifier_log_level: VerifierLogLevel, pub(crate) path: Option<PathBuf>, pub(crate) flags: u32, @@ -423,7 +422,6 @@ impl<T: Link> ProgramData<T> { pub(crate) fn new( name: Option<String>, obj: (obj::Program, obj::Function), - btf_fd: Option<RawFd>, verifier_log_level: VerifierLogLevel, ) -> ProgramData<T> { ProgramData { @@ -435,7 +433,6 @@ impl<T: Link> ProgramData<T> { 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<T: Link> ProgramData<T> { 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<T: Link, P: AsRef<Path>>(data: &ProgramData<T>, path: P) -> Resul fn load_program<T: Link>( prog_type: bpf_prog_type, data: &mut ProgramData<T>, + btf_fd: Option<impl AsFd>, ) -> Result<(), ProgramError> { let ProgramData { name, @@ -556,7 +553,6 @@ fn load_program<T: Link>( attach_btf_obj_fd, attach_btf_id, attach_prog_fd, - btf_fd, verifier_log_level, path: _, flags, @@ -613,7 +609,7 @@ fn load_program<T: Link>( 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, diff --git a/aya/src/programs/perf_event.rs b/aya/src/programs/perf_event.rs index 5de7eeef..70fe929a 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, }; @@ -105,8 +107,8 @@ 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()?; -/// prog.load()?; +/// let prog: &mut PerfEvent = bpf.programs.get_mut("observe_cpu_clock").unwrap().try_into()?; +/// prog.load(bpf.btf_fd.as_ref())?; /// /// for cpu in online_cpus()? { /// prog.attach( @@ -126,8 +128,8 @@ pub struct PerfEvent { impl PerfEvent { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_PERF_EVENT, &mut self.data) + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..89b3d654 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, @@ -27,8 +27,8 @@ 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()?; -/// program.load()?; +/// let program: &mut RawTracePoint = bpf.programs.get_mut("sys_enter").unwrap().try_into()?; +/// program.load(bpf.btf_fd.as_ref())?; /// program.attach("sys_enter")?; /// # Ok::<(), aya::BpfError>(()) /// ``` @@ -40,8 +40,8 @@ pub struct RawTracePoint { impl RawTracePoint { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_RAW_TRACEPOINT, &mut self.data) + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..a3199da0 100644 --- a/aya/src/programs/sk_lookup.rs +++ b/aya/src/programs/sk_lookup.rs @@ -1,4 +1,4 @@ -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}, @@ -39,8 +39,8 @@ 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()?; -/// program.load()?; +/// let program: &mut SkLookup = bpf.programs.get_mut("sk_lookup").unwrap().try_into()?; +/// program.load(bpf.btf_fd.as_ref())?; /// program.attach(file)?; /// # Ok::<(), Error>(()) /// ``` @@ -52,9 +52,9 @@ pub struct SkLookup { impl SkLookup { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..18fe8a03 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}, @@ -46,8 +46,8 @@ 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()?; -/// prog.load()?; +/// let prog: &mut SkMsg = bpf.programs.get_mut("intercept_egress_packet").unwrap().try_into()?; +/// prog.load(bpf.btf_fd.as_ref())?; /// prog.attach(map_fd)?; /// /// let mut client = TcpStream::connect("127.0.0.1:1234")?; @@ -71,8 +71,8 @@ pub struct SkMsg { impl SkMsg { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_SK_MSG, &mut self.data) + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..5a8db29f 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::{ @@ -45,8 +48,8 @@ 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()?; -/// prog.load()?; +/// let prog: &mut SkSkb = bpf.programs.get_mut("intercept_ingress_packet").unwrap().try_into()?; +/// prog.load(bpf.btf_fd.as_ref())?; /// prog.attach(map_fd)?; /// /// # Ok::<(), aya::BpfError>(()) @@ -64,8 +67,8 @@ pub struct SkSkb { impl SkSkb { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_SK_SKB, &mut self.data) + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..a4fffbff 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}, @@ -39,8 +39,8 @@ 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()?; -/// prog.load()?; +/// let prog: &mut SockOps = bpf.programs.get_mut("intercept_active_sockets").unwrap().try_into()?; +/// prog.load(bpf.btf_fd.as_ref())?; /// prog.attach(file)?; /// # Ok::<(), Error>(()) #[derive(Debug)] @@ -51,8 +51,8 @@ pub struct SockOps { impl SockOps { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_SOCK_OPS, &mut self.data) + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..fb2fdc66 100644 --- a/aya/src/programs/socket_filter.rs +++ b/aya/src/programs/socket_filter.rs @@ -2,7 +2,7 @@ use libc::{setsockopt, SOL_SOCKET}; use std::{ io, mem, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, RawFd}, }; use thiserror::Error; @@ -52,8 +52,8 @@ 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()?; -/// prog.load()?; +/// let prog: &mut SocketFilter = bpf.programs.get_mut("filter_packets").unwrap().try_into()?; +/// prog.load(bpf.btf_fd.as_ref())?; /// prog.attach(client.as_raw_fd())?; /// # Ok::<(), Error>(()) /// ``` @@ -65,8 +65,8 @@ pub struct SocketFilter { impl SocketFilter { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_SOCKET_FILTER, &mut self.data) + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..860bff38 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, }; @@ -63,8 +64,8 @@ pub enum TcAttachType { /// // attached /// tc::qdisc_add_clsact("eth0")?; /// -/// let prog: &mut SchedClassifier = bpf.program_mut("redirect_ingress").unwrap().try_into()?; -/// prog.load()?; +/// let prog: &mut SchedClassifier = bpf.programs.get_mut("redirect_ingress").unwrap().try_into()?; +/// prog.load(bpf.btf_fd.as_ref())?; /// prog.attach("eth0", TcAttachType::Ingress)?; /// /// # Ok::<(), Error>(()) @@ -114,8 +115,8 @@ pub struct TcOptions { impl SchedClassifier { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_SCHED_CLS, &mut self.data) + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..302a78ff 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}, @@ -36,8 +38,8 @@ 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()?; -/// program.load("sched_process_fork", &btf)?; +/// let program: &mut BtfTracePoint = bpf.programs.get_mut("sched_process_fork").unwrap().try_into()?; +/// program.load("sched_process_fork", &btf, bpf.btf_fd.as_ref())?; /// program.attach()?; /// # Ok::<(), Error>(()) /// ``` @@ -57,12 +59,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<impl AsFd>, + ) -> 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..2f522240 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::{ @@ -54,8 +54,8 @@ 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()?; -/// prog.load()?; +/// let prog: &mut TracePoint = bpf.programs.get_mut("trace_context_switch").unwrap().try_into()?; +/// prog.load(bpf.btf_fd.as_ref())?; /// prog.attach("sched", "sched_switch")?; /// # Ok::<(), Error>(()) /// ``` @@ -67,8 +67,8 @@ pub struct TracePoint { impl TracePoint { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_TRACEPOINT, &mut self.data) + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..60bfdf83 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, }; @@ -50,8 +50,8 @@ pub struct UProbe { impl UProbe { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { - load_program(BPF_PROG_TYPE_KPROBE, &mut self.data) + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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..36c2adc8 100644 --- a/aya/src/programs/xdp.rs +++ b/aya/src/programs/xdp.rs @@ -3,7 +3,13 @@ use crate::util::KernelVersion; 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::{ @@ -78,9 +84,9 @@ pub struct Xdp { impl Xdp { /// Loads the program inside the kernel. - pub fn load(&mut self) -> Result<(), ProgramError> { + pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> 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 32a55016..3bc0c655 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::RawFd, + os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd}, slice, }; @@ -35,7 +35,7 @@ use crate::{ pub(crate) fn bpf_create_map( name: &CStr, def: &obj::Map, - btf_fd: Option<RawFd>, + btf_fd: Option<impl AsFd>, kernel_version: KernelVersion, ) -> SysResult<c_long> { let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; @@ -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<bpf_attach_type>, - pub(crate) prog_btf_fd: Option<RawFd>, + pub(crate) prog_btf_fd: Option<BorrowedFd<'a>>, pub(crate) attach_btf_obj_fd: Option<u32>, pub(crate) attach_btf_id: Option<u32>, pub(crate) attach_prog_fd: Option<RawFd>, @@ -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; @@ -551,7 +551,7 @@ pub(crate) fn bpf_load_btf( raw_btf: &[u8], log_buf: &mut [u8], verifier_log_level: VerifierLogLevel, -) -> SysResult<c_long> { +) -> SysResult<OwnedFd> { let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let u = unsafe { &mut attr.__bindgen_anon_7 }; u.btf = raw_btf.as_ptr() as *const _ as u64; @@ -561,7 +561,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<RawFd, io::Error> { @@ -701,10 +703,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::<BorrowedFd>::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 20e6a134..abaf748f 100644 --- a/test/integration-test/src/tests/bpf_probe_read.rs +++ b/test/integration-test/src/tests/bpf_probe_read.rs @@ -105,8 +105,8 @@ fn result_bytes(bpf: &Bpf) -> Vec<u8> { 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(); - prog.load().unwrap(); + let prog: &mut UProbe = bpf.programs.get_mut(prog_name).unwrap().try_into().unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); prog.attach(Some(func_name), 0, "/proc/self/exe", None) .unwrap(); diff --git a/test/integration-test/src/tests/btf_relocations.rs b/test/integration-test/src/tests/btf_relocations.rs index 75f36223..3a8b53e9 100644 --- a/test/integration-test/src/tests/btf_relocations.rs +++ b/test/integration-test/src/tests/btf_relocations.rs @@ -385,11 +385,14 @@ impl RelocationTestRunner { } let mut bpf = loader.load(&self.ebpf).context("Loading eBPF failed")?; let program: &mut TracePoint = bpf - .program_mut("bpf_prog") + .programs + .get_mut("bpf_prog") .context("bpf_prog not found")? .try_into() .context("program not a tracepoint")?; - program.load().context("Loading tracepoint failed")?; + program + .load(bpf.btf_fd.as_ref()) + .context("Loading tracepoint failed")?; // Attach to sched_switch and wait some time to make sure it executed at least once program .attach("sched", "sched_switch") diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 8958ae59..92b9ddc9 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -17,11 +17,12 @@ const RETRY_DURATION_MS: u64 = 10; fn long_name() { let mut bpf = Bpf::load(crate::NAME_TEST).unwrap(); let name_prog: &mut Xdp = bpf - .program_mut("ihaveaverylongname") + .programs + .get_mut("ihaveaverylongname") .unwrap() .try_into() .unwrap(); - name_prog.load().unwrap(); + name_prog.load(bpf.btf_fd.as_ref()).unwrap(); name_prog.attach("lo", XdpFlags::default()).unwrap(); // We used to be able to assert with bpftool that the program name was short. @@ -36,8 +37,13 @@ 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(); - prog.load().unwrap(); + let prog: &mut TracePoint = bpf + .programs + .get_mut("tracepoint") + .unwrap() + .try_into() + .unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); prog.attach("sched", "sched_switch").unwrap(); thread::sleep(time::Duration::from_secs(3)); @@ -110,8 +116,13 @@ 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(); - prog.load().unwrap(); + let prog: &mut Xdp = bpf + .programs + .get_mut("test_xdp") + .unwrap() + .try_into() + .unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); assert_loaded!("test_xdp", true); let link = prog.attach("lo", XdpFlags::default()).unwrap(); { @@ -121,7 +132,7 @@ fn unload_xdp() { }; assert_loaded!("test_xdp", false); - prog.load().unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); assert_loaded!("test_xdp", true); prog.attach("lo", XdpFlags::default()).unwrap(); @@ -135,8 +146,13 @@ 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(); - prog.load().unwrap(); + let prog: &mut KProbe = bpf + .programs + .get_mut("test_kprobe") + .unwrap() + .try_into() + .unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); assert_loaded!("test_kprobe", true); let link = prog.attach("try_to_wake_up", 0).unwrap(); { @@ -146,7 +162,7 @@ fn unload_kprobe() { }; assert_loaded!("test_kprobe", false); - prog.load().unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); assert_loaded!("test_kprobe", true); prog.attach("try_to_wake_up", 0).unwrap(); @@ -161,12 +177,13 @@ fn unload_kprobe() { fn basic_tracepoint() { let mut bpf = Bpf::load(crate::TEST).unwrap(); let prog: &mut TracePoint = bpf - .program_mut("test_tracepoint") + .programs + .get_mut("test_tracepoint") .unwrap() .try_into() .unwrap(); - prog.load().unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); assert_loaded!("test_tracepoint", true); let link = prog.attach("syscalls", "sys_enter_kill").unwrap(); @@ -177,7 +194,7 @@ fn basic_tracepoint() { }; assert_loaded!("test_tracepoint", false); - prog.load().unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); assert_loaded!("test_tracepoint", true); prog.attach("syscalls", "sys_enter_kill").unwrap(); @@ -191,9 +208,14 @@ 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 prog: &mut UProbe = bpf + .programs + .get_mut("test_uprobe") + .unwrap() + .try_into() + .unwrap(); - prog.load().unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); assert_loaded!("test_uprobe", true); let link = prog.attach(Some("sleep"), 0, "libc", None).unwrap(); @@ -204,7 +226,7 @@ fn basic_uprobe() { }; assert_loaded!("test_uprobe", false); - prog.load().unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); assert_loaded!("test_uprobe", true); prog.attach(Some("sleep"), 0, "libc", None).unwrap(); @@ -224,8 +246,13 @@ fn pin_link() { } let mut bpf = Bpf::load(crate::TEST).unwrap(); - let prog: &mut Xdp = bpf.program_mut("test_xdp").unwrap().try_into().unwrap(); - prog.load().unwrap(); + let prog: &mut Xdp = bpf + .programs + .get_mut("test_xdp") + .unwrap() + .try_into() + .unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); let link_id = prog.attach("lo", XdpFlags::default()).unwrap(); let link = prog.take_link(link_id).unwrap(); assert_loaded!("test_xdp", true); @@ -257,8 +284,8 @@ 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(); - prog.load().unwrap(); + let prog: &mut Xdp = bpf.programs.get_mut("pass").unwrap().try_into().unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); prog.pin("/sys/fs/bpf/aya-xdp-test-prog").unwrap(); } @@ -291,8 +318,8 @@ 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(); - prog.load().unwrap(); + let prog: &mut Xdp = bpf.programs.get_mut("pass").unwrap().try_into().unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); let link = PinnedLink::from_pin("/sys/fs/bpf/aya-xdp-test-lo") .unwrap() @@ -312,11 +339,12 @@ fn pin_lifecycle_tracepoint() { { let mut bpf = Bpf::load(crate::TEST).unwrap(); let prog: &mut TracePoint = bpf - .program_mut("test_tracepoint") + .programs + .get_mut("test_tracepoint") .unwrap() .try_into() .unwrap(); - prog.load().unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); prog.pin("/sys/fs/bpf/aya-tracepoint-test-prog").unwrap(); } @@ -365,8 +393,13 @@ 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(); - prog.load().unwrap(); + let prog: &mut KProbe = bpf + .programs + .get_mut("test_kprobe") + .unwrap() + .try_into() + .unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); prog.pin("/sys/fs/bpf/aya-kprobe-test-prog").unwrap(); } @@ -423,8 +456,13 @@ 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(); - prog.load().unwrap(); + let prog: &mut UProbe = bpf + .programs + .get_mut("test_uprobe") + .unwrap() + .try_into() + .unwrap(); + prog.load(bpf.btf_fd.as_ref()).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 9033fcc0..79af60cf 100644 --- a/test/integration-test/src/tests/log.rs +++ b/test/integration-test/src/tests/log.rs @@ -58,8 +58,13 @@ async fn log() { .unwrap(); } - let prog: &mut UProbe = bpf.program_mut("test_log").unwrap().try_into().unwrap(); - prog.load().unwrap(); + let prog: &mut UProbe = bpf + .programs + .get_mut("test_log") + .unwrap() + .try_into() + .unwrap(); + prog.load(bpf.btf_fd.as_ref()).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 8642dc4b..8e1d2227 100644 --- a/test/integration-test/src/tests/relocations.rs +++ b/test/integration-test/src/tests/relocations.rs @@ -33,8 +33,8 @@ 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(); - prog.load().unwrap(); + let prog: &mut UProbe = bpf.programs.get_mut(name).unwrap().try_into().unwrap(); + prog.load(bpf.btf_fd.as_ref()).unwrap(); prog.attach( Some("trigger_relocations_program"), diff --git a/test/integration-test/src/tests/smoke.rs b/test/integration-test/src/tests/smoke.rs index 8b09ac92..855e353d 100644 --- a/test/integration-test/src/tests/smoke.rs +++ b/test/integration-test/src/tests/smoke.rs @@ -13,8 +13,8 @@ fn xdp() { } let mut bpf = Bpf::load(crate::PASS).unwrap(); - let dispatcher: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); - dispatcher.load().unwrap(); + let dispatcher: &mut Xdp = bpf.programs.get_mut("pass").unwrap().try_into().unwrap(); + dispatcher.load(bpf.btf_fd.as_ref()).unwrap(); dispatcher.attach("lo", XdpFlags::default()).unwrap(); } @@ -26,11 +26,13 @@ fn extension() { return; } let mut bpf = Bpf::load(crate::MAIN).unwrap(); - let pass: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); - pass.load().unwrap(); + let pass: &mut Xdp = bpf.programs.get_mut("pass").unwrap().try_into().unwrap(); + pass.load(bpf.btf_fd.as_ref()).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(); - drop_.load(pass.fd().unwrap(), "xdp_pass").unwrap(); + let drop_: &mut Extension = bpf.programs.get_mut("drop").unwrap().try_into().unwrap(); + drop_ + .load(pass.fd().unwrap(), "xdp_pass", bpf.btf_fd.as_ref()) + .unwrap(); }