aya: Use `OwnedFd` when loading BTF fd

This fixes an existing file descriptor leak when there is BTF data in
the loaded object.

There is a required breaking change in that now the btf fd will be
passed in the programs and maps when loading them instead of them
storing a raw fd to them as to avoid the maps/programs needing to be
tied by lifetime to the btf fd (since they aren't needed at load
time).

To avoid lifetime issues caused by the bpf object owning both the btf
fd and the map of programs/maps but needing to reference the fd while
mutating the programs these fields are now made public. As far as I
can tell there are no safety issues with making these fields public,
the only issue would be tying that struct's public API more. I did
make the structure non exhaustive so that adding fields wouldn't
become a breaking change.
reviewable/pr662/r5
Andrés Medina 2 years ago
parent dadbe8fc39
commit 7456d2bb0d

@ -3,7 +3,10 @@ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
ffi::CString, ffi::CString,
fs, io, fs, io,
os::{fd::RawFd, raw::c_int}, os::{
fd::{OwnedFd, RawFd},
raw::c_int,
},
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
@ -473,7 +476,6 @@ impl<'a> BpfLoader<'a> {
obj, obj,
fd: None, fd: None,
pinned: false, pinned: false,
btf_fd,
}; };
let fd = match map.obj.pinning() { let fd = match map.obj.pinning() {
PinningType::ByName => { PinningType::ByName => {
@ -488,7 +490,7 @@ impl<'a> BpfLoader<'a> {
fd as RawFd fd as RawFd
} }
Err(_) => { Err(_) => {
let fd = map.create(&name)?; let fd = map.create(&name, btf_fd.as_ref())?;
map.pin(&name, path).map_err(|error| MapError::PinError { map.pin(&name, path).map_err(|error| MapError::PinError {
name: Some(name.to_string()), name: Some(name.to_string()),
error, 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 { 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) 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()) { let program = if extensions.contains(name.as_str()) {
Program::Extension(Extension { Program::Extension(Extension {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), data: ProgramData::new(prog_name, obj, *verifier_log_level),
}) })
} else { } else {
match &section { match &section {
ProgramSection::KProbe { .. } => Program::KProbe(KProbe { 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, kind: ProbeKind::KProbe,
}), }),
ProgramSection::KRetProbe { .. } => Program::KProbe(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, kind: ProbeKind::KRetProbe,
}), }),
ProgramSection::UProbe { .. } => Program::UProbe(UProbe { 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, kind: ProbeKind::UProbe,
}), }),
ProgramSection::URetProbe { .. } => Program::UProbe(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, kind: ProbeKind::URetProbe,
}), }),
ProgramSection::TracePoint { .. } => Program::TracePoint(TracePoint { 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 { .. } => { ProgramSection::SocketFilter { .. } => {
Program::SocketFilter(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, .. } => { ProgramSection::Xdp { frags, .. } => {
let mut data = let mut data = ProgramData::new(prog_name, obj, *verifier_log_level);
ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level);
if *frags { if *frags {
data.flags = BPF_F_XDP_HAS_FRAGS; data.flags = BPF_F_XDP_HAS_FRAGS;
} }
Program::Xdp(Xdp { data }) Program::Xdp(Xdp { data })
} }
ProgramSection::SkMsg { .. } => Program::SkMsg(SkMsg { 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 { .. } => { ProgramSection::CgroupSysctl { .. } => {
Program::CgroupSysctl(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, .. } => { ProgramSection::CgroupSockopt { attach_type, .. } => {
Program::CgroupSockopt(CgroupSockopt { 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, attach_type: *attach_type,
}) })
} }
ProgramSection::SkSkbStreamParser { .. } => Program::SkSkb(SkSkb { 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, kind: SkSkbKind::StreamParser,
}), }),
ProgramSection::SkSkbStreamVerdict { .. } => Program::SkSkb(SkSkb { 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, kind: SkSkbKind::StreamVerdict,
}), }),
ProgramSection::SockOps { .. } => Program::SockOps(SockOps { 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 { .. } => { ProgramSection::SchedClassifier { .. } => {
Program::SchedClassifier(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 { name: unsafe {
CString::from_vec_unchecked(Vec::from(name.clone())) CString::from_vec_unchecked(Vec::from(name.clone()))
.into_boxed_c_str() .into_boxed_c_str()
@ -616,37 +617,36 @@ impl<'a> BpfLoader<'a> {
}) })
} }
ProgramSection::CgroupSkb { .. } => Program::CgroupSkb(CgroupSkb { 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, expected_attach_type: None,
}), }),
ProgramSection::CgroupSkbIngress { .. } => Program::CgroupSkb(CgroupSkb { 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), expected_attach_type: Some(CgroupSkbAttachType::Ingress),
}), }),
ProgramSection::CgroupSkbEgress { .. } => Program::CgroupSkb(CgroupSkb { 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), expected_attach_type: Some(CgroupSkbAttachType::Egress),
}), }),
ProgramSection::CgroupSockAddr { attach_type, .. } => { ProgramSection::CgroupSockAddr { attach_type, .. } => {
Program::CgroupSockAddr(CgroupSockAddr { 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, attach_type: *attach_type,
}) })
} }
ProgramSection::LircMode2 { .. } => Program::LircMode2(LircMode2 { 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 { 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 { .. } => { ProgramSection::RawTracePoint { .. } => {
Program::RawTracePoint(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, .. } => { ProgramSection::Lsm { sleepable, .. } => {
let mut data = let mut data = ProgramData::new(prog_name, obj, *verifier_log_level);
ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level);
if *sleepable { if *sleepable {
data.flags = BPF_F_SLEEPABLE; data.flags = BPF_F_SLEEPABLE;
} }
@ -654,30 +654,30 @@ impl<'a> BpfLoader<'a> {
} }
ProgramSection::BtfTracePoint { .. } => { ProgramSection::BtfTracePoint { .. } => {
Program::BtfTracePoint(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 { 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 { 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 { 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 { 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, .. } => { ProgramSection::CgroupSock { attach_type, .. } => {
Program::CgroupSock(CgroupSock { 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, attach_type: *attach_type,
}) })
} }
ProgramSection::CgroupDevice { .. } => { ProgramSection::CgroupDevice { .. } => {
Program::CgroupDevice(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. /// The main entry point into the library, used to work with eBPF programs and maps.
#[derive(Debug)] #[derive(Debug)]
#[non_exhaustive]
pub struct Bpf { pub struct Bpf {
maps: HashMap<String, Map>, /// Maps that were loaded from the BPF object
programs: HashMap<String, Program>, ///
/// 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 { impl Bpf {
@ -882,8 +903,8 @@ impl Bpf {
/// # let mut bpf = aya::Bpf::load(&[])?; /// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::programs::UProbe; /// use aya::programs::UProbe;
/// ///
/// let program: &mut UProbe = bpf.program_mut("SSL_read").unwrap().try_into()?; /// let program: &mut UProbe = bpf.programs.get_mut("SSL_read").unwrap().try_into()?;
/// program.load()?; /// program.load(bpf.btf_fd.as_ref())?;
/// program.attach(Some("SSL_read"), 0, "libssl", None)?; /// program.attach(Some("SSL_read"), 0, "libssl", None)?;
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
/// ``` /// ```
@ -993,12 +1014,12 @@ pub enum BpfError {
ProgramError(#[from] ProgramError), 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| { let (ret, verifier_log) = retry_with_verifier_logs(10, |logger| {
bpf_load_btf(raw_btf.as_slice(), logger, verifier_log_level) bpf_load_btf(raw_btf.as_slice(), logger, verifier_log_level)
}); });
match ret { match ret {
Ok(fd) => Ok(fd as RawFd), Ok(fd) => Ok(fd),
Err((_, io_error)) => Err(BtfError::LoadError { Err((_, io_error)) => Err(BtfError::LoadError {
io_error, io_error,
verifier_log, verifier_log,

@ -118,7 +118,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: None, fd: None,
pinned: false, pinned: false,
btf_fd: None,
}; };
assert_matches!( assert_matches!(
BloomFilter::<_, u16>::new(&map), BloomFilter::<_, u16>::new(&map),
@ -147,7 +146,6 @@ mod tests {
}), }),
fd: None, fd: None,
pinned: false, pinned: false,
btf_fd: None,
}; };
let map = Map::PerfEventArray(map_data); let map = Map::PerfEventArray(map_data);
@ -164,7 +162,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: None, fd: None,
pinned: false, pinned: false,
btf_fd: None,
}; };
assert_matches!( assert_matches!(
@ -179,7 +176,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
assert!(BloomFilter::<_, u32>::new(&mut map).is_ok()); assert!(BloomFilter::<_, u32>::new(&mut map).is_ok());
@ -191,7 +187,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let map = Map::BloomFilter(map_data); let map = Map::BloomFilter(map_data);
@ -206,7 +201,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let bloom_filter = BloomFilter::<_, u32>::new(&mut map).unwrap(); let bloom_filter = BloomFilter::<_, u32>::new(&mut map).unwrap();
@ -230,7 +224,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let bloom_filter = BloomFilter::<_, u32>::new(&mut map).unwrap(); let bloom_filter = BloomFilter::<_, u32>::new(&mut map).unwrap();
@ -244,7 +237,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let bloom_filter = BloomFilter::<_, u32>::new(&map).unwrap(); let bloom_filter = BloomFilter::<_, u32>::new(&map).unwrap();
@ -267,7 +259,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let bloom_filter = BloomFilter::<_, u32>::new(&map).unwrap(); let bloom_filter = BloomFilter::<_, u32>::new(&map).unwrap();

@ -149,7 +149,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: None, fd: None,
pinned: false, pinned: false,
btf_fd: None,
}; };
assert_matches!( assert_matches!(
HashMap::<_, u8, u32>::new(&map), HashMap::<_, u8, u32>::new(&map),
@ -166,7 +165,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: None, fd: None,
pinned: false, pinned: false,
btf_fd: None,
}; };
assert_matches!( assert_matches!(
HashMap::<_, u32, u16>::new(&map), HashMap::<_, u32, u16>::new(&map),
@ -183,7 +181,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: None, fd: None,
pinned: false, pinned: false,
btf_fd: None,
}; };
let map = Map::Array(map_data); let map = Map::Array(map_data);
@ -199,7 +196,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: None, fd: None,
pinned: false, pinned: false,
btf_fd: None,
}; };
let map = Map::HashMap(map_data); let map = Map::HashMap(map_data);
@ -218,7 +214,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: None, fd: None,
pinned: false, pinned: false,
btf_fd: None,
}; };
assert_matches!( assert_matches!(
@ -233,7 +228,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
assert!(HashMap::<_, u32, u32>::new(&mut map).is_ok()); assert!(HashMap::<_, u32, u32>::new(&mut map).is_ok());
@ -245,7 +239,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let map = Map::HashMap(map_data); let map = Map::HashMap(map_data);
@ -270,7 +263,6 @@ mod tests {
}), }),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let map = Map::HashMap(map_data); let map = Map::HashMap(map_data);
@ -286,7 +278,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap(); let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap();
@ -310,7 +301,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap(); let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap();
@ -331,7 +321,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap(); let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap();
@ -346,7 +335,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap(); let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap();
@ -370,7 +358,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap(); let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap();
@ -384,7 +371,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
@ -407,7 +393,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
@ -444,7 +429,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
let keys = hm.keys().collect::<Result<Vec<_>, _>>(); let keys = hm.keys().collect::<Result<Vec<_>, _>>();
@ -493,7 +477,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
@ -526,7 +509,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
@ -561,7 +543,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
let items = hm.iter().collect::<Result<Vec<_>, _>>().unwrap(); let items = hm.iter().collect::<Result<Vec<_>, _>>().unwrap();
@ -599,7 +580,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
@ -638,7 +618,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
@ -683,7 +662,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();

@ -237,7 +237,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: None, fd: None,
pinned: false, pinned: false,
btf_fd: None,
}; };
assert_matches!( assert_matches!(
LpmTrie::<_, u16, u32>::new(&map), LpmTrie::<_, u16, u32>::new(&map),
@ -254,7 +253,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: None, fd: None,
pinned: false, pinned: false,
btf_fd: None,
}; };
assert_matches!( assert_matches!(
LpmTrie::<_, u32, u16>::new(&map), LpmTrie::<_, u32, u16>::new(&map),
@ -282,7 +280,6 @@ mod tests {
data: Vec::new(), data: Vec::new(),
}), }),
fd: None, fd: None,
btf_fd: None,
pinned: false, pinned: false,
}; };
@ -300,7 +297,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: None, fd: None,
pinned: false, pinned: false,
btf_fd: None,
}; };
assert_matches!( assert_matches!(
@ -315,7 +311,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
assert!(LpmTrie::<_, u32, u32>::new(&mut map).is_ok()); assert!(LpmTrie::<_, u32, u32>::new(&mut map).is_ok());
@ -327,7 +322,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let map = Map::LpmTrie(map_data); let map = Map::LpmTrie(map_data);
@ -342,7 +336,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap(); let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8); let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
@ -367,7 +360,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap(); let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
@ -384,7 +376,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap(); let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8); let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
@ -409,7 +400,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap(); let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8); let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
@ -424,7 +414,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let trie = LpmTrie::<_, u32, u32>::new(&map).unwrap(); let trie = LpmTrie::<_, u32, u32>::new(&map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8); let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
@ -449,7 +438,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: Some(42), fd: Some(42),
pinned: false, pinned: false,
btf_fd: None,
}; };
let trie = LpmTrie::<_, u32, u32>::new(&map).unwrap(); let trie = LpmTrie::<_, u32, u32>::new(&map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8); let ipaddr = Ipv4Addr::new(8, 8, 8, 8);

