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/r11
Andrés Medina 2 years ago
parent ab1ca8fb60
commit b2b52aac9e

@ -82,7 +82,7 @@ use aya::programs::{CgroupSkb, CgroupSkbAttachType};
let mut bpf = Bpf::load_file("bpf.o")?; let mut bpf = Bpf::load_file("bpf.o")?;
// get the `ingress_filter` program compiled into `bpf.o`. // get the `ingress_filter` program compiled into `bpf.o`.
let ingress: &mut CgroupSkb = bpf.program_mut("ingress_filter")?.try_into()?; let mut ingress: aya::WithBtfFd<CgroupSkb> = bpf.program_mut("ingress_filter")?.try_into()?;
// load the program into the kernel // load the program into the kernel
ingress.load()?; ingress.load()?;

@ -82,7 +82,7 @@ use aya::programs::{CgroupSkb, CgroupSkbAttachType};
let mut bpf = Bpf::load_file("bpf.o")?; let mut bpf = Bpf::load_file("bpf.o")?;
// get the `ingress_filter` program compiled into `bpf.o`. // get the `ingress_filter` program compiled into `bpf.o`.
let ingress: &mut CgroupSkb = bpf.program_mut("ingress_filter")?.try_into()?; let mut ingress: aya::WithBtfFd<CgroupSkb> = bpf.program_mut("ingress_filter")?.try_into()?;
// load the program into the kernel // load the program into the kernel
ingress.load()?; ingress.load()?;

