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/r8
Andrés Medina 2 years ago
parent f09e26f756
commit 11e993fdc4

@ -3,7 +3,10 @@ use std::{
collections::{HashMap, HashSet},
ffi::CString,
fs, io,
os::{fd::RawFd, raw::c_int},
os::{
fd::{OwnedFd, RawFd},
raw::c_int,
},
path::{Path, PathBuf},
};
@ -473,7 +476,6 @@ impl<'a> BpfLoader<'a> {
obj,
fd: None,
pinned: false,
btf_fd,
};
let fd = match map.obj.pinning() {
PinningType::ByName => {
@ -488,7 +490,7 @@ impl<'a> BpfLoader<'a> {
fd as RawFd
}
Err(_) => {
let fd = map.create(&name)?;
let fd = map.create(&name, btf_fd.as_ref())?;
map.pin(&name, path).map_err(|error| MapError::PinError {
name: Some(name.to_string()),
error,
@ -497,7 +499,7 @@ impl<'a> BpfLoader<'a> {
}
}
}
PinningType::None => map.create(&name)?,
PinningType::None => map.create(&name, btf_fd.as_ref())?,
};
if !map.obj.data().is_empty() && map.obj.section_kind() != BpfSectionKind::Bss {
bpf_map_update_elem_ptr(fd, &0 as *const _, map.obj.data_mut().as_mut_ptr(), 0)
@ -545,70 +547,69 @@ impl<'a> BpfLoader<'a> {
let program = if extensions.contains(name.as_str()) {
Program::Extension(Extension {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
})
} else {
match &section {
ProgramSection::KProbe { .. } => Program::KProbe(KProbe {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
kind: ProbeKind::KProbe,
}),
ProgramSection::KRetProbe { .. } => Program::KProbe(KProbe {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
kind: ProbeKind::KRetProbe,
}),
ProgramSection::UProbe { .. } => Program::UProbe(UProbe {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
kind: ProbeKind::UProbe,
}),
ProgramSection::URetProbe { .. } => Program::UProbe(UProbe {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
kind: ProbeKind::URetProbe,
}),
ProgramSection::TracePoint { .. } => Program::TracePoint(TracePoint {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
}),
ProgramSection::SocketFilter { .. } => {
Program::SocketFilter(SocketFilter {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
})
}
ProgramSection::Xdp { frags, .. } => {
let mut data =
ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level);
let mut data = ProgramData::new(prog_name, obj, *verifier_log_level);
if *frags {
data.flags = BPF_F_XDP_HAS_FRAGS;
}
Program::Xdp(Xdp { data })
}
ProgramSection::SkMsg { .. } => Program::SkMsg(SkMsg {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
}),
ProgramSection::CgroupSysctl { .. } => {
Program::CgroupSysctl(CgroupSysctl {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
})
}
ProgramSection::CgroupSockopt { attach_type, .. } => {
Program::CgroupSockopt(CgroupSockopt {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
attach_type: *attach_type,
})
}
ProgramSection::SkSkbStreamParser { .. } => Program::SkSkb(SkSkb {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
kind: SkSkbKind::StreamParser,
}),
ProgramSection::SkSkbStreamVerdict { .. } => Program::SkSkb(SkSkb {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
kind: SkSkbKind::StreamVerdict,
}),
ProgramSection::SockOps { .. } => Program::SockOps(SockOps {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
}),
ProgramSection::SchedClassifier { .. } => {
Program::SchedClassifier(SchedClassifier {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
name: unsafe {
CString::from_vec_unchecked(Vec::from(name.clone()))
.into_boxed_c_str()
@ -616,37 +617,36 @@ impl<'a> BpfLoader<'a> {
})
}
ProgramSection::CgroupSkb { .. } => Program::CgroupSkb(CgroupSkb {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
expected_attach_type: None,
}),
ProgramSection::CgroupSkbIngress { .. } => Program::CgroupSkb(CgroupSkb {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
expected_attach_type: Some(CgroupSkbAttachType::Ingress),
}),
ProgramSection::CgroupSkbEgress { .. } => Program::CgroupSkb(CgroupSkb {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
expected_attach_type: Some(CgroupSkbAttachType::Egress),
}),
ProgramSection::CgroupSockAddr { attach_type, .. } => {
Program::CgroupSockAddr(CgroupSockAddr {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
attach_type: *attach_type,
})
}
ProgramSection::LircMode2 { .. } => Program::LircMode2(LircMode2 {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
}),
ProgramSection::PerfEvent { .. } => Program::PerfEvent(PerfEvent {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
}),
ProgramSection::RawTracePoint { .. } => {
Program::RawTracePoint(RawTracePoint {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
})
}
ProgramSection::Lsm { sleepable, .. } => {
let mut data =
ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level);
let mut data = ProgramData::new(prog_name, obj, *verifier_log_level);
if *sleepable {
data.flags = BPF_F_SLEEPABLE;
}
@ -654,30 +654,30 @@ impl<'a> BpfLoader<'a> {
}
ProgramSection::BtfTracePoint { .. } => {
Program::BtfTracePoint(BtfTracePoint {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
})
}
ProgramSection::FEntry { .. } => Program::FEntry(FEntry {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
}),
ProgramSection::FExit { .. } => Program::FExit(FExit {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
}),
ProgramSection::Extension { .. } => Program::Extension(Extension {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
}),
ProgramSection::SkLookup { .. } => Program::SkLookup(SkLookup {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
}),
ProgramSection::CgroupSock { attach_type, .. } => {
Program::CgroupSock(CgroupSock {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
attach_type: *attach_type,
})
}
ProgramSection::CgroupDevice { .. } => {
Program::CgroupDevice(CgroupDevice {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
data: ProgramData::new(prog_name, obj, *verifier_log_level),
})
}
}
@ -699,7 +699,11 @@ impl<'a> BpfLoader<'a> {
})?;
};
Ok(Bpf { maps, programs })
Ok(Bpf {
maps,
programs,
btf_fd,
})
}
}
@ -743,9 +747,26 @@ impl<'a> Default for BpfLoader<'a> {
/// The main entry point into the library, used to work with eBPF programs and maps.
#[derive(Debug)]
#[non_exhaustive]
pub struct Bpf {
maps: HashMap<String, Map>,
programs: HashMap<String, Program>,
/// Maps that were loaded from the BPF object
///
/// After the BPF object is loaded, a `Bpf` instance keeps these
/// maps to manage their lifetime during drop but otherwise does
/// not touch them.
pub maps: HashMap<String, Map>,
/// Programs that were found in the BPF object
///
/// Unlike maps, programs do not start loaded nor attached, that
/// is a separate action. After the BPF object is loaded, a `Bpf`
/// instance keeps these programs to manage their lifetime during
/// drop but otherwise does not touch them.
pub programs: HashMap<String, Program>,
/// The file descriptor of the loaded BTF section from the BPF
/// object.
///
/// This may be used when loading programs
pub btf_fd: Option<OwnedFd>,
}
impl Bpf {
@ -882,8 +903,9 @@ impl Bpf {
/// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::programs::UProbe;
///
/// let program: &mut UProbe = bpf.program_mut("SSL_read").unwrap().try_into()?;
/// program.load()?;
/// let aya::Bpf { programs, btf_fd, .. } = &mut bpf;
/// let program: &mut UProbe = programs.get_mut("SSL_read").unwrap().try_into()?;
/// program.load(btf_fd.as_ref())?;
/// program.attach(Some("SSL_read"), 0, "libssl", None)?;
/// # Ok::<(), aya::BpfError>(())
/// ```
@ -993,12 +1015,12 @@ pub enum BpfError {
ProgramError(#[from] ProgramError),
}
fn load_btf(raw_btf: Vec<u8>, verifier_log_level: VerifierLogLevel) -> Result<RawFd, BtfError> {
fn load_btf(raw_btf: Vec<u8>, verifier_log_level: VerifierLogLevel) -> Result<OwnedFd, BtfError> {
let (ret, verifier_log) = retry_with_verifier_logs(10, |logger| {
bpf_load_btf(raw_btf.as_slice(), logger, verifier_log_level)
});
match ret {
Ok(fd) => Ok(fd as RawFd),
Ok(fd) => Ok(fd),
Err((_, io_error)) => Err(BtfError::LoadError {
io_error,
verifier_log,

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

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

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

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

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

@ -17,7 +17,7 @@ use crate::{
/// sockets.
///
/// A `SockMap` can also be used to redirect packets to sockets contained by the
/// map using `bpf_redirect_map()`, `bpf_sk_redirect_map()` etc.
/// map using `bpf_redirect_map()`, `bpf_sk_redirect_map()` etc.
///
/// # Minimum kernel version
///
@ -33,8 +33,9 @@ use crate::{
/// let intercept_ingress = SockMap::try_from(bpf.map("INTERCEPT_INGRESS").unwrap())?;
/// let map_fd = intercept_ingress.fd()?;
///
/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?;
/// prog.load()?;
/// let aya::Bpf { programs, btf_fd, .. } = &mut bpf;
/// let prog: &mut SkSkb = programs.get_mut("intercept_ingress_packet").unwrap().try_into()?;
/// prog.load(btf_fd.as_ref())?;
/// prog.attach(map_fd)?;
///
/// # Ok::<(), aya::BpfError>(())

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -1,5 +1,7 @@
//! Perf event programs.
use std::os::fd::AsFd;
pub use crate::generated::{
perf_hw_cache_id, perf_hw_cache_op_id, perf_hw_cache_op_result_id, perf_hw_id, perf_sw_ids,
};
@ -105,8 +107,9 @@ pub enum PerfEventScope {
/// perf_sw_ids::PERF_COUNT_SW_CPU_CLOCK, PerfEvent, PerfEventScope, PerfTypeId, SamplePolicy,
/// };
///
/// let prog: &mut PerfEvent = bpf.program_mut("observe_cpu_clock").unwrap().try_into()?;
/// prog.load()?;
/// let aya::Bpf { programs, btf_fd, .. } = &mut bpf;
/// let prog: &mut PerfEvent = programs.get_mut("observe_cpu_clock").unwrap().try_into()?;
/// prog.load(btf_fd.as_ref())?;
///
/// for cpu in online_cpus()? {
/// prog.attach(
@ -126,8 +129,8 @@ pub struct PerfEvent {
impl PerfEvent {
/// Loads the program inside the kernel.
pub fn load(&mut self) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_PERF_EVENT, &mut self.data)
pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_PERF_EVENT, &mut self.data, btf_fd)
}
/// Attaches to the given perf event.

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

@ -1,4 +1,4 @@
use std::os::fd::{AsRawFd, RawFd};
use std::os::fd::{AsFd, AsRawFd, RawFd};
use crate::{
generated::{bpf_attach_type::BPF_SK_LOOKUP, bpf_prog_type::BPF_PROG_TYPE_SK_LOOKUP},
@ -39,8 +39,9 @@ use super::links::FdLink;
/// use aya::programs::SkLookup;
///
/// let file = File::open("/var/run/netns/test")?;
/// let program: &mut SkLookup = bpf.program_mut("sk_lookup").unwrap().try_into()?;
/// program.load()?;
/// let aya::Bpf { programs, btf_fd, .. } = &mut bpf;
/// let program: &mut SkLookup = programs.get_mut("sk_lookup").unwrap().try_into()?;
/// program.load(btf_fd.as_ref())?;
/// program.attach(file)?;
/// # Ok::<(), Error>(())
/// ```
@ -52,9 +53,9 @@ pub struct SkLookup {
impl SkLookup {
/// Loads the program inside the kernel.
pub fn load(&mut self) -> Result<(), ProgramError> {
pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> Result<(), ProgramError> {
self.data.expected_attach_type = Some(BPF_SK_LOOKUP);
load_program(BPF_PROG_TYPE_SK_LOOKUP, &mut self.data)
load_program(BPF_PROG_TYPE_SK_LOOKUP, &mut self.data, btf_fd)
}
/// Attaches the program to the given network namespace.

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

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

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

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

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

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

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

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

@ -3,7 +3,13 @@
use crate::util::KernelVersion;
use bitflags;
use libc::if_nametoindex;
use std::{convert::TryFrom, ffi::CString, hash::Hash, io, mem, os::fd::RawFd};
use std::{
convert::TryFrom,
ffi::CString,
hash::Hash,
io, mem,
os::fd::{AsFd, RawFd},
};
use thiserror::Error;
use crate::{
@ -78,9 +84,9 @@ pub struct Xdp {
impl Xdp {
/// Loads the program inside the kernel.
pub fn load(&mut self) -> Result<(), ProgramError> {
pub fn load(&mut self, btf_fd: Option<impl AsFd>) -> Result<(), ProgramError> {
self.data.expected_attach_type = Some(bpf_attach_type::BPF_XDP);
load_program(BPF_PROG_TYPE_XDP, &mut self.data)
load_program(BPF_PROG_TYPE_XDP, &mut self.data, btf_fd)
}
/// Attaches the program to the given `interface`.

@ -3,7 +3,7 @@ use std::{
ffi::{CStr, CString},
io,
mem::{self, MaybeUninit},
os::fd::RawFd,
os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd},
slice,
};
@ -35,7 +35,7 @@ use crate::{
pub(crate) fn bpf_create_map(
name: &CStr,
def: &obj::Map,
btf_fd: Option<RawFd>,
btf_fd: Option<impl AsFd>,
kernel_version: KernelVersion,
) -> SysResult<c_long> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
@ -75,7 +75,7 @@ pub(crate) fn bpf_create_map(
_ => {
u.btf_key_type_id = m.def.btf_key_type_id;
u.btf_value_type_id = m.def.btf_value_type_id;
u.btf_fd = btf_fd.unwrap_or_default() as u32;
u.btf_fd = btf_fd.map(|fd| fd.as_fd().as_raw_fd()).unwrap_or_default() as u32;
}
}
}
@ -115,7 +115,7 @@ pub(crate) struct BpfLoadProgramAttrs<'a> {
pub(crate) license: &'a CStr,
pub(crate) kernel_version: u32,
pub(crate) expected_attach_type: Option<bpf_attach_type>,
pub(crate) prog_btf_fd: Option<RawFd>,
pub(crate) prog_btf_fd: Option<BorrowedFd<'a>>,
pub(crate) attach_btf_obj_fd: Option<u32>,
pub(crate) attach_btf_id: Option<u32>,
pub(crate) attach_prog_fd: Option<RawFd>,
@ -161,7 +161,7 @@ pub(crate) fn bpf_load_program(
let func_info_buf = aya_attr.func_info.func_info_bytes();
if let Some(btf_fd) = aya_attr.prog_btf_fd {
u.prog_btf_fd = btf_fd as u32;
u.prog_btf_fd = btf_fd.as_raw_fd() as u32;
if aya_attr.line_info_rec_size > 0 {
u.line_info = line_info_buf.as_ptr() as *const _ as u64;
u.line_info_cnt = aya_attr.line_info.len() as u32;
@ -551,7 +551,7 @@ pub(crate) fn bpf_load_btf(
raw_btf: &[u8],
log_buf: &mut [u8],
verifier_log_level: VerifierLogLevel,
) -> SysResult<c_long> {
) -> SysResult<OwnedFd> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_7 };
u.btf = raw_btf.as_ptr() as *const _ as u64;
@ -561,7 +561,9 @@ pub(crate) fn bpf_load_btf(
u.btf_log_buf = log_buf.as_mut_ptr() as u64;
u.btf_log_size = log_buf.len() as u32;
}
sys_bpf(bpf_cmd::BPF_BTF_LOAD, &attr)
let raw_fd = sys_bpf(bpf_cmd::BPF_BTF_LOAD, &attr)? as RawFd;
// SAFETY: BPF_BTF_LOAD returns a newly created file descriptor
Ok(unsafe { OwnedFd::from_raw_fd(raw_fd) })
}
pub(crate) fn bpf_btf_get_fd_by_id(id: u32) -> Result<RawFd, io::Error> {
@ -701,10 +703,9 @@ pub(crate) fn is_bpf_global_data_supported() -> bool {
}),
fd: None,
pinned: false,
btf_fd: None,
};
if let Ok(map_fd) = map_data.create("aya_global") {
if let Ok(map_fd) = map_data.create("aya_global", Option::<BorrowedFd>::None) {
insns[0].imm = map_fd;
let gpl = b"GPL\0";

@ -104,9 +104,12 @@ fn result_bytes(bpf: &Bpf) -> Vec<u8> {
fn load_and_attach_uprobe(prog_name: &str, func_name: &str, bytes: &[u8]) -> Bpf {
let mut bpf = Bpf::load(bytes).unwrap();
let Bpf {
programs, btf_fd, ..
} = &mut bpf;
let prog: &mut UProbe = bpf.program_mut(prog_name).unwrap().try_into().unwrap();
prog.load().unwrap();
let prog: &mut UProbe = programs.get_mut(prog_name).unwrap().try_into().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
prog.attach(Some(func_name), 0, "/proc/self/exe", None)
.unwrap();

@ -5,7 +5,9 @@ use std::{
time::Duration,
};
use aya::{maps::Array, programs::TracePoint, util::KernelVersion, BpfLoader, Btf, Endianness};
use aya::{
maps::Array, programs::TracePoint, util::KernelVersion, Bpf, BpfLoader, Btf, Endianness,
};
// In the tests below we often use values like 0xAAAAAAAA or -0x7AAAAAAA. Those values have no
// special meaning, they just have "nice" bit patterns that can be helpful while debugging.
@ -384,12 +386,17 @@ impl RelocationTestRunner {
loader.btf(None);
}
let mut bpf = loader.load(&self.ebpf).context("Loading eBPF failed")?;
let program: &mut TracePoint = bpf
.program_mut("bpf_prog")
let Bpf {
programs, btf_fd, ..
} = &mut bpf;
let program: &mut TracePoint = programs
.get_mut("bpf_prog")
.context("bpf_prog not found")?
.try_into()
.context("program not a tracepoint")?;
program.load().context("Loading tracepoint failed")?;
program
.load(btf_fd.as_ref())
.context("Loading tracepoint failed")?;
// Attach to sched_switch and wait some time to make sure it executed at least once
program
.attach("sched", "sched_switch")

@ -16,12 +16,15 @@ const RETRY_DURATION_MS: u64 = 10;
#[test]
fn long_name() {
let mut bpf = Bpf::load(crate::NAME_TEST).unwrap();
let name_prog: &mut Xdp = bpf
.program_mut("ihaveaverylongname")
let Bpf {
programs, btf_fd, ..
} = &mut bpf;
let name_prog: &mut Xdp = programs
.get_mut("ihaveaverylongname")
.unwrap()
.try_into()
.unwrap();
name_prog.load().unwrap();
name_prog.load(btf_fd.as_ref()).unwrap();
name_prog.attach("lo", XdpFlags::default()).unwrap();
// We used to be able to assert with bpftool that the program name was short.
@ -36,8 +39,11 @@ fn multiple_btf_maps() {
let map_1: Array<_, u64> = bpf.take_map("map_1").unwrap().try_into().unwrap();
let map_2: Array<_, u64> = bpf.take_map("map_2").unwrap().try_into().unwrap();
let prog: &mut TracePoint = bpf.program_mut("tracepoint").unwrap().try_into().unwrap();
prog.load().unwrap();
let Bpf {
programs, btf_fd, ..
} = &mut bpf;
let prog: &mut TracePoint = programs.get_mut("tracepoint").unwrap().try_into().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
prog.attach("sched", "sched_switch").unwrap();
thread::sleep(time::Duration::from_secs(3));
@ -110,8 +116,11 @@ macro_rules! assert_loaded {
#[test]
fn unload_xdp() {
let mut bpf = Bpf::load(crate::TEST).unwrap();
let prog: &mut Xdp = bpf.program_mut("test_xdp").unwrap().try_into().unwrap();
prog.load().unwrap();
let Bpf {
programs, btf_fd, ..
} = &mut bpf;
let prog: &mut Xdp = programs.get_mut("test_xdp").unwrap().try_into().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
assert_loaded!("test_xdp", true);
let link = prog.attach("lo", XdpFlags::default()).unwrap();
{
@ -121,7 +130,7 @@ fn unload_xdp() {
};
assert_loaded!("test_xdp", false);
prog.load().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
assert_loaded!("test_xdp", true);
prog.attach("lo", XdpFlags::default()).unwrap();
@ -135,8 +144,11 @@ fn unload_xdp() {
#[test]
fn unload_kprobe() {
let mut bpf = Bpf::load(crate::TEST).unwrap();
let prog: &mut KProbe = bpf.program_mut("test_kprobe").unwrap().try_into().unwrap();
prog.load().unwrap();
let Bpf {
programs, btf_fd, ..
} = &mut bpf;
let prog: &mut KProbe = programs.get_mut("test_kprobe").unwrap().try_into().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
assert_loaded!("test_kprobe", true);
let link = prog.attach("try_to_wake_up", 0).unwrap();
{
@ -146,7 +158,7 @@ fn unload_kprobe() {
};
assert_loaded!("test_kprobe", false);
prog.load().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
assert_loaded!("test_kprobe", true);
prog.attach("try_to_wake_up", 0).unwrap();
@ -160,13 +172,16 @@ fn unload_kprobe() {
#[test]
fn basic_tracepoint() {
let mut bpf = Bpf::load(crate::TEST).unwrap();
let prog: &mut TracePoint = bpf
.program_mut("test_tracepoint")
let Bpf {
programs, btf_fd, ..
} = &mut bpf;
let prog: &mut TracePoint = programs
.get_mut("test_tracepoint")
.unwrap()
.try_into()
.unwrap();
prog.load().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
assert_loaded!("test_tracepoint", true);
let link = prog.attach("syscalls", "sys_enter_kill").unwrap();
@ -177,7 +192,7 @@ fn basic_tracepoint() {
};
assert_loaded!("test_tracepoint", false);
prog.load().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
assert_loaded!("test_tracepoint", true);
prog.attach("syscalls", "sys_enter_kill").unwrap();
@ -191,9 +206,12 @@ fn basic_tracepoint() {
#[test]
fn basic_uprobe() {
let mut bpf = Bpf::load(crate::TEST).unwrap();
let prog: &mut UProbe = bpf.program_mut("test_uprobe").unwrap().try_into().unwrap();
let Bpf {
programs, btf_fd, ..
} = &mut bpf;
let prog: &mut UProbe = programs.get_mut("test_uprobe").unwrap().try_into().unwrap();
prog.load().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
assert_loaded!("test_uprobe", true);
let link = prog.attach(Some("sleep"), 0, "libc", None).unwrap();
@ -204,7 +222,7 @@ fn basic_uprobe() {
};
assert_loaded!("test_uprobe", false);
prog.load().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
assert_loaded!("test_uprobe", true);
prog.attach(Some("sleep"), 0, "libc", None).unwrap();
@ -224,8 +242,11 @@ fn pin_link() {
}
let mut bpf = Bpf::load(crate::TEST).unwrap();
let prog: &mut Xdp = bpf.program_mut("test_xdp").unwrap().try_into().unwrap();
prog.load().unwrap();
let Bpf {
programs, btf_fd, ..
} = &mut bpf;
let prog: &mut Xdp = programs.get_mut("test_xdp").unwrap().try_into().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
let link_id = prog.attach("lo", XdpFlags::default()).unwrap();
let link = prog.take_link(link_id).unwrap();
assert_loaded!("test_xdp", true);
@ -257,8 +278,11 @@ fn pin_lifecycle() {
// 1. Load Program and Pin
{
let mut bpf = Bpf::load(crate::PASS).unwrap();
let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap();
prog.load().unwrap();
let Bpf {
programs, btf_fd, ..
} = &mut bpf;
let prog: &mut Xdp = programs.get_mut("pass").unwrap().try_into().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
prog.pin("/sys/fs/bpf/aya-xdp-test-prog").unwrap();
}
@ -291,8 +315,11 @@ fn pin_lifecycle() {
// 4. Load a new version of the program, unpin link, and atomically replace old program
{
let mut bpf = Bpf::load(crate::PASS).unwrap();
let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap();
prog.load().unwrap();
let Bpf {
programs, btf_fd, ..
} = &mut bpf;
let prog: &mut Xdp = programs.get_mut("pass").unwrap().try_into().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
let link = PinnedLink::from_pin("/sys/fs/bpf/aya-xdp-test-lo")
.unwrap()
@ -311,12 +338,15 @@ fn pin_lifecycle_tracepoint() {
// 1. Load Program and Pin
{
let mut bpf = Bpf::load(crate::TEST).unwrap();
let prog: &mut TracePoint = bpf
.program_mut("test_tracepoint")
let Bpf {
programs, btf_fd, ..
} = &mut bpf;
let prog: &mut TracePoint = programs
.get_mut("test_tracepoint")
.unwrap()
.try_into()
.unwrap();
prog.load().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
prog.pin("/sys/fs/bpf/aya-tracepoint-test-prog").unwrap();
}
@ -365,8 +395,11 @@ fn pin_lifecycle_kprobe() {
// 1. Load Program and Pin
{
let mut bpf = Bpf::load(crate::TEST).unwrap();
let prog: &mut KProbe = bpf.program_mut("test_kprobe").unwrap().try_into().unwrap();
prog.load().unwrap();
let Bpf {
programs, btf_fd, ..
} = &mut bpf;
let prog: &mut KProbe = programs.get_mut("test_kprobe").unwrap().try_into().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
prog.pin("/sys/fs/bpf/aya-kprobe-test-prog").unwrap();
}
@ -423,8 +456,11 @@ fn pin_lifecycle_uprobe() {
// 1. Load Program and Pin
{
let mut bpf = Bpf::load(crate::TEST).unwrap();
let prog: &mut UProbe = bpf.program_mut("test_uprobe").unwrap().try_into().unwrap();
prog.load().unwrap();
let Bpf {
programs, btf_fd, ..
} = &mut bpf;
let prog: &mut UProbe = programs.get_mut("test_uprobe").unwrap().try_into().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
prog.pin("/sys/fs/bpf/aya-uprobe-test-prog").unwrap();
}

@ -58,8 +58,11 @@ async fn log() {
.unwrap();
}
let prog: &mut UProbe = bpf.program_mut("test_log").unwrap().try_into().unwrap();
prog.load().unwrap();
let Bpf {
programs, btf_fd, ..
} = &mut bpf;
let prog: &mut UProbe = programs.get_mut("test_log").unwrap().try_into().unwrap();
prog.load(btf_fd.as_ref()).unwrap();
prog.attach(Some("trigger_ebpf_program"), 0, "/proc/self/exe", None)
.unwrap();

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

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

Loading…
Cancel
Save