@ -24,8 +24,8 @@
//! //!
//! let intercept_egress = SockMap::try_from(bpf.map_mut("INTERCEPT_EGRESS").unwrap())?; //! let intercept_egress = SockMap::try_from(bpf.map_mut("INTERCEPT_EGRESS").unwrap())?;
//! let map_fd = intercept_egress.fd()?; //! let map_fd = intercept_egress.fd()?;
//! let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; //! let prog: &mut SkMsg = bpf.programs.get_mut("intercept_egress_packet").unwrap().try_into()?;
//! prog.load()?; //! prog.load(bpf.btf_fd.as_ref())?;
//! prog.attach(map_fd)?; //! prog.attach(map_fd)?;
//! //!
//! # Ok::<(), aya::BpfError>(()) //! # Ok::<(), aya::BpfError>(())
@ -42,7 +42,7 @@ use std::{
marker::PhantomData, marker::PhantomData,
mem, mem,
ops::Deref, ops::Deref,
os::fd::{AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd, RawFd},
path::Path, path::Path,
ptr, ptr,
}; };
@ -486,14 +486,13 @@ pub(crate) fn check_v_size<V>(map: &MapData) -> Result<(), MapError> {
pub struct MapData { pub struct MapData {
pub(crate) obj: obj::Map, pub(crate) obj: obj::Map,
pub(crate) fd: Option<RawFd>, pub(crate) fd: Option<RawFd>,
pub(crate) btf_fd: Option<RawFd>,
/// Indicates if this map has been pinned to bpffs /// Indicates if this map has been pinned to bpffs
pub pinned: bool, pub pinned: bool,
} }
impl MapData { impl MapData {
/// Creates a new map with the provided `name` /// 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() { if self.fd.is_some() {
return Err(MapError::AlreadyCreated { name: name.into() }); return Err(MapError::AlreadyCreated { name: name.into() });
} }
@ -504,7 +503,7 @@ impl MapData {
let kernel_version = KernelVersion::current().unwrap(); let kernel_version = KernelVersion::current().unwrap();
#[cfg(test)] #[cfg(test)]
let kernel_version = KernelVersion::new(0xff, 0xff, 0xff); 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)| { |(code, io_error)| {
if kernel_version < KernelVersion::new(5, 11, 0) { if kernel_version < KernelVersion::new(5, 11, 0) {
maybe_warn_rlimit(); maybe_warn_rlimit();
@ -568,7 +567,6 @@ impl MapData {
Ok(MapData { Ok(MapData {
obj: parse_map_info(info, PinningType::ByName), obj: parse_map_info(info, PinningType::ByName),
fd: Some(fd), fd: Some(fd),
btf_fd: None,
pinned: true, pinned: true,
}) })
} }
@ -587,7 +585,6 @@ impl MapData {
Ok(MapData { Ok(MapData {
obj: parse_map_info(info, PinningType::None), obj: parse_map_info(info, PinningType::None),
fd: Some(fd), fd: Some(fd),
btf_fd: None,
pinned: false, pinned: false,
}) })
} }
@ -639,7 +636,6 @@ impl Clone for MapData {
MapData { MapData {
obj: self.obj.clone(), obj: self.obj.clone(),
fd: self.fd.map(|fd| unsafe { libc::dup(fd) }), fd: self.fd.map(|fd| unsafe { libc::dup(fd) }),
btf_fd: self.btf_fd,
pinned: self.pinned, pinned: self.pinned,
} }
} }
@ -842,6 +838,8 @@ impl<T: Pod> Deref for PerCpuValues<T> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::os::fd::BorrowedFd;
use assert_matches::assert_matches; use assert_matches::assert_matches;
use libc::EFAULT; use libc::EFAULT;
@ -876,7 +874,6 @@ mod tests {
obj: new_obj_map(), obj: new_obj_map(),
fd: None, fd: None,
pinned: false, pinned: false,
btf_fd: None,
} }
} }
@ -891,9 +888,12 @@ mod tests {
}); });
let mut map = new_map(); 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_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] #[test]
@ -901,7 +901,7 @@ mod tests {
override_syscall(|_| Err((-42, io::Error::from_raw_os_error(EFAULT)))); override_syscall(|_| Err((-42, io::Error::from_raw_os_error(EFAULT))));
let mut map = new_map(); let mut map = new_map();
let ret = map.create("foo"); let ret = map.create("foo", Option::<BorrowedFd>::None);
assert_matches!(ret, Err(MapError::CreateError { .. })); assert_matches!(ret, Err(MapError::CreateError { .. }));
if let Err(MapError::CreateError { if let Err(MapError::CreateError {
name, name,

@ -49,8 +49,8 @@ use crate::{
/// let mut intercept_egress = SockHash::<_, u32>::try_from(bpf.map("INTERCEPT_EGRESS").unwrap())?; /// let mut intercept_egress = SockHash::<_, u32>::try_from(bpf.map("INTERCEPT_EGRESS").unwrap())?;
/// let map_fd = intercept_egress.fd()?; /// let map_fd = intercept_egress.fd()?;
/// ///
/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; /// let prog: &mut SkMsg = bpf.programs.get_mut("intercept_egress_packet").unwrap().try_into()?;
/// prog.load()?; /// prog.load(bpf.btf_fd.as_ref())?;
/// prog.attach(map_fd)?; /// prog.attach(map_fd)?;
/// ///
/// let mut client = TcpStream::connect("127.0.0.1:1234")?; /// let mut client = TcpStream::connect("127.0.0.1:1234")?;

@ -33,8 +33,8 @@ use crate::{
/// let intercept_ingress = SockMap::try_from(bpf.map("INTERCEPT_INGRESS").unwrap())?; /// let intercept_ingress = SockMap::try_from(bpf.map("INTERCEPT_INGRESS").unwrap())?;
/// let map_fd = intercept_ingress.fd()?; /// let map_fd = intercept_ingress.fd()?;
/// ///
/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?; /// let prog: &mut SkSkb = bpf.programs.get_mut("intercept_ingress_packet").unwrap().try_into()?;
/// prog.load()?; /// prog.load(bpf.btf_fd.as_ref())?;
/// prog.attach(map_fd)?; /// prog.attach(map_fd)?;
/// ///
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())

@ -1,7 +1,7 @@
//! Cgroup device programs. //! Cgroup device programs.
use crate::util::KernelVersion; use crate::util::KernelVersion;
use std::os::fd::{AsRawFd, RawFd}; use std::os::fd::{AsFd, AsRawFd, RawFd};
use crate::{ use crate::{
generated::{bpf_attach_type::BPF_CGROUP_DEVICE, bpf_prog_type::BPF_PROG_TYPE_CGROUP_DEVICE}, 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; /// use aya::programs::CgroupDevice;
/// ///
/// let cgroup = std::fs::File::open("/sys/fs/cgroup/unified")?; /// let cgroup = std::fs::File::open("/sys/fs/cgroup/unified")?;
/// let program: &mut CgroupDevice = bpf.program_mut("cgroup_dev").unwrap().try_into()?; /// let program: &mut CgroupDevice = bpf.programs.get_mut("cgroup_dev").unwrap().try_into()?;
/// program.load()?; /// program.load(bpf.btf_fd.as_ref())?;
/// program.attach(cgroup)?; /// program.attach(cgroup)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
/// ``` /// ```
@ -53,8 +53,8 @@ pub struct CgroupDevice {
impl CgroupDevice { impl CgroupDevice {
/// Loads the program inside the kernel /// 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> {
load_program(BPF_PROG_TYPE_CGROUP_DEVICE, &mut self.data) load_program(BPF_PROG_TYPE_CGROUP_DEVICE, &mut self.data, btf_fd)
} }
/// Attaches the program to the given cgroup. /// Attaches the program to the given cgroup.

@ -3,7 +3,7 @@
use crate::util::KernelVersion; use crate::util::KernelVersion;
use std::{ use std::{
hash::Hash, hash::Hash,
os::fd::{AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd, RawFd},
path::Path, path::Path,
}; };
@ -50,8 +50,8 @@ use crate::{
/// use aya::programs::{CgroupSkb, CgroupSkbAttachType}; /// use aya::programs::{CgroupSkb, CgroupSkbAttachType};
/// ///
/// let file = File::open("/sys/fs/cgroup/unified")?; /// let file = File::open("/sys/fs/cgroup/unified")?;
/// let egress: &mut CgroupSkb = bpf.program_mut("egress_filter").unwrap().try_into()?; /// let egress: &mut CgroupSkb = bpf.programs.get_mut("egress_filter").unwrap().try_into()?;
/// egress.load()?; /// egress.load(bpf.btf_fd.as_ref())?;
/// egress.attach(file, CgroupSkbAttachType::Egress)?; /// egress.attach(file, CgroupSkbAttachType::Egress)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
/// ``` /// ```
@ -64,14 +64,14 @@ pub struct CgroupSkb {
impl CgroupSkb { impl CgroupSkb {
/// Loads the program inside the kernel. /// 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.data.expected_attach_type =
self.expected_attach_type self.expected_attach_type
.map(|attach_type| match attach_type { .map(|attach_type| match attach_type {
CgroupSkbAttachType::Ingress => BPF_CGROUP_INET_INGRESS, CgroupSkbAttachType::Ingress => BPF_CGROUP_INET_INGRESS,
CgroupSkbAttachType::Egress => BPF_CGROUP_INET_EGRESS, 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. /// Returns the expected attach type of the program.

@ -5,7 +5,7 @@ pub use aya_obj::programs::CgroupSockAttachType;
use crate::util::KernelVersion; use crate::util::KernelVersion;
use std::{ use std::{
hash::Hash, hash::Hash,
os::fd::{AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd, RawFd},
path::Path, path::Path,
}; };
@ -48,8 +48,8 @@ use crate::{
/// use aya::programs::{CgroupSock, CgroupSockAttachType}; /// use aya::programs::{CgroupSock, CgroupSockAttachType};
/// ///
/// let file = File::open("/sys/fs/cgroup/unified")?; /// let file = File::open("/sys/fs/cgroup/unified")?;
/// let bind: &mut CgroupSock = bpf.program_mut("bind").unwrap().try_into()?; /// let bind: &mut CgroupSock = bpf.programs.get_mut("bind").unwrap().try_into()?;
/// bind.load()?; /// bind.load(bpf.btf_fd.as_ref())?;
/// bind.attach(file)?; /// bind.attach(file)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
/// ``` /// ```
@ -62,9 +62,9 @@ pub struct CgroupSock {
impl CgroupSock { impl CgroupSock {
/// Loads the program inside the kernel. /// 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()); 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. /// Attaches the program to the given cgroup.

@ -5,7 +5,7 @@ pub use aya_obj::programs::CgroupSockAddrAttachType;
use crate::util::KernelVersion; use crate::util::KernelVersion;
use std::{ use std::{
hash::Hash, hash::Hash,
os::fd::{AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd, RawFd},
path::Path, path::Path,
}; };
@ -49,8 +49,8 @@ use crate::{
/// use aya::programs::{CgroupSockAddr, CgroupSockAddrAttachType}; /// use aya::programs::{CgroupSockAddr, CgroupSockAddrAttachType};
/// ///
/// let file = File::open("/sys/fs/cgroup/unified")?; /// let file = File::open("/sys/fs/cgroup/unified")?;
/// let egress: &mut CgroupSockAddr = bpf.program_mut("connect4").unwrap().try_into()?; /// let egress: &mut CgroupSockAddr = bpf.programs.get_mut("connect4").unwrap().try_into()?;
/// egress.load()?; /// egress.load(bpf.btf_fd.as_ref())?;
/// egress.attach(file)?; /// egress.attach(file)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
/// ``` /// ```
@ -63,9 +63,9 @@ pub struct CgroupSockAddr {
impl CgroupSockAddr { impl CgroupSockAddr {
/// Loads the program inside the kernel. /// 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()); 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. /// Attaches the program to the given cgroup.

@ -5,7 +5,7 @@ pub use aya_obj::programs::CgroupSockoptAttachType;
use crate::util::KernelVersion; use crate::util::KernelVersion;
use std::{ use std::{
hash::Hash, hash::Hash,
os::fd::{AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd, RawFd},
path::Path, path::Path,
}; };
@ -46,8 +46,8 @@ use crate::{
/// use aya::programs::CgroupSockopt; /// use aya::programs::CgroupSockopt;
/// ///
/// let file = File::open("/sys/fs/cgroup/unified")?; /// let file = File::open("/sys/fs/cgroup/unified")?;
/// let program: &mut CgroupSockopt = bpf.program_mut("cgroup_sockopt").unwrap().try_into()?; /// let program: &mut CgroupSockopt = bpf.programs.get_mut("cgroup_sockopt").unwrap().try_into()?;
/// program.load()?; /// program.load(bpf.btf_fd.as_ref())?;
/// program.attach(file)?; /// program.attach(file)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
/// ``` /// ```
@ -60,9 +60,9 @@ pub struct CgroupSockopt {
impl CgroupSockopt { impl CgroupSockopt {
/// Loads the program inside the kernel. /// 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()); 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. /// Attaches the program to the given cgroup.

@ -3,7 +3,7 @@
use crate::util::KernelVersion; use crate::util::KernelVersion;
use std::{ use std::{
hash::Hash, hash::Hash,
os::fd::{AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd, RawFd},
}; };
use crate::{ use crate::{
@ -42,8 +42,8 @@ use crate::{
/// use aya::programs::CgroupSysctl; /// use aya::programs::CgroupSysctl;
/// ///
/// let file = File::open("/sys/fs/cgroup/unified")?; /// let file = File::open("/sys/fs/cgroup/unified")?;
/// let program: &mut CgroupSysctl = bpf.program_mut("cgroup_sysctl").unwrap().try_into()?; /// let program: &mut CgroupSysctl = bpf.programs.get_mut("cgroup_sysctl").unwrap().try_into()?;
/// program.load()?; /// program.load(bpf.btf_fd.as_ref())?;
/// program.attach(file)?; /// program.attach(file)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
/// ``` /// ```
@ -55,8 +55,8 @@ pub struct CgroupSysctl {
impl CgroupSysctl { impl CgroupSysctl {
/// Loads the program inside the kernel. /// 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> {
load_program(BPF_PROG_TYPE_CGROUP_SYSCTL, &mut self.data) load_program(BPF_PROG_TYPE_CGROUP_SYSCTL, &mut self.data, btf_fd)
} }
/// Attaches the program to the given cgroup. /// Attaches the program to the given cgroup.

@ -1,5 +1,5 @@
//! Extension programs. //! Extension programs.
use std::os::fd::{AsRawFd, RawFd}; use std::os::fd::{AsFd, AsRawFd, RawFd};
use thiserror::Error; use thiserror::Error;
use object::Endianness; use object::Endianness;
@ -37,13 +37,13 @@ pub enum ExtensionError {
/// use aya::{BpfLoader, programs::{Xdp, XdpFlags, Extension}}; /// use aya::{BpfLoader, programs::{Xdp, XdpFlags, Extension}};
/// ///
/// let mut bpf = BpfLoader::new().extension("extension").load_file("app.o")?; /// let mut bpf = BpfLoader::new().extension("extension").load_file("app.o")?;
/// let prog: &mut Xdp = bpf.program_mut("main").unwrap().try_into()?; /// let prog: &mut Xdp = bpf.programs.get_mut("main").unwrap().try_into()?;
/// prog.load()?; /// prog.load(bpf.btf_fd.as_ref())?;
/// prog.attach("eth0", XdpFlags::default())?; /// prog.attach("eth0", XdpFlags::default())?;
/// ///
/// let prog_fd = prog.fd().unwrap(); /// let prog_fd = prog.fd().unwrap();
/// let ext: &mut Extension = bpf.program_mut("extension").unwrap().try_into()?; /// let ext: &mut Extension = bpf.programs.get_mut("extension").unwrap().try_into()?;
/// ext.load(prog_fd, "function_to_replace")?; /// ext.load(prog_fd, "function_to_replace", bpf.btf_fd.as_ref())?;
/// ext.attach()?; /// ext.attach()?;
/// Ok::<(), aya::BpfError>(()) /// Ok::<(), aya::BpfError>(())
/// ``` /// ```
@ -68,14 +68,19 @@ impl Extension {
/// The extension code will be loaded but inactive until it's attached. /// 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 /// There are no restrictions on what functions may be replaced, so you could replace
/// the main entry point of your program with an extension. /// 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 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_prog_fd = Some(target_prog_fd);
self.data.attach_btf_id = Some(btf_id); self.data.attach_btf_id = Some(prog_btf_id);
load_program(BPF_PROG_TYPE_EXT, &mut self.data) load_program(BPF_PROG_TYPE_EXT, &mut self.data, btf_fd)
} }
/// Attaches the extension. /// Attaches the extension.

@ -1,5 +1,7 @@
//! Fentry programs. //! Fentry programs.
use std::os::fd::AsFd;
use crate::{ use crate::{
generated::{bpf_attach_type::BPF_TRACE_FENTRY, bpf_prog_type::BPF_PROG_TYPE_TRACING}, generated::{bpf_attach_type::BPF_TRACE_FENTRY, bpf_prog_type::BPF_PROG_TYPE_TRACING},
obj::btf::{Btf, BtfKind}, obj::btf::{Btf, BtfKind},
@ -37,8 +39,8 @@ use crate::{
/// use aya::{Bpf, programs::FEntry, BtfError, Btf}; /// use aya::{Bpf, programs::FEntry, BtfError, Btf};
/// ///
/// let btf = Btf::from_sys_fs()?; /// let btf = Btf::from_sys_fs()?;
/// let program: &mut FEntry = bpf.program_mut("filename_lookup").unwrap().try_into()?; /// let program: &mut FEntry = bpf.programs.get_mut("filename_lookup").unwrap().try_into()?;
/// program.load("filename_lookup", &btf)?; /// program.load("filename_lookup", &btf, bpf.btf_fd.as_ref())?;
/// program.attach()?; /// program.attach()?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
/// ``` /// ```
@ -55,10 +57,15 @@ impl FEntry {
/// Loads the program so it's executed when the kernel function `fn_name` /// 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 /// is entered. The `btf` argument must contain the BTF info for the
/// running kernel. /// 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.expected_attach_type = Some(BPF_TRACE_FENTRY);
self.data.attach_btf_id = Some(btf.id_by_type_name_kind(fn_name, BtfKind::Func)?); 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. /// Attaches the program.

@ -1,5 +1,7 @@
//! Fexit programs. //! Fexit programs.
use std::os::fd::AsFd;
use crate::{ use crate::{
generated::{bpf_attach_type::BPF_TRACE_FEXIT, bpf_prog_type::BPF_PROG_TYPE_TRACING}, generated::{bpf_attach_type::BPF_TRACE_FEXIT, bpf_prog_type::BPF_PROG_TYPE_TRACING},
obj::btf::{Btf, BtfKind}, obj::btf::{Btf, BtfKind},
@ -37,8 +39,8 @@ use crate::{
/// use aya::{Bpf, programs::FExit, BtfError, Btf}; /// use aya::{Bpf, programs::FExit, BtfError, Btf};
/// ///
/// let btf = Btf::from_sys_fs()?; /// let btf = Btf::from_sys_fs()?;
/// let program: &mut FExit = bpf.program_mut("filename_lookup").unwrap().try_into()?; /// let program: &mut FExit = bpf.programs.get_mut("filename_lookup").unwrap().try_into()?;
/// program.load("filename_lookup", &btf)?; /// program.load("filename_lookup", &btf, bpf.btf_fd.as_ref())?;
/// program.attach()?; /// program.attach()?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
/// ``` /// ```
@ -55,10 +57,15 @@ impl FExit {
/// Loads the program so it's executed when the kernel function `fn_name` /// 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 /// is exited. The `btf` argument must contain the BTF info for the running
/// kernel. /// 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.expected_attach_type = Some(BPF_TRACE_FEXIT);
self.data.attach_btf_id = Some(btf.id_by_type_name_kind(fn_name, BtfKind::Func)?); 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. /// Attaches the program.

@ -1,5 +1,5 @@
//! Kernel space probes. //! Kernel space probes.
use std::{io, path::Path}; use std::{io, os::fd::AsFd, path::Path};
use thiserror::Error; use thiserror::Error;
use crate::{ use crate::{
@ -32,8 +32,8 @@ use crate::{
/// # let mut bpf = Bpf::load_file("ebpf_programs.o")?; /// # let mut bpf = Bpf::load_file("ebpf_programs.o")?;
/// use aya::{Bpf, programs::KProbe}; /// use aya::{Bpf, programs::KProbe};
/// ///
/// let program: &mut KProbe = bpf.program_mut("intercept_wakeups").unwrap().try_into()?; /// let program: &mut KProbe = bpf.programs.get_mut("intercept_wakeups").unwrap().try_into()?;
/// program.load()?; /// program.load(bpf.btf_fd.as_ref())?;
/// program.attach("try_to_wake_up", 0)?; /// program.attach("try_to_wake_up", 0)?;
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
/// ``` /// ```
@ -46,8 +46,8 @@ pub struct KProbe {
impl KProbe { impl KProbe {
/// Loads the program inside the kernel. /// 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> {
load_program(BPF_PROG_TYPE_KPROBE, &mut self.data) load_program(BPF_PROG_TYPE_KPROBE, &mut self.data, btf_fd)
} }
/// Returns `KProbe` if the program is a `kprobe`, or `KRetProbe` if the /// Returns `KProbe` if the program is a `kprobe`, or `KRetProbe` if the

@ -97,8 +97,8 @@ pub struct FdLinkId(pub(crate) RawFd);
/// # let mut bpf = Bpf::load_file("ebpf_programs.o")?; /// # let mut bpf = Bpf::load_file("ebpf_programs.o")?;
/// use aya::{Bpf, programs::{links::FdLink, KProbe}}; /// use aya::{Bpf, programs::{links::FdLink, KProbe}};
/// ///
/// let program: &mut KProbe = bpf.program_mut("intercept_wakeups").unwrap().try_into()?; /// let program: &mut KProbe = bpf.programs.get_mut("intercept_wakeups").unwrap().try_into()?;
/// program.load()?; /// program.load(bpf.btf_fd.as_ref())?;
/// let link_id = program.attach("try_to_wake_up", 0)?; /// let link_id = program.attach("try_to_wake_up", 0)?;
/// let link = program.take_link(link_id).unwrap(); /// let link = program.take_link(link_id).unwrap();
/// let fd_link: FdLink = link.try_into().unwrap(); /// let fd_link: FdLink = link.try_into().unwrap();

@ -1,5 +1,5 @@
//! Lirc programs. //! Lirc programs.
use std::os::fd::{AsRawFd, RawFd}; use std::os::fd::{AsFd, AsRawFd, RawFd};
use crate::{ use crate::{
generated::{bpf_attach_type::BPF_LIRC_MODE2, bpf_prog_type::BPF_PROG_TYPE_LIRC_MODE2}, 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 file = File::open("/dev/lirc0")?;
/// let mut bpf = aya::Bpf::load_file("imon_rsc.o")?; /// let mut bpf = aya::Bpf::load_file("imon_rsc.o")?;
/// let decoder: &mut LircMode2 = bpf.program_mut("imon_rsc").unwrap().try_into().unwrap(); /// let decoder: &mut LircMode2 = bpf.programs.get_mut("imon_rsc").unwrap().try_into().unwrap();
/// decoder.load()?; /// decoder.load(bpf.btf_fd.as_ref())?;
/// decoder.attach(file)?; /// decoder.attach(file)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
/// ``` /// ```
@ -53,8 +53,8 @@ pub struct LircMode2 {
impl LircMode2 { impl LircMode2 {
/// Loads the program inside the kernel. /// 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> {
load_program(BPF_PROG_TYPE_LIRC_MODE2, &mut self.data) load_program(BPF_PROG_TYPE_LIRC_MODE2, &mut self.data, btf_fd)
} }
/// Attaches the program to the given lirc device. /// Attaches the program to the given lirc device.

@ -1,5 +1,7 @@
//! LSM probes. //! LSM probes.
use std::os::fd::AsFd;
use crate::{ use crate::{
generated::{bpf_attach_type::BPF_LSM_MAC, bpf_prog_type::BPF_PROG_TYPE_LSM}, generated::{bpf_attach_type::BPF_LSM_MAC, bpf_prog_type::BPF_PROG_TYPE_LSM},
obj::btf::{Btf, BtfKind}, obj::btf::{Btf, BtfKind},
@ -39,8 +41,8 @@ use crate::{
/// use aya::{Bpf, programs::Lsm, BtfError, Btf}; /// use aya::{Bpf, programs::Lsm, BtfError, Btf};
/// ///
/// let btf = Btf::from_sys_fs()?; /// let btf = Btf::from_sys_fs()?;
/// let program: &mut Lsm = bpf.program_mut("lsm_prog").unwrap().try_into()?; /// let program: &mut Lsm = bpf.programs.get_mut("lsm_prog").unwrap().try_into()?;
/// program.load("security_bprm_exec", &btf)?; /// program.load("security_bprm_exec", &btf, bpf.btf_fd.as_ref())?;
/// program.attach()?; /// program.attach()?;
/// # Ok::<(), LsmError>(()) /// # Ok::<(), LsmError>(())
/// ``` /// ```
@ -59,12 +61,17 @@ impl Lsm {
/// ///
/// * `lsm_hook_name` - full name of the LSM hook that the program should /// * `lsm_hook_name` - full name of the LSM hook that the program should
/// be attached to /// 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); self.data.expected_attach_type = Some(BPF_LSM_MAC);
let type_name = format!("bpf_lsm_{lsm_hook_name}"); let type_name = format!("bpf_lsm_{lsm_hook_name}");
self.data.attach_btf_id = self.data.attach_btf_id =
Some(btf.id_by_type_name_kind(type_name.as_str(), BtfKind::Func)?); 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. /// Attaches the program.

@ -18,8 +18,8 @@
//! //!
//! let mut bpf = Bpf::load_file("ebpf_programs.o")?; //! let mut bpf = Bpf::load_file("ebpf_programs.o")?;
//! // intercept_wakeups is the name of the program we want to load //! // intercept_wakeups is the name of the program we want to load
//! let program: &mut KProbe = bpf.program_mut("intercept_wakeups").unwrap().try_into()?; //! let program: &mut KProbe = bpf.programs.get_mut("intercept_wakeups").unwrap().try_into()?;
//! program.load()?; //! program.load(bpf.btf_fd.as_ref())?;
//! // intercept_wakeups will be called every time try_to_wake_up() is called //! // intercept_wakeups will be called every time try_to_wake_up() is called
//! // inside the kernel //! // inside the kernel
//! program.attach("try_to_wake_up", 0)?; //! program.attach("try_to_wake_up", 0)?;
@ -69,7 +69,7 @@ use libc::ENOSPC;
use std::{ use std::{
ffi::CString, ffi::CString,
io, io,
os::fd::{AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd, RawFd},
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use thiserror::Error; 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_obj_fd: Option<u32>,
pub(crate) attach_btf_id: Option<u32>, pub(crate) attach_btf_id: Option<u32>,
pub(crate) attach_prog_fd: Option<RawFd>, pub(crate) attach_prog_fd: Option<RawFd>,
pub(crate) btf_fd: Option<RawFd>,
pub(crate) verifier_log_level: VerifierLogLevel, pub(crate) verifier_log_level: VerifierLogLevel,
pub(crate) path: Option<PathBuf>, pub(crate) path: Option<PathBuf>,
pub(crate) flags: u32, pub(crate) flags: u32,
@ -423,7 +422,6 @@ impl<T: Link> ProgramData<T> {
pub(crate) fn new( pub(crate) fn new(
name: Option<String>, name: Option<String>,
obj: (obj::Program, obj::Function), obj: (obj::Program, obj::Function),
btf_fd: Option<RawFd>,
verifier_log_level: VerifierLogLevel, verifier_log_level: VerifierLogLevel,
) -> ProgramData<T> { ) -> ProgramData<T> {
ProgramData { ProgramData {
@ -435,7 +433,6 @@ impl<T: Link> ProgramData<T> {
attach_btf_obj_fd: None, attach_btf_obj_fd: None,
attach_btf_id: None, attach_btf_id: None,
attach_prog_fd: None, attach_prog_fd: None,
btf_fd,
verifier_log_level, verifier_log_level,
path: None, path: None,
flags: 0, flags: 0,
@ -475,7 +472,6 @@ impl<T: Link> ProgramData<T> {
attach_btf_obj_fd, attach_btf_obj_fd,
attach_btf_id, attach_btf_id,
attach_prog_fd: None, attach_prog_fd: None,
btf_fd: None,
verifier_log_level, verifier_log_level,
path: Some(path.to_path_buf()), path: Some(path.to_path_buf()),
flags: 0, 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>( fn load_program<T: Link>(
prog_type: bpf_prog_type, prog_type: bpf_prog_type,
data: &mut ProgramData<T>, data: &mut ProgramData<T>,
btf_fd: Option<impl AsFd>,
) -> Result<(), ProgramError> { ) -> Result<(), ProgramError> {
let ProgramData { let ProgramData {
name, name,
@ -556,7 +553,6 @@ fn load_program<T: Link>(
attach_btf_obj_fd, attach_btf_obj_fd,
attach_btf_id, attach_btf_id,
attach_prog_fd, attach_prog_fd,
btf_fd,
verifier_log_level, verifier_log_level,
path: _, path: _,
flags, flags,
@ -613,7 +609,7 @@ fn load_program<T: Link>(
license, license,
kernel_version: target_kernel_version, kernel_version: target_kernel_version,
expected_attach_type: *expected_attach_type, 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_obj_fd: *attach_btf_obj_fd,
attach_btf_id: *attach_btf_id, attach_btf_id: *attach_btf_id,
attach_prog_fd: *attach_prog_fd, attach_prog_fd: *attach_prog_fd,

@ -1,5 +1,7 @@
//! Perf event programs. //! Perf event programs.
use std::os::fd::AsFd;
pub use crate::generated::{ 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, 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, /// 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 prog: &mut PerfEvent = bpf.programs.get_mut("observe_cpu_clock").unwrap().try_into()?;
/// prog.load()?; /// prog.load(bpf.btf_fd.as_ref())?;
/// ///
/// for cpu in online_cpus()? { /// for cpu in online_cpus()? {
/// prog.attach( /// prog.attach(
@ -126,8 +128,8 @@ pub struct PerfEvent {
impl PerfEvent { impl PerfEvent {
/// Loads the program inside the kernel. /// 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> {
load_program(BPF_PROG_TYPE_PERF_EVENT, &mut self.data) load_program(BPF_PROG_TYPE_PERF_EVENT, &mut self.data, btf_fd)
} }
/// Attaches to the given perf event. /// Attaches to the given perf event.

@ -1,5 +1,5 @@
//! Raw tracepoints. //! Raw tracepoints.
use std::ffi::CString; use std::{ffi::CString, os::fd::AsFd};
use crate::{ use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_RAW_TRACEPOINT, generated::bpf_prog_type::BPF_PROG_TYPE_RAW_TRACEPOINT,
@ -27,8 +27,8 @@ use crate::{
/// # let mut bpf = Bpf::load_file("ebpf_programs.o")?; /// # let mut bpf = Bpf::load_file("ebpf_programs.o")?;
/// use aya::{Bpf, programs::RawTracePoint}; /// use aya::{Bpf, programs::RawTracePoint};
/// ///
/// let program: &mut RawTracePoint = bpf.program_mut("sys_enter").unwrap().try_into()?; /// let program: &mut RawTracePoint = bpf.programs.get_mut("sys_enter").unwrap().try_into()?;
/// program.load()?; /// program.load(bpf.btf_fd.as_ref())?;
/// program.attach("sys_enter")?; /// program.attach("sys_enter")?;
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
/// ``` /// ```
@ -40,8 +40,8 @@ pub struct RawTracePoint {
impl RawTracePoint { impl RawTracePoint {
/// Loads the program inside the kernel. /// 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> {
load_program(BPF_PROG_TYPE_RAW_TRACEPOINT, &mut self.data) load_program(BPF_PROG_TYPE_RAW_TRACEPOINT, &mut self.data, btf_fd)
} }
/// Attaches the program to the given tracepoint. /// Attaches the program to the given tracepoint.

@ -1,4 +1,4 @@
use std::os::fd::{AsRawFd, RawFd}; use std::os::fd::{AsFd, AsRawFd, RawFd};
use crate::{ use crate::{
generated::{bpf_attach_type::BPF_SK_LOOKUP, bpf_prog_type::BPF_PROG_TYPE_SK_LOOKUP}, 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; /// use aya::programs::SkLookup;
/// ///
/// let file = File::open("/var/run/netns/test")?; /// let file = File::open("/var/run/netns/test")?;
/// let program: &mut SkLookup = bpf.program_mut("sk_lookup").unwrap().try_into()?; /// let program: &mut SkLookup = bpf.programs.get_mut("sk_lookup").unwrap().try_into()?;
/// program.load()?; /// program.load(bpf.btf_fd.as_ref())?;
/// program.attach(file)?; /// program.attach(file)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
/// ``` /// ```
@ -52,9 +52,9 @@ pub struct SkLookup {
impl SkLookup { impl SkLookup {
/// Loads the program inside the kernel. /// 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); 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. /// Attaches the program to the given network namespace.

@ -1,6 +1,6 @@
//! Skmsg programs. //! Skmsg programs.
use std::os::fd::AsRawFd; use std::os::fd::{AsFd, AsRawFd};
use crate::{ use crate::{
generated::{bpf_attach_type::BPF_SK_MSG_VERDICT, bpf_prog_type::BPF_PROG_TYPE_SK_MSG}, 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 intercept_egress: SockHash<_, u32> = bpf.map("INTERCEPT_EGRESS").unwrap().try_into()?;
/// let map_fd = intercept_egress.fd()?; /// let map_fd = intercept_egress.fd()?;
/// ///
/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; /// let prog: &mut SkMsg = bpf.programs.get_mut("intercept_egress_packet").unwrap().try_into()?;
/// prog.load()?; /// prog.load(bpf.btf_fd.as_ref())?;
/// prog.attach(map_fd)?; /// prog.attach(map_fd)?;
/// ///
/// let mut client = TcpStream::connect("127.0.0.1:1234")?; /// let mut client = TcpStream::connect("127.0.0.1:1234")?;
@ -71,8 +71,8 @@ pub struct SkMsg {
impl SkMsg { impl SkMsg {
/// Loads the program inside the kernel. /// 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> {
load_program(BPF_PROG_TYPE_SK_MSG, &mut self.data) load_program(BPF_PROG_TYPE_SK_MSG, &mut self.data, btf_fd)
} }
/// Attaches the program to the given sockmap. /// Attaches the program to the given sockmap.

@ -1,6 +1,9 @@
//! Skskb programs. //! Skskb programs.
use std::{os::fd::AsRawFd, path::Path}; use std::{
os::fd::{AsFd, AsRawFd},
path::Path,
};
use crate::{ use crate::{
generated::{ generated::{
@ -45,8 +48,8 @@ pub enum SkSkbKind {
/// let intercept_ingress: SockMap<_> = bpf.map("INTERCEPT_INGRESS").unwrap().try_into()?; /// let intercept_ingress: SockMap<_> = bpf.map("INTERCEPT_INGRESS").unwrap().try_into()?;
/// let map_fd = intercept_ingress.fd()?; /// let map_fd = intercept_ingress.fd()?;
/// ///
/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?; /// let prog: &mut SkSkb = bpf.programs.get_mut("intercept_ingress_packet").unwrap().try_into()?;
/// prog.load()?; /// prog.load(bpf.btf_fd.as_ref())?;
/// prog.attach(map_fd)?; /// prog.attach(map_fd)?;
/// ///
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
@ -64,8 +67,8 @@ pub struct SkSkb {
impl SkSkb { impl SkSkb {
/// Loads the program inside the kernel. /// 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> {
load_program(BPF_PROG_TYPE_SK_SKB, &mut self.data) load_program(BPF_PROG_TYPE_SK_SKB, &mut self.data, btf_fd)
} }
/// Attaches the program to the given socket map. /// Attaches the program to the given socket map.

@ -1,5 +1,5 @@
//! Socket option programs. //! Socket option programs.
use std::os::fd::AsRawFd; use std::os::fd::{AsFd, AsRawFd};
use crate::{ use crate::{
generated::{bpf_attach_type::BPF_CGROUP_SOCK_OPS, bpf_prog_type::BPF_PROG_TYPE_SOCK_OPS}, 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; /// use aya::programs::SockOps;
/// ///
/// let file = File::open("/sys/fs/cgroup/unified")?; /// let file = File::open("/sys/fs/cgroup/unified")?;
/// let prog: &mut SockOps = bpf.program_mut("intercept_active_sockets").unwrap().try_into()?; /// let prog: &mut SockOps = bpf.programs.get_mut("intercept_active_sockets").unwrap().try_into()?;
/// prog.load()?; /// prog.load(bpf.btf_fd.as_ref())?;
/// prog.attach(file)?; /// prog.attach(file)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
#[derive(Debug)] #[derive(Debug)]
@ -51,8 +51,8 @@ pub struct SockOps {
impl SockOps { impl SockOps {
/// Loads the program inside the kernel. /// 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> {
load_program(BPF_PROG_TYPE_SOCK_OPS, &mut self.data) load_program(BPF_PROG_TYPE_SOCK_OPS, &mut self.data, btf_fd)
} }
/// Attaches the program to the given cgroup. /// Attaches the program to the given cgroup.

@ -2,7 +2,7 @@
use libc::{setsockopt, SOL_SOCKET}; use libc::{setsockopt, SOL_SOCKET};
use std::{ use std::{
io, mem, io, mem,
os::fd::{AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd, RawFd},
}; };
use thiserror::Error; use thiserror::Error;
@ -52,8 +52,8 @@ pub enum SocketFilterError {
/// use aya::programs::SocketFilter; /// use aya::programs::SocketFilter;
/// ///
/// let mut client = TcpStream::connect("127.0.0.1:1234")?; /// let mut client = TcpStream::connect("127.0.0.1:1234")?;
/// let prog: &mut SocketFilter = bpf.program_mut("filter_packets").unwrap().try_into()?; /// let prog: &mut SocketFilter = bpf.programs.get_mut("filter_packets").unwrap().try_into()?;
/// prog.load()?; /// prog.load(bpf.btf_fd.as_ref())?;
/// prog.attach(client.as_raw_fd())?; /// prog.attach(client.as_raw_fd())?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
/// ``` /// ```
@ -65,8 +65,8 @@ pub struct SocketFilter {
impl SocketFilter { impl SocketFilter {
/// Loads the program inside the kernel. /// 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> {
load_program(BPF_PROG_TYPE_SOCKET_FILTER, &mut self.data) load_program(BPF_PROG_TYPE_SOCKET_FILTER, &mut self.data, btf_fd)
} }
/// Attaches the filter on the given socket. /// Attaches the filter on the given socket.

@ -4,6 +4,7 @@ use thiserror::Error;
use std::{ use std::{
ffi::{CStr, CString}, ffi::{CStr, CString},
io, io,
os::fd::AsFd,
path::Path, path::Path,
}; };
@ -63,8 +64,8 @@ pub enum TcAttachType {
/// // attached /// // attached
/// tc::qdisc_add_clsact("eth0")?; /// tc::qdisc_add_clsact("eth0")?;
/// ///
/// let prog: &mut SchedClassifier = bpf.program_mut("redirect_ingress").unwrap().try_into()?; /// let prog: &mut SchedClassifier = bpf.programs.get_mut("redirect_ingress").unwrap().try_into()?;
/// prog.load()?; /// prog.load(bpf.btf_fd.as_ref())?;
/// prog.attach("eth0", TcAttachType::Ingress)?; /// prog.attach("eth0", TcAttachType::Ingress)?;
/// ///
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
@ -114,8 +115,8 @@ pub struct TcOptions {
impl SchedClassifier { impl SchedClassifier {
/// Loads the program inside the kernel. /// 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> {
load_program(BPF_PROG_TYPE_SCHED_CLS, &mut self.data) load_program(BPF_PROG_TYPE_SCHED_CLS, &mut self.data, btf_fd)
} }
/// Attaches the program to the given `interface` using the default options. /// Attaches the program to the given `interface` using the default options.

@ -1,5 +1,7 @@
//! BTF-enabled raw tracepoints. //! BTF-enabled raw tracepoints.
use std::os::fd::AsFd;
use crate::{ use crate::{
generated::{bpf_attach_type::BPF_TRACE_RAW_TP, bpf_prog_type::BPF_PROG_TYPE_TRACING}, generated::{bpf_attach_type::BPF_TRACE_RAW_TP, bpf_prog_type::BPF_PROG_TYPE_TRACING},
obj::btf::{Btf, BtfKind}, obj::btf::{Btf, BtfKind},
@ -36,8 +38,8 @@ use crate::{
/// use aya::{Bpf, programs::BtfTracePoint, BtfError, Btf}; /// use aya::{Bpf, programs::BtfTracePoint, BtfError, Btf};
/// ///
/// let btf = Btf::from_sys_fs()?; /// let btf = Btf::from_sys_fs()?;
/// let program: &mut BtfTracePoint = bpf.program_mut("sched_process_fork").unwrap().try_into()?; /// let program: &mut BtfTracePoint = bpf.programs.get_mut("sched_process_fork").unwrap().try_into()?;
/// program.load("sched_process_fork", &btf)?; /// program.load("sched_process_fork", &btf, bpf.btf_fd.as_ref())?;
/// program.attach()?; /// program.attach()?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
/// ``` /// ```
@ -57,12 +59,17 @@ impl BtfTracePoint {
/// ///
/// * `tracepoint` - full name of the tracepoint that we should attach to /// * `tracepoint` - full name of the tracepoint that we should attach to
/// * `btf` - btf information for the target system /// * `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); self.data.expected_attach_type = Some(BPF_TRACE_RAW_TP);
let type_name = format!("btf_trace_{tracepoint}"); let type_name = format!("btf_trace_{tracepoint}");
self.data.attach_btf_id = self.data.attach_btf_id =
Some(btf.id_by_type_name_kind(type_name.as_str(), BtfKind::Typedef)?); 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. /// Attaches the program.

@ -1,5 +1,5 @@
//! Tracepoint programs. //! Tracepoint programs.
use std::{fs, io, path::Path}; use std::{fs, io, os::fd::AsFd, path::Path};
use thiserror::Error; use thiserror::Error;
use crate::{ use crate::{
@ -54,8 +54,8 @@ pub enum TracePointError {
/// # let mut bpf = aya::Bpf::load(&[])?; /// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::programs::TracePoint; /// use aya::programs::TracePoint;
/// ///
/// let prog: &mut TracePoint = bpf.program_mut("trace_context_switch").unwrap().try_into()?; /// let prog: &mut TracePoint = bpf.programs.get_mut("trace_context_switch").unwrap().try_into()?;
/// prog.load()?; /// prog.load(bpf.btf_fd.as_ref())?;
/// prog.attach("sched", "sched_switch")?; /// prog.attach("sched", "sched_switch")?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
/// ``` /// ```
@ -67,8 +67,8 @@ pub struct TracePoint {
impl TracePoint { impl TracePoint {
/// Loads the program inside the kernel. /// 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> {
load_program(BPF_PROG_TYPE_TRACEPOINT, &mut self.data) load_program(BPF_PROG_TYPE_TRACEPOINT, &mut self.data, btf_fd)
} }
/// Attaches to a given trace point. /// Attaches to a given trace point.

@ -7,7 +7,7 @@ use std::{
fs, fs,
io::{self, BufRead, Cursor, Read}, io::{self, BufRead, Cursor, Read},
mem, mem,
os::raw::c_char, os::{fd::AsFd, raw::c_char},
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::Arc, sync::Arc,
}; };
@ -50,8 +50,8 @@ pub struct UProbe {
impl UProbe { impl UProbe {
/// Loads the program inside the kernel. /// 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> {
load_program(BPF_PROG_TYPE_KPROBE, &mut self.data) load_program(BPF_PROG_TYPE_KPROBE, &mut self.data, btf_fd)
} }
/// Returns `UProbe` if the program is a `uprobe`, or `URetProbe` if the /// Returns `UProbe` if the program is a `uprobe`, or `URetProbe` if the

@ -3,7 +3,13 @@
use crate::util::KernelVersion; use crate::util::KernelVersion;
use bitflags; use bitflags;
use libc::if_nametoindex; 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 thiserror::Error;
use crate::{ use crate::{
@ -78,9 +84,9 @@ pub struct Xdp {
impl Xdp { impl Xdp {
/// Loads the program inside the kernel. /// 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); 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`. /// Attaches the program to the given `interface`.

@ -3,7 +3,7 @@ use std::{
ffi::{CStr, CString}, ffi::{CStr, CString},
io, io,
mem::{self, MaybeUninit}, mem::{self, MaybeUninit},
os::fd::RawFd, os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd},
slice, slice,
}; };
@ -35,7 +35,7 @@ use crate::{
pub(crate) fn bpf_create_map( pub(crate) fn bpf_create_map(
name: &CStr, name: &CStr,
def: &obj::Map, def: &obj::Map,
btf_fd: Option<RawFd>, btf_fd: Option<impl AsFd>,
kernel_version: KernelVersion, kernel_version: KernelVersion,
) -> SysResult<c_long> { ) -> SysResult<c_long> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; 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_key_type_id = m.def.btf_key_type_id;
u.btf_value_type_id = m.def.btf_value_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) license: &'a CStr,
pub(crate) kernel_version: u32, pub(crate) kernel_version: u32,
pub(crate) expected_attach_type: Option<bpf_attach_type>, 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_obj_fd: Option<u32>,
pub(crate) attach_btf_id: Option<u32>, pub(crate) attach_btf_id: Option<u32>,
pub(crate) attach_prog_fd: Option<RawFd>, 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(); let func_info_buf = aya_attr.func_info.func_info_bytes();
if let Some(btf_fd) = aya_attr.prog_btf_fd { 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 { if aya_attr.line_info_rec_size > 0 {
u.line_info = line_info_buf.as_ptr() as *const _ as u64; u.line_info = line_info_buf.as_ptr() as *const _ as u64;
u.line_info_cnt = aya_attr.line_info.len() as u32; u.line_info_cnt = aya_attr.line_info.len() as u32;
@ -551,7 +551,7 @@ pub(crate) fn bpf_load_btf(
raw_btf: &[u8], raw_btf: &[u8],
log_buf: &mut [u8], log_buf: &mut [u8],
verifier_log_level: VerifierLogLevel, verifier_log_level: VerifierLogLevel,
) -> SysResult<c_long> { ) -> SysResult<OwnedFd> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_7 }; let u = unsafe { &mut attr.__bindgen_anon_7 };
u.btf = raw_btf.as_ptr() as *const _ as u64; 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_buf = log_buf.as_mut_ptr() as u64;
u.btf_log_size = log_buf.len() as u32; 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> { 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, fd: None,
pinned: false, 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; insns[0].imm = map_fd;
let gpl = b"GPL\0"; let gpl = b"GPL\0";

@ -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 { fn load_and_attach_uprobe(prog_name: &str, func_name: &str, bytes: &[u8]) -> Bpf {
let mut bpf = Bpf::load(bytes).unwrap(); let mut bpf = Bpf::load(bytes).unwrap();
let prog: &mut UProbe = bpf.program_mut(prog_name).unwrap().try_into().unwrap(); let prog: &mut UProbe = bpf.programs.get_mut(prog_name).unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load(bpf.btf_fd.as_ref()).unwrap();
prog.attach(Some(func_name), 0, "/proc/self/exe", None) prog.attach(Some(func_name), 0, "/proc/self/exe", None)
.unwrap(); .unwrap();

@ -385,11 +385,14 @@ impl RelocationTestRunner {
} }
let mut bpf = loader.load(&self.ebpf).context("Loading eBPF failed")?; let mut bpf = loader.load(&self.ebpf).context("Loading eBPF failed")?;
let program: &mut TracePoint = bpf let program: &mut TracePoint = bpf
.program_mut("bpf_prog") .programs
.get_mut("bpf_prog")
.context("bpf_prog not found")? .context("bpf_prog not found")?
.try_into() .try_into()
.context("program not a tracepoint")?; .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 // Attach to sched_switch and wait some time to make sure it executed at least once
program program
.attach("sched", "sched_switch") .attach("sched", "sched_switch")

@ -17,11 +17,12 @@ const RETRY_DURATION_MS: u64 = 10;
fn long_name() { fn long_name() {
let mut bpf = Bpf::load(crate::NAME_TEST).unwrap(); let mut bpf = Bpf::load(crate::NAME_TEST).unwrap();
let name_prog: &mut Xdp = bpf let name_prog: &mut Xdp = bpf
.program_mut("ihaveaverylongname") .programs
.get_mut("ihaveaverylongname")
.unwrap() .unwrap()
.try_into() .try_into()
.unwrap(); .unwrap();
name_prog.load().unwrap(); name_prog.load(bpf.btf_fd.as_ref()).unwrap();
name_prog.attach("lo", XdpFlags::default()).unwrap(); name_prog.attach("lo", XdpFlags::default()).unwrap();
// We used to be able to assert with bpftool that the program name was short. // 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_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 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 prog: &mut TracePoint = bpf
prog.load().unwrap(); .programs
.get_mut("tracepoint")
.unwrap()
.try_into()
.unwrap();
prog.load(bpf.btf_fd.as_ref()).unwrap();
prog.attach("sched", "sched_switch").unwrap(); prog.attach("sched", "sched_switch").unwrap();
thread::sleep(time::Duration::from_secs(3)); thread::sleep(time::Duration::from_secs(3));
@ -110,8 +116,13 @@ macro_rules! assert_loaded {
#[test] #[test]
fn unload_xdp() { fn unload_xdp() {
let mut bpf = Bpf::load(crate::TEST).unwrap(); let mut bpf = Bpf::load(crate::TEST).unwrap();
let prog: &mut Xdp = bpf.program_mut("test_xdp").unwrap().try_into().unwrap(); let prog: &mut Xdp = bpf
prog.load().unwrap(); .programs
.get_mut("test_xdp")
.unwrap()
.try_into()
.unwrap();
prog.load(bpf.btf_fd.as_ref()).unwrap();
assert_loaded!("test_xdp", true); assert_loaded!("test_xdp", true);
let link = prog.attach("lo", XdpFlags::default()).unwrap(); let link = prog.attach("lo", XdpFlags::default()).unwrap();
{ {
@ -121,7 +132,7 @@ fn unload_xdp() {
}; };
assert_loaded!("test_xdp", false); assert_loaded!("test_xdp", false);
prog.load().unwrap(); prog.load(bpf.btf_fd.as_ref()).unwrap();
assert_loaded!("test_xdp", true); assert_loaded!("test_xdp", true);
prog.attach("lo", XdpFlags::default()).unwrap(); prog.attach("lo", XdpFlags::default()).unwrap();
@ -135,8 +146,13 @@ fn unload_xdp() {
#[test] #[test]
fn unload_kprobe() { fn unload_kprobe() {
let mut bpf = Bpf::load(crate::TEST).unwrap(); let mut bpf = Bpf::load(crate::TEST).unwrap();
let prog: &mut KProbe = bpf.program_mut("test_kprobe").unwrap().try_into().unwrap(); let prog: &mut KProbe = bpf
prog.load().unwrap(); .programs
.get_mut("test_kprobe")
.unwrap()
.try_into()
.unwrap();
prog.load(bpf.btf_fd.as_ref()).unwrap();
assert_loaded!("test_kprobe", true); assert_loaded!("test_kprobe", true);
let link = prog.attach("try_to_wake_up", 0).unwrap(); let link = prog.attach("try_to_wake_up", 0).unwrap();
{ {
@ -146,7 +162,7 @@ fn unload_kprobe() {
}; };
assert_loaded!("test_kprobe", false); assert_loaded!("test_kprobe", false);
prog.load().unwrap(); prog.load(bpf.btf_fd.as_ref()).unwrap();
assert_loaded!("test_kprobe", true); assert_loaded!("test_kprobe", true);
prog.attach("try_to_wake_up", 0).unwrap(); prog.attach("try_to_wake_up", 0).unwrap();
@ -161,12 +177,13 @@ fn unload_kprobe() {
fn basic_tracepoint() { fn basic_tracepoint() {
let mut bpf = Bpf::load(crate::TEST).unwrap(); let mut bpf = Bpf::load(crate::TEST).unwrap();
let prog: &mut TracePoint = bpf let prog: &mut TracePoint = bpf
.program_mut("test_tracepoint") .programs
.get_mut("test_tracepoint")
.unwrap() .unwrap()
.try_into() .try_into()
.unwrap(); .unwrap();
prog.load().unwrap(); prog.load(bpf.btf_fd.as_ref()).unwrap();
assert_loaded!("test_tracepoint", true); assert_loaded!("test_tracepoint", true);
let link = prog.attach("syscalls", "sys_enter_kill").unwrap(); let link = prog.attach("syscalls", "sys_enter_kill").unwrap();
@ -177,7 +194,7 @@ fn basic_tracepoint() {
}; };
assert_loaded!("test_tracepoint", false); assert_loaded!("test_tracepoint", false);
prog.load().unwrap(); prog.load(bpf.btf_fd.as_ref()).unwrap();
assert_loaded!("test_tracepoint", true); assert_loaded!("test_tracepoint", true);
prog.attach("syscalls", "sys_enter_kill").unwrap(); prog.attach("syscalls", "sys_enter_kill").unwrap();
@ -191,9 +208,14 @@ fn basic_tracepoint() {
#[test] #[test]
fn basic_uprobe() { fn basic_uprobe() {
let mut bpf = Bpf::load(crate::TEST).unwrap(); 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); assert_loaded!("test_uprobe", true);
let link = prog.attach(Some("sleep"), 0, "libc", None).unwrap(); let link = prog.attach(Some("sleep"), 0, "libc", None).unwrap();
@ -204,7 +226,7 @@ fn basic_uprobe() {
}; };
assert_loaded!("test_uprobe", false); assert_loaded!("test_uprobe", false);
prog.load().unwrap(); prog.load(bpf.btf_fd.as_ref()).unwrap();
assert_loaded!("test_uprobe", true); assert_loaded!("test_uprobe", true);
prog.attach(Some("sleep"), 0, "libc", None).unwrap(); prog.attach(Some("sleep"), 0, "libc", None).unwrap();
@ -224,8 +246,13 @@ fn pin_link() {
} }
let mut bpf = Bpf::load(crate::TEST).unwrap(); let mut bpf = Bpf::load(crate::TEST).unwrap();
let prog: &mut Xdp = bpf.program_mut("test_xdp").unwrap().try_into().unwrap(); let prog: &mut Xdp = bpf
prog.load().unwrap(); .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_id = prog.attach("lo", XdpFlags::default()).unwrap();
let link = prog.take_link(link_id).unwrap(); let link = prog.take_link(link_id).unwrap();
assert_loaded!("test_xdp", true); assert_loaded!("test_xdp", true);
@ -257,8 +284,8 @@ fn pin_lifecycle() {
// 1. Load Program and Pin // 1. Load Program and Pin
{ {
let mut bpf = Bpf::load(crate::PASS).unwrap(); let mut bpf = Bpf::load(crate::PASS).unwrap();
let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); let prog: &mut Xdp = bpf.programs.get_mut("pass").unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load(bpf.btf_fd.as_ref()).unwrap();
prog.pin("/sys/fs/bpf/aya-xdp-test-prog").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 // 4. Load a new version of the program, unpin link, and atomically replace old program
{ {
let mut bpf = Bpf::load(crate::PASS).unwrap(); let mut bpf = Bpf::load(crate::PASS).unwrap();
let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); let prog: &mut Xdp = bpf.programs.get_mut("pass").unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load(bpf.btf_fd.as_ref()).unwrap();
let link = PinnedLink::from_pin("/sys/fs/bpf/aya-xdp-test-lo") let link = PinnedLink::from_pin("/sys/fs/bpf/aya-xdp-test-lo")
.unwrap() .unwrap()
@ -312,11 +339,12 @@ fn pin_lifecycle_tracepoint() {
{ {
let mut bpf = Bpf::load(crate::TEST).unwrap(); let mut bpf = Bpf::load(crate::TEST).unwrap();
let prog: &mut TracePoint = bpf let prog: &mut TracePoint = bpf
.program_mut("test_tracepoint") .programs
.get_mut("test_tracepoint")
.unwrap() .unwrap()
.try_into() .try_into()
.unwrap(); .unwrap();
prog.load().unwrap(); prog.load(bpf.btf_fd.as_ref()).unwrap();
prog.pin("/sys/fs/bpf/aya-tracepoint-test-prog").unwrap(); prog.pin("/sys/fs/bpf/aya-tracepoint-test-prog").unwrap();
} }
@ -365,8 +393,13 @@ fn pin_lifecycle_kprobe() {
// 1. Load Program and Pin // 1. Load Program and Pin
{ {
let mut bpf = Bpf::load(crate::TEST).unwrap(); let mut bpf = Bpf::load(crate::TEST).unwrap();
let prog: &mut KProbe = bpf.program_mut("test_kprobe").unwrap().try_into().unwrap(); let prog: &mut KProbe = bpf
prog.load().unwrap(); .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(); prog.pin("/sys/fs/bpf/aya-kprobe-test-prog").unwrap();
} }
@ -423,8 +456,13 @@ fn pin_lifecycle_uprobe() {
// 1. Load Program and Pin // 1. Load Program and Pin
{ {
let mut bpf = Bpf::load(crate::TEST).unwrap(); 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
prog.load().unwrap(); .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(); prog.pin("/sys/fs/bpf/aya-uprobe-test-prog").unwrap();
} }

@ -58,8 +58,13 @@ async fn log() {
.unwrap(); .unwrap();
} }
let prog: &mut UProbe = bpf.program_mut("test_log").unwrap().try_into().unwrap(); let prog: &mut UProbe = bpf
prog.load().unwrap(); .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) prog.attach(Some("trigger_ebpf_program"), 0, "/proc/self/exe", None)
.unwrap(); .unwrap();

@ -33,8 +33,8 @@ fn text_64_64_reloc() {
fn load_and_attach(name: &str, bytes: &[u8]) -> Bpf { fn load_and_attach(name: &str, bytes: &[u8]) -> Bpf {
let mut bpf = Bpf::load(bytes).unwrap(); let mut bpf = Bpf::load(bytes).unwrap();
let prog: &mut UProbe = bpf.program_mut(name).unwrap().try_into().unwrap(); let prog: &mut UProbe = bpf.programs.get_mut(name).unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load(bpf.btf_fd.as_ref()).unwrap();
prog.attach( prog.attach(
Some("trigger_relocations_program"), Some("trigger_relocations_program"),

@ -13,8 +13,8 @@ fn xdp() {
} }
let mut bpf = Bpf::load(crate::PASS).unwrap(); let mut bpf = Bpf::load(crate::PASS).unwrap();
let dispatcher: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); let dispatcher: &mut Xdp = bpf.programs.get_mut("pass").unwrap().try_into().unwrap();
dispatcher.load().unwrap(); dispatcher.load(bpf.btf_fd.as_ref()).unwrap();
dispatcher.attach("lo", XdpFlags::default()).unwrap(); dispatcher.attach("lo", XdpFlags::default()).unwrap();
} }
@ -26,11 +26,13 @@ fn extension() {
return; return;
} }
let mut bpf = Bpf::load(crate::MAIN).unwrap(); let mut bpf = Bpf::load(crate::MAIN).unwrap();
let pass: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); let pass: &mut Xdp = bpf.programs.get_mut("pass").unwrap().try_into().unwrap();
pass.load().unwrap(); pass.load(bpf.btf_fd.as_ref()).unwrap();
pass.attach("lo", XdpFlags::default()).unwrap(); pass.attach("lo", XdpFlags::default()).unwrap();
let mut bpf = BpfLoader::new().extension("drop").load(crate::EXT).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 drop_: &mut Extension = bpf.programs.get_mut("drop").unwrap().try_into().unwrap();
drop_.load(pass.fd().unwrap(), "xdp_pass").unwrap(); drop_
.load(pass.fd().unwrap(), "xdp_pass", bpf.btf_fd.as_ref())
.unwrap();
} }

Loading…
Cancel
Save