@ -3,7 +3,11 @@ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
ffi::CString, ffi::CString,
fs, io, fs, io,
os::{fd::RawFd, raw::c_int}, ops::{Deref, DerefMut},
os::{
fd::{AsFd, BorrowedFd, OwnedFd, RawFd},
raw::c_int,
},
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
@ -473,7 +477,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 +491,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 +500,7 @@ impl<'a> BpfLoader<'a> {
} }
} }
} }
PinningType::None => map.create(&name)?, PinningType::None => map.create(&name, btf_fd.as_ref())?,
}; };
if !map.obj.data().is_empty() && map.obj.section_kind() != BpfSectionKind::Bss { 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 +548,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 +618,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 +655,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 +700,11 @@ impl<'a> BpfLoader<'a> {
})?; })?;
}; };
Ok(Bpf { maps, programs }) Ok(Bpf {
maps,
programs,
btf_fd,
})
} }
} }
@ -741,11 +746,53 @@ impl<'a> Default for BpfLoader<'a> {
} }
} }
/// A program with a BTF file descriptor
pub struct WithBtfFd<'p, P> {
/// The program underneath
pub program: &'p mut P,
pub(crate) btf_fd: Option<BorrowedFd<'p>>,
}
impl<'f, P> Deref for WithBtfFd<'f, P> {
type Target = P;
fn deref(&self) -> &Self::Target {
&*self.program
}
}
impl<'f, P> DerefMut for WithBtfFd<'f, P> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.program
}
}
impl<'p, P, T> AsRef<T> for WithBtfFd<'p, P>
where
T: ?Sized,
<WithBtfFd<'p, P> as Deref>::Target: AsRef<T>,
{
fn as_ref(&self) -> &T {
self.deref().as_ref()
}
}
impl<'p, P, T> AsMut<T> for WithBtfFd<'p, P>
where
<WithBtfFd<'p, P> as Deref>::Target: AsMut<T>,
{
fn as_mut(&mut self) -> &mut T {
self.deref_mut().as_mut()
}
}
/// The main entry point into the library, used to work with eBPF programs and maps. /// 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: HashMap<String, Map>,
programs: HashMap<String, Program>, programs: HashMap<String, Program>,
btf_fd: Option<OwnedFd>,
} }
impl Bpf { impl Bpf {
@ -882,13 +929,16 @@ 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 mut program: aya::WithBtfFd<UProbe> = bpf.program_mut("SSL_read").unwrap().try_into()?;
/// program.load()?; /// program.load()?;
/// program.attach(Some("SSL_read"), 0, "libssl", None)?; /// program.attach(Some("SSL_read"), 0, "libssl", None)?;
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
/// ``` /// ```
pub fn program_mut(&mut self, name: &str) -> Option<&mut Program> { pub fn program_mut(&mut self, name: &str) -> Option<WithBtfFd<'_, Program>> {
self.programs.get_mut(name) self.programs.get_mut(name).map(|program| WithBtfFd {
program,
btf_fd: self.btf_fd.as_ref().map(|p| p.as_fd()),
})
} }
/// An iterator over all the programs. /// An iterator over all the programs.
@ -993,12 +1043,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,7 +24,7 @@
//! //!
//! 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 mut prog: aya::WithBtfFd<SkMsg> = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
//! prog.load()?; //! prog.load()?;
//! prog.attach(map_fd)?; //! prog.attach(map_fd)?;
//! //!
@ -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,7 +49,7 @@ 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 mut prog: aya::WithBtfFd<SkMsg> = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
/// prog.load()?; /// prog.load()?;
/// prog.attach(map_fd)?; /// prog.attach(map_fd)?;
/// ///

@ -17,7 +17,7 @@ use crate::{
/// sockets. /// sockets.
/// ///
/// A `SockMap` can also be used to redirect packets to sockets contained by the /// 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 /// # Minimum kernel version
/// ///
@ -33,7 +33,7 @@ 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 mut prog: aya::WithBtfFd<SkSkb> = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?;
/// prog.load()?; /// prog.load()?;
/// prog.attach(map_fd)?; /// prog.attach(map_fd)?;
/// ///

@ -1,7 +1,7 @@
//! Cgroup device programs. //! Cgroup device programs.
use crate::util::KernelVersion; use crate::{util::KernelVersion, WithBtfFd};
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,7 +40,7 @@ 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 mut program: aya::WithBtfFd<CgroupDevice> = bpf.program_mut("cgroup_dev").unwrap().try_into()?;
/// program.load()?; /// program.load()?;
/// program.attach(cgroup)?; /// program.attach(cgroup)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
@ -51,10 +51,17 @@ pub struct CgroupDevice {
pub(crate) data: ProgramData<CgroupDeviceLink>, pub(crate) data: ProgramData<CgroupDeviceLink>,
} }
impl<'p> WithBtfFd<'p, CgroupDevice> {
/// Loads the program inside the kernel.
pub fn load(&mut self) -> Result<(), ProgramError> {
self.program.load(self.btf_fd)
}
}
impl CgroupDevice { 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.

@ -1,9 +1,9 @@
//! Cgroup skb programs. //! Cgroup skb programs.
use crate::util::KernelVersion; use crate::{util::KernelVersion, WithBtfFd};
use std::{ use std::{
hash::Hash, hash::Hash,
os::fd::{AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd, RawFd},
path::Path, path::Path,
}; };
@ -50,7 +50,7 @@ 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 mut egress: aya::WithBtfFd<CgroupSkb> = bpf.program_mut("egress_filter").unwrap().try_into()?;
/// egress.load()?; /// egress.load()?;
/// egress.attach(file, CgroupSkbAttachType::Egress)?; /// egress.attach(file, CgroupSkbAttachType::Egress)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
@ -62,16 +62,23 @@ pub struct CgroupSkb {
pub(crate) expected_attach_type: Option<CgroupSkbAttachType>, pub(crate) expected_attach_type: Option<CgroupSkbAttachType>,
} }
impl CgroupSkb { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
self.program.load(self.btf_fd)
}
}
impl CgroupSkb {
/// Loads the program inside the kernel.
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.

@ -2,10 +2,10 @@
pub use aya_obj::programs::CgroupSockAttachType; pub use aya_obj::programs::CgroupSockAttachType;
use crate::util::KernelVersion; use crate::{util::KernelVersion, WithBtfFd};
use std::{ use std::{
hash::Hash, hash::Hash,
os::fd::{AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd, RawFd},
path::Path, path::Path,
}; };
@ -48,7 +48,7 @@ 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 mut bind: aya::WithBtfFd<CgroupSock> = bpf.program_mut("bind").unwrap().try_into()?;
/// bind.load()?; /// bind.load()?;
/// bind.attach(file)?; /// bind.attach(file)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
@ -60,11 +60,18 @@ pub struct CgroupSock {
pub(crate) attach_type: CgroupSockAttachType, pub(crate) attach_type: CgroupSockAttachType,
} }
impl CgroupSock { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
self.program.load(self.btf_fd)
}
}
impl CgroupSock {
/// Loads the program inside the kernel.
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.

@ -2,10 +2,10 @@
pub use aya_obj::programs::CgroupSockAddrAttachType; pub use aya_obj::programs::CgroupSockAddrAttachType;
use crate::util::KernelVersion; use crate::{util::KernelVersion, WithBtfFd};
use std::{ use std::{
hash::Hash, hash::Hash,
os::fd::{AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd, RawFd},
path::Path, path::Path,
}; };
@ -49,7 +49,7 @@ 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 mut egress: aya::WithBtfFd<CgroupSockAddr> = bpf.program_mut("connect4").unwrap().try_into()?;
/// egress.load()?; /// egress.load()?;
/// egress.attach(file)?; /// egress.attach(file)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
@ -61,11 +61,18 @@ pub struct CgroupSockAddr {
pub(crate) attach_type: CgroupSockAddrAttachType, pub(crate) attach_type: CgroupSockAddrAttachType,
} }
impl CgroupSockAddr { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
self.program.load(self.btf_fd)
}
}
impl CgroupSockAddr {
/// Loads the program inside the kernel.
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.

@ -2,10 +2,10 @@
pub use aya_obj::programs::CgroupSockoptAttachType; pub use aya_obj::programs::CgroupSockoptAttachType;
use crate::util::KernelVersion; use crate::{util::KernelVersion, WithBtfFd};
use std::{ use std::{
hash::Hash, hash::Hash,
os::fd::{AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd, RawFd},
path::Path, path::Path,
}; };
@ -46,7 +46,7 @@ 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 mut program: aya::WithBtfFd<CgroupSockopt> = bpf.program_mut("cgroup_sockopt").unwrap().try_into()?;
/// program.load()?; /// program.load()?;
/// program.attach(file)?; /// program.attach(file)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
@ -58,11 +58,18 @@ pub struct CgroupSockopt {
pub(crate) attach_type: CgroupSockoptAttachType, pub(crate) attach_type: CgroupSockoptAttachType,
} }
impl CgroupSockopt { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
self.program.load(self.btf_fd)
}
}
impl CgroupSockopt {
/// Loads the program inside the kernel.
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.

@ -1,9 +1,9 @@
//! Cgroup sysctl programs. //! Cgroup sysctl programs.
use crate::util::KernelVersion; use crate::{util::KernelVersion, WithBtfFd};
use std::{ use std::{
hash::Hash, hash::Hash,
os::fd::{AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd, RawFd},
}; };
use crate::{ use crate::{
@ -42,7 +42,7 @@ 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 mut program: aya::WithBtfFd<CgroupSysctl> = bpf.program_mut("cgroup_sysctl").unwrap().try_into()?;
/// program.load()?; /// program.load()?;
/// program.attach(file)?; /// program.attach(file)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
@ -53,10 +53,17 @@ pub struct CgroupSysctl {
pub(crate) data: ProgramData<CgroupSysctlLink>, pub(crate) data: ProgramData<CgroupSysctlLink>,
} }
impl CgroupSysctl { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_CGROUP_SYSCTL, &mut self.data) self.program.load(self.btf_fd)
}
}
impl CgroupSysctl {
/// Loads the program inside the kernel.
pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> Result<(), ProgramError> {
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;
@ -11,7 +11,7 @@ use crate::{
define_link_wrapper, load_program, FdLink, FdLinkId, ProgramData, ProgramError, ProgramFd, define_link_wrapper, load_program, FdLink, FdLinkId, ProgramData, ProgramError, ProgramFd,
}, },
sys::{self, bpf_link_create}, sys::{self, bpf_link_create},
Btf, Btf, WithBtfFd,
}; };
/// The type returned when loading or attaching an [`Extension`] fails. /// The type returned when loading or attaching an [`Extension`] fails.
@ -37,12 +37,12 @@ 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 mut prog: aya::WithBtfFd<Xdp> = bpf.program_mut("main").unwrap().try_into()?;
/// prog.load()?; /// prog.load()?;
/// 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 mut ext: aya::WithBtfFd<Extension> = bpf.program_mut("extension").unwrap().try_into()?;
/// ext.load(prog_fd, "function_to_replace")?; /// ext.load(prog_fd, "function_to_replace")?;
/// ext.attach()?; /// ext.attach()?;
/// Ok::<(), aya::BpfError>(()) /// Ok::<(), aya::BpfError>(())
@ -53,6 +53,13 @@ pub struct Extension {
pub(crate) data: ProgramData<ExtensionLink>, pub(crate) data: ProgramData<ExtensionLink>,
} }
impl<'p> WithBtfFd<'p, Extension> {
/// Loads the program inside the kernel.
pub fn load(&mut self, program: ProgramFd, func_name: &str) -> Result<(), ProgramError> {
self.program.load(program, func_name, self.btf_fd)
}
}
impl Extension { impl Extension {
/// Loads the extension inside the kernel. /// Loads the extension inside the kernel.
/// ///
@ -68,14 +75,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},
@ -7,6 +9,7 @@ use crate::{
define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId, define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId,
ProgramData, ProgramError, ProgramData, ProgramError,
}, },
WithBtfFd,
}; };
/// A program that can be attached to the entry point of (almost) any kernel /// A program that can be attached to the entry point of (almost) any kernel
@ -37,7 +40,7 @@ use crate::{
/// use aya::{Bpf, programs::FEntry, BtfError, Btf}; /// 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 mut program: aya::WithBtfFd<FEntry> = bpf.program_mut("filename_lookup").unwrap().try_into()?;
/// program.load("filename_lookup", &btf)?; /// program.load("filename_lookup", &btf)?;
/// program.attach()?; /// program.attach()?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
@ -49,16 +52,28 @@ pub struct FEntry {
pub(crate) data: ProgramData<FEntryLink>, pub(crate) data: ProgramData<FEntryLink>,
} }
impl<'p> WithBtfFd<'p, FEntry> {
/// Loads the program inside the kernel.
pub fn load(&mut self, fn_name: &str, btf: &Btf) -> Result<(), ProgramError> {
self.program.load(fn_name, btf, self.btf_fd)
}
}
impl FEntry { impl FEntry {
/// Loads the program inside the kernel. /// Loads the program inside the kernel.
/// ///
/// 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},
@ -7,6 +9,7 @@ use crate::{
define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId, define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId,
ProgramData, ProgramError, ProgramData, ProgramError,
}, },
WithBtfFd,
}; };
/// A program that can be attached to the exit point of (almost) anny kernel /// A program that can be attached to the exit point of (almost) anny kernel
@ -37,7 +40,7 @@ use crate::{
/// use aya::{Bpf, programs::FExit, BtfError, Btf}; /// 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 mut program: aya::WithBtfFd<FExit> = bpf.program_mut("filename_lookup").unwrap().try_into()?;
/// program.load("filename_lookup", &btf)?; /// program.load("filename_lookup", &btf)?;
/// program.attach()?; /// program.attach()?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
@ -49,16 +52,28 @@ pub struct FExit {
pub(crate) data: ProgramData<FExitLink>, pub(crate) data: ProgramData<FExitLink>,
} }
impl<'p> WithBtfFd<'p, FExit> {
/// Loads the program inside the kernel.
pub fn load(&mut self, fn_name: &str, btf: &Btf) -> Result<(), ProgramError> {
self.program.load(fn_name, btf, self.btf_fd)
}
}
impl FExit { impl FExit {
/// Loads the program inside the kernel. /// Loads the program inside the kernel.
/// ///
/// 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::{
@ -11,7 +11,7 @@ use crate::{
FdLink, LinkError, ProgramData, ProgramError, FdLink, LinkError, ProgramData, ProgramError,
}, },
sys::bpf_link_get_info_by_fd, sys::bpf_link_get_info_by_fd,
VerifierLogLevel, VerifierLogLevel, WithBtfFd,
}; };
/// A kernel probe. /// A kernel probe.
@ -32,7 +32,7 @@ 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 mut program: aya::WithBtfFd<KProbe> = bpf.program_mut("intercept_wakeups").unwrap().try_into()?;
/// program.load()?; /// program.load()?;
/// program.attach("try_to_wake_up", 0)?; /// program.attach("try_to_wake_up", 0)?;
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
@ -44,10 +44,17 @@ pub struct KProbe {
pub(crate) kind: ProbeKind, pub(crate) kind: ProbeKind,
} }
impl KProbe { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_KPROBE, &mut self.data) self.program.load(self.btf_fd)
}
}
impl KProbe {
/// Loads the program inside the kernel.
pub fn load(&mut self, btf_fd: Option<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 /// Returns `KProbe` if the program is a `kprobe`, or `KRetProbe` if the

@ -97,7 +97,7 @@ 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 mut program: aya::WithBtfFd<KProbe> = bpf.program_mut("intercept_wakeups").unwrap().try_into()?;
/// program.load()?; /// program.load()?;
/// 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();
@ -138,7 +138,7 @@ impl FdLink {
/// # Program(#[from] aya::programs::ProgramError) /// # Program(#[from] aya::programs::ProgramError)
/// # } /// # }
/// # let mut bpf = aya::Bpf::load(&[])?; /// # let mut bpf = aya::Bpf::load(&[])?;
/// # let prog: &mut Extension = bpf.program_mut("example").unwrap().try_into()?; /// # let mut prog: aya::WithBtfFd<Extension> = bpf.program_mut("example").unwrap().try_into()?;
/// let link_id = prog.attach()?; /// let link_id = prog.attach()?;
/// let owned_link = prog.take_link(link_id)?; /// let owned_link = prog.take_link(link_id)?;
/// let fd_link: FdLink = owned_link.into(); /// let fd_link: FdLink = owned_link.into();

@ -1,10 +1,11 @@
//! Lirc programs. //! Lirc programs.
use std::os::fd::{AsRawFd, IntoRawFd as _, RawFd}; use std::os::fd::{AsFd, AsRawFd, IntoRawFd as _, 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},
programs::{load_program, query, Link, ProgramData, ProgramError, ProgramInfo}, programs::{load_program, query, Link, ProgramData, ProgramError, ProgramInfo},
sys::{bpf_prog_attach, bpf_prog_detach, bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd}, sys::{bpf_prog_attach, bpf_prog_detach, bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd},
WithBtfFd,
}; };
use libc::{close, dup}; use libc::{close, dup};
@ -40,7 +41,7 @@ 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 mut decoder: aya::WithBtfFd<LircMode2> = bpf.program_mut("imon_rsc").unwrap().try_into().unwrap();
/// decoder.load()?; /// decoder.load()?;
/// decoder.attach(file)?; /// decoder.attach(file)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
@ -51,10 +52,17 @@ pub struct LircMode2 {
pub(crate) data: ProgramData<LircLink>, pub(crate) data: ProgramData<LircLink>,
} }
impl LircMode2 { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_LIRC_MODE2, &mut self.data) self.program.load(self.btf_fd)
}
}
impl LircMode2 {
/// Loads the program inside the kernel.
pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> Result<(), ProgramError> {
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},
@ -7,6 +9,7 @@ use crate::{
define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId, define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId,
ProgramData, ProgramError, ProgramData, ProgramError,
}, },
WithBtfFd,
}; };
/// A program that attaches to Linux LSM hooks. Used to implement security policy and /// A program that attaches to Linux LSM hooks. Used to implement security policy and
@ -39,7 +42,7 @@ use crate::{
/// use aya::{Bpf, programs::Lsm, BtfError, Btf}; /// 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 mut program: aya::WithBtfFd<Lsm> = bpf.program_mut("lsm_prog").unwrap().try_into()?;
/// program.load("security_bprm_exec", &btf)?; /// program.load("security_bprm_exec", &btf)?;
/// program.attach()?; /// program.attach()?;
/// # Ok::<(), LsmError>(()) /// # Ok::<(), LsmError>(())
@ -52,6 +55,13 @@ pub struct Lsm {
pub(crate) data: ProgramData<LsmLink>, pub(crate) data: ProgramData<LsmLink>,
} }
impl<'p> WithBtfFd<'p, Lsm> {
/// Loads the program inside the kernel.
pub fn load(&mut self, lsm_hook_name: &str, btf: &Btf) -> Result<(), ProgramError> {
self.program.load(lsm_hook_name, btf, self.btf_fd)
}
}
impl Lsm { impl Lsm {
/// Loads the program inside the kernel. /// Loads the program inside the kernel.
/// ///
@ -59,12 +69,17 @@ impl Lsm {
/// ///
/// * `lsm_hook_name` - full name of the LSM hook that the program should /// * `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,7 +18,7 @@
//! //!
//! 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 mut program: aya::WithBtfFd<KProbe> = bpf.program_mut("intercept_wakeups").unwrap().try_into()?;
//! program.load()?; //! program.load()?;
//! // 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
@ -69,7 +69,7 @@ use libc::ENOSPC;
use std::{ use std::{
ffi::CString, ffi::CString,
io, io,
os::fd::{AsRawFd, IntoRawFd as _, RawFd}, os::fd::{AsFd, AsRawFd, IntoRawFd as _, 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,
@ -885,6 +881,17 @@ macro_rules! impl_try_from_program {
} }
} }
} }
impl<'a> TryFrom<$crate::WithBtfFd<'a, Program>> for $crate::bpf::WithBtfFd<'a, $ty> {
type Error = ProgramError;
fn try_from(program: $crate::WithBtfFd<'a, Program>) -> Result<$crate::WithBtfFd<'a, $ty>, ProgramError> {
Ok($crate::bpf::WithBtfFd {
program: program.program.try_into()?,
btf_fd: program.btf_fd
})
}
}
)+ )+
} }
} }

@ -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,
}; };
@ -20,6 +22,7 @@ use crate::{
FdLink, LinkError, ProgramData, ProgramError, FdLink, LinkError, ProgramData, ProgramError,
}, },
sys::{bpf_link_get_info_by_fd, perf_event_open}, sys::{bpf_link_get_info_by_fd, perf_event_open},
WithBtfFd,
}; };
/// The type of perf event /// The type of perf event
@ -105,7 +108,7 @@ 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 mut prog: aya::WithBtfFd<PerfEvent> = bpf.program_mut("observe_cpu_clock").unwrap().try_into()?;
/// prog.load()?; /// prog.load()?;
/// ///
/// for cpu in online_cpus()? { /// for cpu in online_cpus()? {
@ -124,10 +127,17 @@ pub struct PerfEvent {
pub(crate) data: ProgramData<PerfEventLink>, pub(crate) data: ProgramData<PerfEventLink>,
} }
impl PerfEvent { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_PERF_EVENT, &mut self.data) self.program.load(self.btf_fd)
}
}
impl PerfEvent {
/// Loads the program inside the kernel.
pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> Result<(), ProgramError> {
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,
@ -7,6 +7,7 @@ use crate::{
define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId, define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId,
ProgramData, ProgramError, ProgramData, ProgramError,
}, },
WithBtfFd,
}; };
/// A program that can be attached at a pre-defined kernel trace point, but also /// A program that can be attached at a pre-defined kernel trace point, but also
@ -27,7 +28,7 @@ use crate::{
/// # let mut bpf = Bpf::load_file("ebpf_programs.o")?; /// # 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 mut program: aya::WithBtfFd<RawTracePoint> = bpf.program_mut("sys_enter").unwrap().try_into()?;
/// program.load()?; /// program.load()?;
/// program.attach("sys_enter")?; /// program.attach("sys_enter")?;
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
@ -38,10 +39,17 @@ pub struct RawTracePoint {
pub(crate) data: ProgramData<RawTracePointLink>, pub(crate) data: ProgramData<RawTracePointLink>,
} }
impl RawTracePoint { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_RAW_TRACEPOINT, &mut self.data) self.program.load(self.btf_fd)
}
}
impl RawTracePoint {
/// Loads the program inside the kernel.
pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> Result<(), ProgramError> {
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,9 +1,10 @@
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},
programs::{define_link_wrapper, load_program, FdLinkId, ProgramData, ProgramError}, programs::{define_link_wrapper, load_program, FdLinkId, ProgramData, ProgramError},
sys::bpf_link_create, sys::bpf_link_create,
WithBtfFd,
}; };
use super::links::FdLink; use super::links::FdLink;
@ -39,7 +40,7 @@ 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 mut program: aya::WithBtfFd<SkLookup> = bpf.program_mut("sk_lookup").unwrap().try_into()?;
/// program.load()?; /// program.load()?;
/// program.attach(file)?; /// program.attach(file)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
@ -50,11 +51,18 @@ pub struct SkLookup {
pub(crate) data: ProgramData<SkLookupLink>, pub(crate) data: ProgramData<SkLookupLink>,
} }
impl SkLookup { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
self.program.load(self.btf_fd)
}
}
impl SkLookup {
/// Loads the program inside the kernel.
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},
@ -10,6 +10,7 @@ use crate::{
ProgramError, ProgramError,
}, },
sys::bpf_prog_attach, sys::bpf_prog_attach,
WithBtfFd,
}; };
/// A program used to intercept messages sent with `sendmsg()`/`sendfile()`. /// A program used to intercept messages sent with `sendmsg()`/`sendfile()`.
@ -46,7 +47,7 @@ use crate::{
/// let intercept_egress: SockHash<_, u32> = bpf.map("INTERCEPT_EGRESS").unwrap().try_into()?; /// let 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 mut prog: aya::WithBtfFd<SkMsg> = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
/// prog.load()?; /// prog.load()?;
/// prog.attach(map_fd)?; /// prog.attach(map_fd)?;
/// ///
@ -69,10 +70,17 @@ pub struct SkMsg {
pub(crate) data: ProgramData<SkMsgLink>, pub(crate) data: ProgramData<SkMsgLink>,
} }
impl SkMsg { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_SK_MSG, &mut self.data) self.program.load(self.btf_fd)
}
}
impl SkMsg {
/// Loads the program inside the kernel.
pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> Result<(), ProgramError> {
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::{
@ -13,7 +16,7 @@ use crate::{
ProgramError, ProgramError,
}, },
sys::bpf_prog_attach, sys::bpf_prog_attach,
VerifierLogLevel, VerifierLogLevel, WithBtfFd,
}; };
/// The kind of [`SkSkb`] program. /// The kind of [`SkSkb`] program.
@ -45,7 +48,7 @@ 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 mut prog: aya::WithBtfFd<SkSkb> = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?;
/// prog.load()?; /// prog.load()?;
/// prog.attach(map_fd)?; /// prog.attach(map_fd)?;
/// ///
@ -62,10 +65,17 @@ pub struct SkSkb {
pub(crate) kind: SkSkbKind, pub(crate) kind: SkSkbKind,
} }
impl SkSkb { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_SK_SKB, &mut self.data) self.program.load(self.btf_fd)
}
}
impl SkSkb {
/// Loads the program inside the kernel.
pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> Result<(), ProgramError> {
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},
@ -8,6 +8,7 @@ use crate::{
ProgramError, ProgramError,
}, },
sys::bpf_prog_attach, sys::bpf_prog_attach,
WithBtfFd,
}; };
/// A program used to work with sockets. /// A program used to work with sockets.
@ -39,7 +40,7 @@ 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 mut prog: aya::WithBtfFd<SockOps> = bpf.program_mut("intercept_active_sockets").unwrap().try_into()?;
/// prog.load()?; /// prog.load()?;
/// prog.attach(file)?; /// prog.attach(file)?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
@ -49,10 +50,17 @@ pub struct SockOps {
pub(crate) data: ProgramData<SockOpsLink>, pub(crate) data: ProgramData<SockOpsLink>,
} }
impl SockOps { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_SOCK_OPS, &mut self.data) self.program.load(self.btf_fd)
}
}
impl SockOps {
/// Loads the program inside the kernel.
pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> Result<(), ProgramError> {
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,13 +2,14 @@
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;
use crate::{ use crate::{
generated::{bpf_prog_type::BPF_PROG_TYPE_SOCKET_FILTER, SO_ATTACH_BPF, SO_DETACH_BPF}, generated::{bpf_prog_type::BPF_PROG_TYPE_SOCKET_FILTER, SO_ATTACH_BPF, SO_DETACH_BPF},
programs::{load_program, Link, ProgramData, ProgramError}, programs::{load_program, Link, ProgramData, ProgramError},
WithBtfFd,
}; };
/// The type returned when attaching a [`SocketFilter`] fails. /// The type returned when attaching a [`SocketFilter`] fails.
@ -52,7 +53,7 @@ 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 mut prog: aya::WithBtfFd<SocketFilter> = bpf.program_mut("filter_packets").unwrap().try_into()?;
/// prog.load()?; /// prog.load()?;
/// prog.attach(client.as_raw_fd())?; /// prog.attach(client.as_raw_fd())?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
@ -63,10 +64,17 @@ pub struct SocketFilter {
pub(crate) data: ProgramData<SocketFilterLink>, pub(crate) data: ProgramData<SocketFilterLink>,
} }
impl SocketFilter { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_SOCKET_FILTER, &mut self.data) self.program.load(self.btf_fd)
}
}
impl SocketFilter {
/// Loads the program inside the kernel.
pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> Result<(), ProgramError> {
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,
}; };
@ -17,7 +18,7 @@ use crate::{
netlink_qdisc_detach, netlink_qdisc_detach,
}, },
util::{ifindex_from_ifname, tc_handler_make}, util::{ifindex_from_ifname, tc_handler_make},
VerifierLogLevel, VerifierLogLevel, WithBtfFd,
}; };
/// Traffic control attach type. /// Traffic control attach type.
@ -63,7 +64,7 @@ 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 mut prog: aya::WithBtfFd<SchedClassifier> = bpf.program_mut("redirect_ingress").unwrap().try_into()?;
/// prog.load()?; /// prog.load()?;
/// prog.attach("eth0", TcAttachType::Ingress)?; /// prog.attach("eth0", TcAttachType::Ingress)?;
/// ///
@ -112,10 +113,17 @@ pub struct TcOptions {
pub handle: u32, pub handle: u32,
} }
impl SchedClassifier { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_SCHED_CLS, &mut self.data) self.program.load(self.btf_fd)
}
}
impl SchedClassifier {
/// Loads the program inside the kernel.
pub fn load(&mut self, btf_fd: Option<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. /// 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},
@ -7,6 +9,7 @@ use crate::{
define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId, define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId,
ProgramData, ProgramError, ProgramData, ProgramError,
}, },
WithBtfFd,
}; };
/// Marks a function as a [BTF-enabled raw tracepoint][1] eBPF program that can be attached at /// Marks a function as a [BTF-enabled raw tracepoint][1] eBPF program that can be attached at
@ -36,7 +39,7 @@ use crate::{
/// use aya::{Bpf, programs::BtfTracePoint, BtfError, Btf}; /// 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 mut program: aya::WithBtfFd<BtfTracePoint> = bpf.program_mut("sched_process_fork").unwrap().try_into()?;
/// program.load("sched_process_fork", &btf)?; /// program.load("sched_process_fork", &btf)?;
/// program.attach()?; /// program.attach()?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
@ -50,6 +53,13 @@ pub struct BtfTracePoint {
pub(crate) data: ProgramData<BtfTracePointLink>, pub(crate) data: ProgramData<BtfTracePointLink>,
} }
impl<'p> WithBtfFd<'p, BtfTracePoint> {
/// Loads the program inside the kernel.
pub fn load(&mut self, tracepoint: &str, btf: &Btf) -> Result<(), ProgramError> {
self.program.load(tracepoint, btf, self.btf_fd)
}
}
impl BtfTracePoint { impl BtfTracePoint {
/// Loads the program inside the kernel. /// Loads the program inside the kernel.
/// ///
@ -57,12 +67,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::{
@ -11,6 +11,7 @@ use crate::{
FdLink, LinkError, ProgramData, ProgramError, FdLink, LinkError, ProgramData, ProgramError,
}, },
sys::{bpf_link_get_info_by_fd, perf_event_open_trace_point}, sys::{bpf_link_get_info_by_fd, perf_event_open_trace_point},
WithBtfFd,
}; };
/// The type returned when attaching a [`TracePoint`] fails. /// The type returned when attaching a [`TracePoint`] fails.
@ -54,7 +55,7 @@ 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 mut prog: aya::WithBtfFd<TracePoint> = bpf.program_mut("trace_context_switch").unwrap().try_into()?;
/// prog.load()?; /// prog.load()?;
/// prog.attach("sched", "sched_switch")?; /// prog.attach("sched", "sched_switch")?;
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
@ -65,10 +66,17 @@ pub struct TracePoint {
pub(crate) data: ProgramData<TracePointLink>, pub(crate) data: ProgramData<TracePointLink>,
} }
impl TracePoint { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_TRACEPOINT, &mut self.data) self.program.load(self.btf_fd)
}
}
impl TracePoint {
/// Loads the program inside the kernel.
pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> Result<(), ProgramError> {
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,
}; };
@ -22,7 +22,7 @@ use crate::{
FdLink, LinkError, ProgramData, ProgramError, FdLink, LinkError, ProgramData, ProgramError,
}, },
sys::bpf_link_get_info_by_fd, sys::bpf_link_get_info_by_fd,
VerifierLogLevel, VerifierLogLevel, WithBtfFd,
}; };
const LD_SO_CACHE_FILE: &str = "/etc/ld.so.cache"; const LD_SO_CACHE_FILE: &str = "/etc/ld.so.cache";
@ -48,10 +48,17 @@ pub struct UProbe {
pub(crate) kind: ProbeKind, pub(crate) kind: ProbeKind,
} }
impl UProbe { impl<'p> WithBtfFd<'p, 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) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_KPROBE, &mut self.data) self.program.load(self.btf_fd)
}
}
impl UProbe {
/// Loads the program inside the kernel.
pub fn load(&mut self, btf_fd: Option<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 /// Returns `UProbe` if the program is a `uprobe`, or `URetProbe` if the

@ -1,9 +1,15 @@
//! eXpress Data Path (XDP) programs. //! eXpress Data Path (XDP) programs.
use crate::util::KernelVersion; use crate::{util::KernelVersion, WithBtfFd};
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::{
@ -66,7 +72,7 @@ bitflags! {
/// # let mut bpf = Bpf::load_file("ebpf_programs.o")?; /// # let mut bpf = Bpf::load_file("ebpf_programs.o")?;
/// use aya::{Bpf, programs::{Xdp, XdpFlags}}; /// use aya::{Bpf, programs::{Xdp, XdpFlags}};
/// ///
/// let program: &mut Xdp = bpf.program_mut("intercept_packets").unwrap().try_into()?; /// let mut program: aya::WithBtfFd<Xdp> = bpf.program_mut("intercept_packets").unwrap().try_into()?;
/// program.attach("eth0", XdpFlags::default())?; /// program.attach("eth0", XdpFlags::default())?;
/// # Ok::<(), aya::BpfError>(()) /// # Ok::<(), aya::BpfError>(())
/// ``` /// ```
@ -76,11 +82,18 @@ pub struct Xdp {
pub(crate) data: ProgramData<XdpLink>, pub(crate) data: ProgramData<XdpLink>,
} }
impl Xdp { impl<'f> WithBtfFd<'f, 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) -> Result<(), ProgramError> {
self.program.load(self.btf_fd)
}
}
impl Xdp {
/// Loads the program inside the kernel.
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::{FromRawFd as _, OwnedFd, RawFd}, os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd as _, 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;
@ -561,7 +561,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;
@ -571,7 +571,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> {
@ -711,10 +713,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";

@ -1,4 +1,4 @@
use aya::{maps::Array, programs::UProbe, Bpf}; use aya::{maps::Array, programs::UProbe, Bpf, WithBtfFd};
const RESULT_BUF_LEN: usize = 1024; const RESULT_BUF_LEN: usize = 1024;
@ -104,8 +104,7 @@ 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 mut prog: WithBtfFd<UProbe> = bpf.program_mut(prog_name).unwrap().try_into().unwrap();
let prog: &mut UProbe = bpf.program_mut(prog_name).unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load().unwrap();
prog.attach(Some(func_name), 0, "/proc/self/exe", None) prog.attach(Some(func_name), 0, "/proc/self/exe", None)

@ -5,7 +5,9 @@ use std::{
time::Duration, time::Duration,
}; };
use aya::{maps::Array, programs::TracePoint, util::KernelVersion, BpfLoader, Btf, Endianness}; use aya::{
maps::Array, programs::TracePoint, util::KernelVersion, BpfLoader, Btf, Endianness, WithBtfFd,
};
// In the tests below we often use values like 0xAAAAAAAA or -0x7AAAAAAA. Those values have no // In the tests below we often use values like 0xAAAAAAAA or -0x7AAAAAAA. Those values have no
// special meaning, they just have "nice" bit patterns that can be helpful while debugging. // special meaning, they just have "nice" bit patterns that can be helpful while debugging.
@ -384,7 +386,7 @@ impl RelocationTestRunner {
loader.btf(None); loader.btf(None);
} }
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 mut program: WithBtfFd<TracePoint> = bpf
.program_mut("bpf_prog") .program_mut("bpf_prog")
.context("bpf_prog not found")? .context("bpf_prog not found")?
.try_into() .try_into()

@ -7,7 +7,7 @@ use aya::{
loaded_programs, KProbe, TracePoint, UProbe, Xdp, XdpFlags, loaded_programs, KProbe, TracePoint, UProbe, Xdp, XdpFlags,
}, },
util::KernelVersion, util::KernelVersion,
Bpf, Bpf, WithBtfFd,
}; };
const MAX_RETRIES: u32 = 100; const MAX_RETRIES: u32 = 100;
@ -16,7 +16,7 @@ const RETRY_DURATION_MS: u64 = 10;
#[test] #[test]
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 mut name_prog: WithBtfFd<Xdp> = bpf
.program_mut("ihaveaverylongname") .program_mut("ihaveaverylongname")
.unwrap() .unwrap()
.try_into() .try_into()
@ -36,7 +36,8 @@ fn multiple_btf_maps() {
let map_1: Array<_, u64> = bpf.take_map("map_1").unwrap().try_into().unwrap(); let map_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 mut prog: WithBtfFd<TracePoint> =
bpf.program_mut("tracepoint").unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load().unwrap();
prog.attach("sched", "sched_switch").unwrap(); prog.attach("sched", "sched_switch").unwrap();
@ -110,7 +111,7 @@ 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 mut prog: WithBtfFd<Xdp> = bpf.program_mut("test_xdp").unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load().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();
@ -135,7 +136,7 @@ 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 mut prog: WithBtfFd<KProbe> = bpf.program_mut("test_kprobe").unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load().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();
@ -160,7 +161,7 @@ fn unload_kprobe() {
#[test] #[test]
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 mut prog: WithBtfFd<TracePoint> = bpf
.program_mut("test_tracepoint") .program_mut("test_tracepoint")
.unwrap() .unwrap()
.try_into() .try_into()
@ -191,7 +192,7 @@ 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 mut prog: WithBtfFd<UProbe> = bpf.program_mut("test_uprobe").unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load().unwrap();
assert_loaded!("test_uprobe", true); assert_loaded!("test_uprobe", true);
@ -224,7 +225,7 @@ 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 mut prog: WithBtfFd<Xdp> = bpf.program_mut("test_xdp").unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load().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();
@ -257,7 +258,7 @@ 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 mut prog: WithBtfFd<Xdp> = bpf.program_mut("pass").unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load().unwrap();
prog.pin("/sys/fs/bpf/aya-xdp-test-prog").unwrap(); prog.pin("/sys/fs/bpf/aya-xdp-test-prog").unwrap();
} }
@ -291,7 +292,7 @@ fn pin_lifecycle() {
// 4. Load a new version of the program, unpin link, and atomically replace old program // 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 mut prog: WithBtfFd<Xdp> = bpf.program_mut("pass").unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load().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")
@ -311,7 +312,7 @@ fn pin_lifecycle_tracepoint() {
// 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 TracePoint = bpf let mut prog: WithBtfFd<TracePoint> = bpf
.program_mut("test_tracepoint") .program_mut("test_tracepoint")
.unwrap() .unwrap()
.try_into() .try_into()
@ -365,7 +366,8 @@ 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 mut prog: WithBtfFd<KProbe> =
bpf.program_mut("test_kprobe").unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load().unwrap();
prog.pin("/sys/fs/bpf/aya-kprobe-test-prog").unwrap(); prog.pin("/sys/fs/bpf/aya-kprobe-test-prog").unwrap();
} }
@ -423,7 +425,8 @@ 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 mut prog: WithBtfFd<UProbe> =
bpf.program_mut("test_uprobe").unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load().unwrap();
prog.pin("/sys/fs/bpf/aya-uprobe-test-prog").unwrap(); prog.pin("/sys/fs/bpf/aya-uprobe-test-prog").unwrap();
} }

@ -3,7 +3,7 @@ use std::{
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use aya::{programs::UProbe, Bpf}; use aya::{programs::UProbe, Bpf, WithBtfFd};
use aya_log::BpfLogger; use aya_log::BpfLogger;
use log::{Level, Log, Record}; use log::{Level, Log, Record};
@ -60,7 +60,7 @@ async fn log() {
.unwrap(); .unwrap();
} }
let prog: &mut UProbe = bpf.program_mut("test_log").unwrap().try_into().unwrap(); let mut prog: WithBtfFd<UProbe> = bpf.program_mut("test_log").unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load().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();

@ -1,6 +1,6 @@
use std::time::Duration; use std::time::Duration;
use aya::{programs::UProbe, Bpf}; use aya::{programs::UProbe, Bpf, WithBtfFd};
#[test] #[test]
fn relocations() { fn relocations() {
@ -32,8 +32,7 @@ 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 mut prog: WithBtfFd<UProbe> = bpf.program_mut(name).unwrap().try_into().unwrap();
let prog: &mut UProbe = bpf.program_mut(name).unwrap().try_into().unwrap();
prog.load().unwrap(); prog.load().unwrap();
prog.attach( prog.attach(

@ -1,7 +1,7 @@
use aya::{ use aya::{
programs::{Extension, Xdp, XdpFlags}, programs::{Extension, Xdp, XdpFlags},
util::KernelVersion, util::KernelVersion,
Bpf, BpfLoader, Bpf, BpfLoader, WithBtfFd,
}; };
#[test] #[test]
@ -13,7 +13,7 @@ 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 mut dispatcher: WithBtfFd<Xdp> = bpf.program_mut("pass").unwrap().try_into().unwrap();
dispatcher.load().unwrap(); dispatcher.load().unwrap();
dispatcher.attach("lo", XdpFlags::default()).unwrap(); dispatcher.attach("lo", XdpFlags::default()).unwrap();
} }
@ -26,11 +26,11 @@ 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 mut pass: WithBtfFd<Xdp> = bpf.program_mut("pass").unwrap().try_into().unwrap();
pass.load().unwrap(); pass.load().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 mut drop_: WithBtfFd<Extension> = bpf.program_mut("drop").unwrap().try_into().unwrap();
drop_.load(pass.fd().unwrap(), "xdp_pass").unwrap(); drop_.load(pass.fd().unwrap(), "xdp_pass").unwrap();
} }

Loading…
Cancel
Save