Use OwnedFd for MapData and Program

there are still plenty of TODOs mainly around places that I had to
call for as_raw_fd() which I need to vet to see if we can change for
BorrowedFd<'_> but there are a couple of gotchas regarding the
program/map fd borrowings which is currently affecting a doc test
reviewable/pr614/r3
Andrés Medina
parent d87f337496
commit a0cbb5428f

@ -3,7 +3,7 @@ use std::{
collections::{HashMap, HashSet},
ffi::CString,
fs, io,
os::{raw::c_int, unix::io::RawFd},
os::{fd::AsRawFd, raw::c_int, unix::io::RawFd},
path::{Path, PathBuf},
};
@ -398,7 +398,7 @@ impl<'a> BpfLoader<'a> {
pinned: false,
btf_fd,
};
let fd = match map.obj.pinning() {
match map.obj.pinning() {
PinningType::ByName => {
let path = match &self.map_pin_path {
Some(p) => p,
@ -406,31 +406,38 @@ impl<'a> BpfLoader<'a> {
};
// try to open map in case it's already pinned
match map.open_pinned(&name, path) {
Ok(fd) => {
Ok(_) => {
map.pinned = true;
fd as RawFd
}
Err(_) => {
let fd = map.create(&name)?;
map.create(&name)?;
map.pin(&name, path).map_err(|error| MapError::PinError {
name: Some(name.to_string()),
error,
})?;
fd
}
}
}
PinningType::None => map.create(&name)?,
};
// OK: we just loaded the map
let fd = map.fd.as_ref().unwrap();
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)
.map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(),
io_error,
})?;
// TODO (AM)
bpf_map_update_elem_ptr(
fd.as_raw_fd(),
&0 as *const _,
map.obj.data_mut().as_mut_ptr(),
0,
)
.map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(),
io_error,
})?;
}
if map.obj.section_kind() == BpfSectionKind::Rodata {
bpf_map_freeze(fd).map_err(|(_, io_error)| MapError::SyscallError {
// TODO (AM)
bpf_map_freeze(fd.as_raw_fd()).map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_freeze".to_owned(),
io_error,
})?;
@ -446,7 +453,14 @@ impl<'a> BpfLoader<'a> {
obj.relocate_maps(
maps.iter()
.map(|(s, data)| (s.as_str(), data.fd, &data.obj)),
// TODO (AM)
.map(|(s, data)| {
(
s.as_str(),
data.fd.as_ref().map(|f| f.as_raw_fd()),
&data.obj,
)
}),
&text_sections,
)?;
obj.relocate_calls(&text_sections)?;

@ -1,6 +1,7 @@
use std::{
borrow::{Borrow, BorrowMut},
marker::PhantomData,
os::fd::AsRawFd,
};
use crate::{
@ -65,12 +66,14 @@ impl<T: Borrow<MapData>, V: Pod> Array<T, V> {
check_bounds(data, *index)?;
let fd = data.fd_or_err()?;
let value = bpf_map_lookup_elem(fd, index, flags).map_err(|(_, io_error)| {
MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(),
io_error,
}
})?;
// TODO (AM)
let value =
bpf_map_lookup_elem(fd.as_raw_fd(), index, flags).map_err(|(_, io_error)| {
MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(),
io_error,
}
})?;
value.ok_or(MapError::KeyNotFound)
}
@ -92,12 +95,13 @@ impl<T: BorrowMut<MapData>, V: Pod> Array<T, V> {
let data = self.inner.borrow_mut();
check_bounds(data, index)?;
let fd = data.fd_or_err()?;
bpf_map_update_elem(fd, Some(&index), value.borrow(), flags).map_err(|(_, io_error)| {
MapError::SyscallError {
// TODO (AM)
bpf_map_update_elem(fd.as_raw_fd(), Some(&index), value.borrow(), flags).map_err(
|(_, io_error)| MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(),
io_error,
}
})?;
},
)?;
Ok(())
}
}

@ -1,6 +1,7 @@
use std::{
borrow::{Borrow, BorrowMut},
marker::PhantomData,
os::fd::AsRawFd,
};
use crate::{
@ -84,12 +85,13 @@ impl<T: Borrow<MapData>, V: Pod> PerCpuArray<T, V> {
check_bounds(data, *index)?;
let fd = data.fd_or_err()?;
let value = bpf_map_lookup_elem_per_cpu(fd, index, flags).map_err(|(_, io_error)| {
MapError::SyscallError {
// TODO (AM)
let value = bpf_map_lookup_elem_per_cpu(fd.as_raw_fd(), index, flags).map_err(
|(_, io_error)| MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(),
io_error,
}
})?;
},
)?;
value.ok_or(MapError::KeyNotFound)
}
@ -112,12 +114,13 @@ impl<T: BorrowMut<MapData>, V: Pod> PerCpuArray<T, V> {
check_bounds(data, index)?;
let fd = data.fd_or_err()?;
bpf_map_update_elem_per_cpu(fd, &index, &values, flags).map_err(|(_, io_error)| {
MapError::SyscallError {
// TODO (AM)
bpf_map_update_elem_per_cpu(fd.as_raw_fd(), &index, &values, flags).map_err(
|(_, io_error)| MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(),
io_error,
}
})?;
},
)?;
Ok(())
}
}

@ -79,12 +79,13 @@ impl<T: BorrowMut<MapData>> ProgramArray<T> {
let fd = data.fd_or_err()?;
let prog_fd = program.as_raw_fd();
bpf_map_update_elem(fd, Some(&index), &prog_fd, flags).map_err(|(_, io_error)| {
MapError::SyscallError {
// TODO (AM)
bpf_map_update_elem(fd.as_raw_fd(), Some(&index), &prog_fd, flags).map_err(
|(_, io_error)| MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(),
io_error,
}
})?;
},
)?;
Ok(())
}
@ -97,7 +98,8 @@ impl<T: BorrowMut<MapData>> ProgramArray<T> {
check_bounds(data, *index)?;
let fd = self.inner.borrow_mut().fd_or_err()?;
bpf_map_delete_elem(fd, index)
// TODO (AM)
bpf_map_delete_elem(fd.as_raw_fd(), index)
.map(|_| ())
.map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_delete_elem".to_owned(),

@ -1,5 +1,5 @@
//! A Bloom Filter.
use std::{borrow::Borrow, marker::PhantomData};
use std::{borrow::Borrow, marker::PhantomData, os::fd::AsRawFd};
use crate::{
maps::{check_v_size, MapData, MapError},
@ -52,7 +52,8 @@ impl<T: Borrow<MapData>, V: Pod> BloomFilter<T, V> {
pub fn contains(&self, mut value: &V, flags: u64) -> Result<(), MapError> {
let fd = self.inner.borrow().fd_or_err()?;
bpf_map_lookup_elem_ptr::<u32, _>(fd, None, &mut value, flags)
// TODO (AM)
bpf_map_lookup_elem_ptr::<u32, _>(fd.as_raw_fd(), None, &mut value, flags)
.map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(),
io_error,
@ -64,7 +65,8 @@ impl<T: Borrow<MapData>, V: Pod> BloomFilter<T, V> {
/// Inserts a value into the map.
pub fn insert(&self, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> {
let fd = self.inner.borrow().fd_or_err()?;
bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| {
// TODO (AM)
bpf_map_push_elem(fd.as_raw_fd(), value.borrow(), flags).map_err(|(_, io_error)| {
MapError::SyscallError {
call: "bpf_map_push_elem".to_owned(),
io_error,
@ -88,7 +90,7 @@ mod tests {
sys::{override_syscall, SysResult, Syscall},
};
use libc::{EFAULT, ENOENT};
use std::io;
use std::{env, fs::File, io, os::fd::OwnedFd};
fn new_obj_map() -> obj::Map {
obj::Map::Legacy(LegacyMap {
@ -175,7 +177,7 @@ mod tests {
fn test_new_ok() {
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -187,7 +189,7 @@ mod tests {
fn test_try_from_ok() {
let map_data = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -202,7 +204,7 @@ mod tests {
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -226,7 +228,7 @@ mod tests {
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -240,7 +242,7 @@ mod tests {
override_syscall(|_| sys_error(EFAULT));
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -263,7 +265,7 @@ mod tests {
});
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -274,4 +276,11 @@ mod tests {
Err(MapError::ElementNotFound)
));
}
fn create_fd() -> OwnedFd {
let dir = env::temp_dir();
File::create(dir.join("f1"))
.expect("unable to create file in tmpdir")
.into()
}
}

@ -1,6 +1,7 @@
use std::{
borrow::{Borrow, BorrowMut},
marker::PhantomData,
os::fd::AsRawFd,
};
use crate::{
@ -54,7 +55,8 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> HashMap<T, K, V> {
/// Returns a copy of the value associated with the key.
pub fn get(&self, key: &K, flags: u64) -> Result<V, MapError> {
let fd = self.inner.borrow().fd_or_err()?;
let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| {
// TODO (AM)
let value = bpf_map_lookup_elem(fd.as_raw_fd(), key, flags).map_err(|(_, io_error)| {
MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(),
io_error,
@ -105,7 +107,7 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> IterableMap<K, V> for HashMap<T, K, V>
#[cfg(test)]
mod tests {
use std::io;
use std::{env, fs::File, io, os::fd::OwnedFd};
use libc::{EFAULT, ENOENT};
@ -230,7 +232,7 @@ mod tests {
fn test_new_ok() {
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -242,7 +244,7 @@ mod tests {
fn test_try_from_ok() {
let map_data = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -267,7 +269,7 @@ mod tests {
symbol_index: None,
data: Vec::new(),
}),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -283,7 +285,7 @@ mod tests {
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -307,7 +309,7 @@ mod tests {
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -328,7 +330,7 @@ mod tests {
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -343,7 +345,7 @@ mod tests {
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -367,7 +369,7 @@ mod tests {
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -381,7 +383,7 @@ mod tests {
override_syscall(|_| sys_error(EFAULT));
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -404,7 +406,7 @@ mod tests {
});
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -441,7 +443,7 @@ mod tests {
});
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -490,7 +492,7 @@ mod tests {
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -523,7 +525,7 @@ mod tests {
});
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -558,7 +560,7 @@ mod tests {
});
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -596,7 +598,7 @@ mod tests {
});
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -635,7 +637,7 @@ mod tests {
});
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -680,7 +682,7 @@ mod tests {
});
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -695,4 +697,11 @@ mod tests {
assert!(matches!(iter.next(), Some(Ok((30, 300)))));
assert!(matches!(iter.next(), None));
}
fn create_fd() -> OwnedFd {
let dir = env::temp_dir();
File::create(dir.join("f1"))
.expect("unable to create file in tmpdir")
.into()
}
}

@ -1,4 +1,6 @@
//! Hash map types.
use std::os::fd::AsRawFd;
use crate::{
maps::MapError,
sys::{bpf_map_delete_elem, bpf_map_update_elem},
@ -21,7 +23,8 @@ pub(crate) fn insert<K: Pod, V: Pod>(
flags: u64,
) -> Result<(), MapError> {
let fd = map.fd_or_err()?;
bpf_map_update_elem(fd, Some(key), value, flags).map_err(|(_, io_error)| {
// TODO (AM)
bpf_map_update_elem(fd.as_raw_fd(), Some(key), value, flags).map_err(|(_, io_error)| {
MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(),
io_error,
@ -33,7 +36,8 @@ pub(crate) fn insert<K: Pod, V: Pod>(
pub(crate) fn remove<K: Pod>(map: &mut MapData, key: &K) -> Result<(), MapError> {
let fd = map.fd_or_err()?;
bpf_map_delete_elem(fd, key)
// TODO (AM)
bpf_map_delete_elem(fd.as_raw_fd(), key)
.map(|_| ())
.map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_delete_elem".to_owned(),

@ -2,6 +2,7 @@
use std::{
borrow::{Borrow, BorrowMut},
marker::PhantomData,
os::fd::AsRawFd,
};
use crate::{
@ -64,12 +65,14 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
/// Returns a slice of values - one for each CPU - associated with the key.
pub fn get(&self, key: &K, flags: u64) -> Result<PerCpuValues<V>, MapError> {
let fd = self.inner.borrow().fd_or_err()?;
let values = bpf_map_lookup_elem_per_cpu(fd, key, flags).map_err(|(_, io_error)| {
MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(),
io_error,
}
})?;
let values =
// TODO (AM)
bpf_map_lookup_elem_per_cpu(fd.as_raw_fd(), key, flags).map_err(|(_, io_error)| {
MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(),
io_error,
}
})?;
values.ok_or(MapError::KeyNotFound)
}
@ -122,7 +125,8 @@ impl<T: BorrowMut<MapData>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
flags: u64,
) -> Result<(), MapError> {
let fd = self.inner.borrow_mut().fd_or_err()?;
bpf_map_update_elem_per_cpu(fd, key.borrow(), &values, flags).map_err(
// TODO (AM)
bpf_map_update_elem_per_cpu(fd.as_raw_fd(), key.borrow(), &values, flags).map_err(
|(_, io_error)| MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(),
io_error,

@ -2,6 +2,7 @@
use std::{
borrow::{Borrow, BorrowMut},
marker::PhantomData,
os::fd::AsRawFd,
};
use crate::{
@ -128,7 +129,8 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
/// Returns a copy of the value associated with the longest prefix matching key in the LpmTrie.
pub fn get(&self, key: &Key<K>, flags: u64) -> Result<V, MapError> {
let fd = self.inner.borrow().fd_or_err()?;
let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| {
// TODO (AM)
let value = bpf_map_lookup_elem(fd.as_raw_fd(), key, flags).map_err(|(_, io_error)| {
MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(),
io_error,
@ -159,12 +161,13 @@ impl<T: BorrowMut<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
flags: u64,
) -> Result<(), MapError> {
let fd = self.inner.borrow().fd_or_err()?;
bpf_map_update_elem(fd, Some(key), value.borrow(), flags).map_err(|(_, io_error)| {
MapError::SyscallError {
// TODO (AM)
bpf_map_update_elem(fd.as_raw_fd(), Some(key), value.borrow(), flags).map_err(
|(_, io_error)| MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(),
io_error,
}
})?;
},
)?;
Ok(())
}
@ -174,7 +177,8 @@ impl<T: BorrowMut<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
/// Both the prefix and data must match exactly - this method does not do a longest prefix match.
pub fn remove(&mut self, key: &Key<K>) -> Result<(), MapError> {
let fd = self.inner.borrow().fd_or_err()?;
bpf_map_delete_elem(fd, key)
// TODO (AM)
bpf_map_delete_elem(fd.as_raw_fd(), key)
.map(|_| ())
.map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_delete_elem".to_owned(),
@ -207,7 +211,7 @@ mod tests {
sys::{override_syscall, SysResult, Syscall},
};
use libc::{EFAULT, ENOENT};
use std::{io, mem, net::Ipv4Addr};
use std::{env, fs::File, io, mem, net::Ipv4Addr, os::fd::OwnedFd};
fn new_obj_map() -> obj::Map {
obj::Map::Legacy(LegacyMap {
@ -311,7 +315,7 @@ mod tests {
fn test_new_ok() {
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -323,7 +327,7 @@ mod tests {
fn test_try_from_ok() {
let map_data = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -338,7 +342,7 @@ mod tests {
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -363,7 +367,7 @@ mod tests {
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -380,7 +384,7 @@ mod tests {
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -405,7 +409,7 @@ mod tests {
let mut map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -420,7 +424,7 @@ mod tests {
override_syscall(|_| sys_error(EFAULT));
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -445,7 +449,7 @@ mod tests {
});
let map = MapData {
obj: new_obj_map(),
fd: Some(42),
fd: Some(create_fd()),
pinned: false,
btf_fd: None,
};
@ -455,4 +459,11 @@ mod tests {
assert!(matches!(trie.get(&key, 0), Err(MapError::KeyNotFound)));
}
fn create_fd() -> OwnedFd {
let dir = env::temp_dir();
File::create(dir.join("f1"))
.expect("unable to create file in tmpdir")
.into()
}
}

@ -42,7 +42,7 @@ use std::{
marker::PhantomData,
mem,
ops::Deref,
os::fd::{AsRawFd, RawFd},
os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd},
path::Path,
ptr,
};
@ -185,11 +185,17 @@ pub enum MapError {
}
/// A map file descriptor.
pub struct MapFd(RawFd);
pub struct MapFd<'f>(BorrowedFd<'f>);
impl AsRawFd for MapFd {
impl AsRawFd for MapFd<'_> {
fn as_raw_fd(&self) -> RawFd {
self.0
self.0.as_raw_fd()
}
}
impl AsFd for MapFd<'_> {
fn as_fd(&self) -> BorrowedFd<'_> {
self.0.as_fd()
}
}
@ -474,7 +480,7 @@ pub(crate) fn check_v_size<V>(map: &MapData) -> Result<(), MapError> {
#[derive(Debug)]
pub struct MapData {
pub(crate) obj: obj::Map,
pub(crate) fd: Option<RawFd>,
pub(crate) fd: Option<OwnedFd>,
pub(crate) btf_fd: Option<RawFd>,
/// Indicates if this map has been pinned to bpffs
pub pinned: bool,
@ -482,7 +488,7 @@ pub struct MapData {
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) -> Result<(), MapError> {
if self.fd.is_some() {
return Err(MapError::AlreadyCreated { name: name.into() });
}
@ -500,18 +506,18 @@ impl MapData {
code,
io_error,
}
})? as RawFd;
})?;
self.fd = Some(fd);
Ok(fd)
Ok(())
}
pub(crate) fn open_pinned<P: AsRef<Path>>(
&mut self,
name: &str,
path: P,
) -> Result<RawFd, MapError> {
) -> Result<(), MapError> {
if self.fd.is_some() {
return Err(MapError::AlreadyCreated { name: name.into() });
}
@ -520,11 +526,10 @@ impl MapData {
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| MapError::SyscallError {
call: "BPF_OBJ_GET".to_string(),
io_error,
})? as RawFd;
})?;
self.fd = Some(fd);
Ok(fd)
Ok(())
}
/// Loads a map from a pinned path in bpffs.
@ -542,13 +547,15 @@ impl MapData {
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| MapError::SyscallError {
call: "BPF_OBJ_GET".to_owned(),
io_error,
})? as RawFd;
let info = bpf_map_get_info_by_fd(fd).map_err(|io_error| MapError::SyscallError {
call: "BPF_MAP_GET_INFO_BY_FD".to_owned(),
io_error,
})?;
// TODO (AM)
let info =
bpf_map_get_info_by_fd(fd.as_raw_fd()).map_err(|io_error| MapError::SyscallError {
call: "BPF_MAP_GET_INFO_BY_FD".to_owned(),
io_error,
})?;
Ok(MapData {
obj: parse_map_info(info, PinningType::ByName),
fd: Some(fd),
@ -562,11 +569,13 @@ impl MapData {
/// If loading from a BPF Filesystem (bpffs) you should use [`Map::from_pin`](crate::maps::MapData::from_pin).
/// This API is intended for cases where you have received a valid BPF FD from some other means.
/// For example, you received an FD over Unix Domain Socket.
pub fn from_fd(fd: RawFd) -> Result<MapData, MapError> {
let info = bpf_map_get_info_by_fd(fd).map_err(|io_error| MapError::SyscallError {
call: "BPF_OBJ_GET".to_owned(),
io_error,
})?;
pub fn from_fd(fd: OwnedFd) -> Result<MapData, MapError> {
// TODO (AM)
let info =
bpf_map_get_info_by_fd(fd.as_raw_fd()).map_err(|io_error| MapError::SyscallError {
call: "BPF_OBJ_GET".to_owned(),
io_error,
})?;
Ok(MapData {
obj: parse_map_info(info, PinningType::None),
@ -576,8 +585,11 @@ impl MapData {
})
}
pub(crate) fn fd_or_err(&self) -> Result<RawFd, MapError> {
self.fd.ok_or(MapError::NotCreated)
pub(crate) fn fd_or_err(&self) -> Result<BorrowedFd<'_>, MapError> {
self.fd
.as_ref()
.map(|f| f.as_fd())
.ok_or(MapError::NotCreated)
}
pub(crate) fn pin<P: AsRef<Path>>(&mut self, name: &str, path: P) -> Result<(), PinError> {
@ -585,7 +597,7 @@ impl MapData {
return Err(PinError::AlreadyPinned { name: name.into() });
}
let map_path = path.as_ref().join(name);
let fd = self.fd.ok_or(PinError::NoFd {
let fd = self.fd.as_ref().ok_or(PinError::NoFd {
name: name.to_string(),
})?;
let path_string = CString::new(map_path.to_string_lossy().into_owned()).map_err(|e| {
@ -593,9 +605,12 @@ impl MapData {
error: e.to_string(),
}
})?;
bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError {
name: "BPF_OBJ_PIN".to_string(),
io_error,
// TODO (AM): switch to BorrowedFd
bpf_pin_object(fd.as_raw_fd(), &path_string).map_err(|(_, io_error)| {
PinError::SyscallError {
name: "BPF_OBJ_PIN".to_string(),
io_error,
}
})?;
self.pinned = true;
Ok(())
@ -604,28 +619,32 @@ impl MapData {
/// Returns the file descriptor of the map.
///
/// Can be converted to [`RawFd`] using [`AsRawFd`].
pub fn fd(&self) -> Option<MapFd> {
self.fd.map(MapFd)
pub fn fd(&self) -> Option<MapFd<'_>> {
self.fd.as_ref().map(|fd| MapFd(fd.as_fd()))
}
}
impl Drop for MapData {
fn drop(&mut self) {
// TODO: Replace this with an OwnedFd once that is stabilized.
if let Some(fd) = self.fd.take() {
unsafe { libc::close(fd) };
}
impl MapData {
/// Attempts to duplicate MapData
///
/// Fails if if the inner file descriptor could not be cloned
// TODO (AM): should we return MapError? New variant? Maybe make MapError non_exhaustive?
pub fn try_clone(&self) -> io::Result<Self> {
let fd = self.fd.as_ref().map(|f| f.try_clone()).transpose()?;
Ok(MapData {
fd,
obj: self.obj.clone(),
btf_fd: self.btf_fd,
pinned: self.pinned,
})
}
}
// TODO (AM): DELETE?
impl Clone for MapData {
fn clone(&self) -> MapData {
MapData {
obj: self.obj.clone(),
fd: self.fd.map(|fd| unsafe { libc::dup(fd) }),
btf_fd: self.btf_fd,
pinned: self.pinned,
}
self.try_clone().unwrap()
}
}
@ -671,7 +690,8 @@ impl<K: Pod> Iterator for MapKeys<'_, K> {
}
};
match bpf_map_get_next_key(fd, self.key.as_ref()) {
// TODO (AM)
match bpf_map_get_next_key(fd.as_raw_fd(), self.key.as_ref()) {
Ok(Some(key)) => {
self.key = Some(key);
Some(Ok(key))
@ -874,8 +894,8 @@ mod tests {
});
let mut map = new_map();
assert!(matches!(map.create("foo"), Ok(42)));
assert_eq!(map.fd, Some(42));
map.create("foo").unwrap();
assert_eq!(map.fd.as_ref().unwrap().as_raw_fd(), 42);
assert!(matches!(
map.create("foo"),
Err(MapError::AlreadyCreated { .. })
@ -899,6 +919,6 @@ mod tests {
assert_eq!(code, -42);
assert_eq!(io_error.raw_os_error(), Some(EFAULT));
}
assert_eq!(map.fd, None);
assert!(map.fd.is_none());
}
}

@ -64,7 +64,7 @@ impl<T: BorrowMut<MapData> + Borrow<MapData>> AsRawFd for PerfEventArrayBuffer<T
/// A map that can be used to receive events from eBPF programs using the linux [`perf`] API.
///
/// Each element of a [`PerfEventArray`] is a separate [`PerfEventArrayBuffer`] which can be used
/// to receive events sent by eBPF programs that use `bpf_perf_event_output()`.
/// to receive events sent by eBPF programs that use `bpf_perf_event_output()`.
///
/// To receive events you need to:
/// * call [`PerfEventArray::open`]
@ -138,7 +138,7 @@ impl<T: BorrowMut<MapData> + Borrow<MapData>> AsRawFd for PerfEventArrayBuffer<T
///
/// In the example above the implementation of `poll_buffers()` and `poll.poll_readable()` is not
/// given. [`PerfEventArrayBuffer`] implements the [`AsRawFd`] trait, so you can implement polling
/// using any crate that can poll file descriptors, like [epoll], [mio] etc.
/// using any crate that can poll file descriptors, like [epoll], [mio] etc.
///
/// Perf buffers are internally implemented as ring buffers. If your eBPF programs produce large
/// amounts of data, in order not to lose events you might want to process each
@ -186,7 +186,8 @@ impl<T: BorrowMut<MapData> + Borrow<MapData>> PerfEventArray<T> {
let map_data: &MapData = self.map.deref().borrow();
let map_fd = map_data.fd_or_err().unwrap();
let buf = PerfBuffer::open(index, self.page_size, page_count.unwrap_or(2))?;
bpf_map_update_elem(map_fd, Some(&index), &buf.as_raw_fd(), 0)
// TODO (AM)
bpf_map_update_elem(map_fd.as_raw_fd(), Some(&index), &buf.as_raw_fd(), 0)
.map_err(|(_, io_error)| io_error)?;
Ok(PerfEventArrayBuffer {

@ -2,6 +2,7 @@
use std::{
borrow::{Borrow, BorrowMut},
marker::PhantomData,
os::fd::AsRawFd,
};
use crate::{
@ -64,7 +65,8 @@ impl<T: BorrowMut<MapData>, V: Pod> Queue<T, V> {
pub fn pop(&mut self, flags: u64) -> Result<V, MapError> {
let fd = self.inner.borrow().fd_or_err()?;
let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err(
// TODO (AM)
let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd.as_raw_fd(), None, flags).map_err(
|(_, io_error)| MapError::SyscallError {
call: "bpf_map_lookup_and_delete_elem".to_owned(),
io_error,
@ -80,7 +82,8 @@ impl<T: BorrowMut<MapData>, V: Pod> Queue<T, V> {
/// [`MapError::SyscallError`] if `bpf_map_update_elem` fails.
pub fn push(&mut self, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> {
let fd = self.inner.borrow().fd_or_err()?;
bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| {
// TODO (AM)
bpf_map_push_elem(fd.as_raw_fd(), value.borrow(), flags).map_err(|(_, io_error)| {
MapError::SyscallError {
call: "bpf_map_push_elem".to_owned(),
io_error,

@ -83,7 +83,8 @@ impl<T: Borrow<MapData>, K: Pod> SockHash<T, K> {
/// Returns the fd of the socket stored at the given key.
pub fn get(&self, key: &K, flags: u64) -> Result<RawFd, MapError> {
let fd = self.inner.borrow().fd_or_err()?;
let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| {
// TODO (AM)
let value = bpf_map_lookup_elem(fd.as_raw_fd(), key, flags).map_err(|(_, io_error)| {
MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(),
io_error,
@ -109,7 +110,8 @@ impl<T: Borrow<MapData>, K: Pod> SockHash<T, K> {
/// The returned file descriptor can be used to attach programs that work with
/// socket maps, like [`SkMsg`](crate::programs::SkMsg) and [`SkSkb`](crate::programs::SkSkb).
pub fn fd(&self) -> Result<SockMapFd, MapError> {
Ok(SockMapFd(self.inner.borrow().fd_or_err()?))
// TODO (AM)
Ok(SockMapFd(self.inner.borrow().fd_or_err()?.as_raw_fd()))
}
}

@ -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
///
@ -65,7 +65,8 @@ impl<T: Borrow<MapData>> SockMap<T> {
/// The returned file descriptor can be used to attach programs that work with
/// socket maps, like [`SkMsg`](crate::programs::SkMsg) and [`SkSkb`](crate::programs::SkSkb).
pub fn fd(&self) -> Result<SockMapFd, MapError> {
Ok(SockMapFd(self.inner.borrow().fd_or_err()?))
// TODO (AM)
Ok(SockMapFd(self.inner.borrow().fd_or_err()?.as_raw_fd()))
}
}
@ -75,7 +76,8 @@ impl<T: BorrowMut<MapData>> SockMap<T> {
let data = self.inner.borrow_mut();
let fd = data.fd_or_err()?;
check_bounds(data, index)?;
bpf_map_update_elem(fd, Some(&index), &socket.as_raw_fd(), flags).map_err(
// TODO (AM)
bpf_map_update_elem(fd.as_raw_fd(), Some(&index), &socket.as_raw_fd(), flags).map_err(
|(_, io_error)| MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(),
io_error,
@ -89,7 +91,8 @@ impl<T: BorrowMut<MapData>> SockMap<T> {
let data = self.inner.borrow_mut();
let fd = data.fd_or_err()?;
check_bounds(data, *index)?;
bpf_map_delete_elem(fd, index)
// TODO (AM)
bpf_map_delete_elem(fd.as_raw_fd(), index)
.map(|_| ())
.map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_delete_elem".to_owned(),

@ -2,6 +2,7 @@
use std::{
borrow::{Borrow, BorrowMut},
marker::PhantomData,
os::fd::AsRawFd,
};
use crate::{
@ -64,7 +65,8 @@ impl<T: BorrowMut<MapData>, V: Pod> Stack<T, V> {
pub fn pop(&mut self, flags: u64) -> Result<V, MapError> {
let fd = self.inner.borrow().fd_or_err()?;
let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err(
// TODO (AM)
let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd.as_raw_fd(), None, flags).map_err(
|(_, io_error)| MapError::SyscallError {
call: "bpf_map_lookup_and_delete_elem".to_owned(),
io_error,
@ -80,12 +82,13 @@ impl<T: BorrowMut<MapData>, V: Pod> Stack<T, V> {
/// [`MapError::SyscallError`] if `bpf_map_update_elem` fails.
pub fn push(&mut self, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> {
let fd = self.inner.borrow().fd_or_err()?;
bpf_map_update_elem(fd, None::<&u32>, value.borrow(), flags).map_err(|(_, io_error)| {
MapError::SyscallError {
// TODO (AM)
bpf_map_update_elem(fd.as_raw_fd(), None::<&u32>, value.borrow(), flags).map_err(
|(_, io_error)| MapError::SyscallError {
call: "bpf_map_update_elem".to_owned(),
io_error,
}
})?;
},
)?;
Ok(())
}
}

@ -1,7 +1,9 @@
//! A hash map of kernel or user space stack traces.
//!
//! See [`StackTraceMap`] for documentation and examples.
use std::{borrow::Borrow, collections::BTreeMap, fs, io, mem, path::Path, str::FromStr};
use std::{
borrow::Borrow, collections::BTreeMap, fs, io, mem, os::fd::AsRawFd, path::Path, str::FromStr,
};
use crate::{
maps::{IterableMap, MapData, MapError, MapIter, MapKeys},
@ -18,7 +20,7 @@ use crate::{
/// # Minimum kernel version
///
/// The minimum kernel version required to use this feature is 4.6.
///
///
/// # Examples
///
/// ```no_run
@ -105,7 +107,8 @@ impl<T: Borrow<MapData>> StackTraceMap<T> {
let fd = self.inner.borrow().fd_or_err()?;
let mut frames = vec![0; self.max_stack_depth];
bpf_map_lookup_elem_ptr(fd, Some(stack_id), frames.as_mut_ptr(), flags)
// TODO (AM)
bpf_map_lookup_elem_ptr(fd.as_raw_fd(), Some(stack_id), frames.as_mut_ptr(), flags)
.map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_lookup_elem".to_owned(),
io_error,

@ -1,5 +1,5 @@
//! Cgroup device programs.
use std::os::fd::{AsRawFd, RawFd};
use std::os::fd::AsRawFd;
use crate::{
generated::{bpf_attach_type::BPF_CGROUP_DEVICE, bpf_prog_type::BPF_PROG_TYPE_CGROUP_DEVICE},
@ -64,28 +64,31 @@ impl CgroupDevice {
let k_ver = kernel_version().unwrap();
if k_ver >= (5, 7, 0) {
let link_fd = bpf_link_create(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE, None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
},
)? as RawFd;
// TODO (AM)
let link_fd =
bpf_link_create(prog_fd.as_raw_fd(), cgroup_fd, BPF_CGROUP_DEVICE, None, 0)
.map_err(|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
})?;
self.data
.links
.insert(CgroupDeviceLink::new(CgroupDeviceLinkInner::Fd(
FdLink::new(link_fd),
)))
} else {
bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE).map_err(|(_, io_error)| {
ProgramError::SyscallError {
// TODO (AM)
bpf_prog_attach(prog_fd.as_raw_fd(), cgroup_fd, BPF_CGROUP_DEVICE).map_err(
|(_, io_error)| ProgramError::SyscallError {
call: "bpf_prog_attach".to_owned(),
io_error,
}
})?;
},
)?;
self.data
.links
.insert(CgroupDeviceLink::new(CgroupDeviceLinkInner::ProgAttach(
ProgAttachLink::new(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE),
// TODO (AM)
ProgAttachLink::new(prog_fd.as_raw_fd(), cgroup_fd, BPF_CGROUP_DEVICE),
)))
}
}

@ -1,9 +1,5 @@
//! Cgroup skb programs.
use std::{
hash::Hash,
os::fd::{AsRawFd, RawFd},
path::Path,
};
use std::{hash::Hash, os::fd::AsRawFd, path::Path};
use crate::{
generated::{
@ -98,29 +94,31 @@ impl CgroupSkb {
};
let k_ver = kernel_version().unwrap();
if k_ver >= (5, 7, 0) {
let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
// TODO (AM)
let link_fd = bpf_link_create(prog_fd.as_raw_fd(), cgroup_fd, attach_type, None, 0)
.map_err(|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
},
)? as RawFd;
})?;
self.data
.links
.insert(CgroupSkbLink::new(CgroupSkbLinkInner::Fd(FdLink::new(
link_fd,
))))
} else {
bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| {
ProgramError::SyscallError {
// TODO (AM)
bpf_prog_attach(prog_fd.as_raw_fd(), cgroup_fd, attach_type).map_err(
|(_, io_error)| ProgramError::SyscallError {
call: "bpf_prog_attach".to_owned(),
io_error,
}
})?;
},
)?;
self.data
.links
.insert(CgroupSkbLink::new(CgroupSkbLinkInner::ProgAttach(
ProgAttachLink::new(prog_fd, cgroup_fd, attach_type),
// TODO (AM)
ProgAttachLink::new(prog_fd.as_raw_fd(), cgroup_fd, attach_type),
)))
}
}

@ -1,11 +1,7 @@
//! Cgroup socket programs.
pub use aya_obj::programs::CgroupSockAttachType;
use std::{
hash::Hash,
os::fd::{AsRawFd, RawFd},
path::Path,
};
use std::{hash::Hash, os::fd::AsRawFd, path::Path};
use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCK,
@ -73,29 +69,31 @@ impl CgroupSock {
let attach_type = self.data.expected_attach_type.unwrap();
let k_ver = kernel_version().unwrap();
if k_ver >= (5, 7, 0) {
let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
// TODO (AM)
let link_fd = bpf_link_create(prog_fd.as_raw_fd(), cgroup_fd, attach_type, None, 0)
.map_err(|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
},
)? as RawFd;
})?;
self.data
.links
.insert(CgroupSockLink::new(CgroupSockLinkInner::Fd(FdLink::new(
link_fd,
))))
} else {
bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| {
ProgramError::SyscallError {
// TODO (AM)
bpf_prog_attach(prog_fd.as_raw_fd(), cgroup_fd, attach_type).map_err(
|(_, io_error)| ProgramError::SyscallError {
call: "bpf_prog_attach".to_owned(),
io_error,
}
})?;
},
)?;
self.data
.links
.insert(CgroupSockLink::new(CgroupSockLinkInner::ProgAttach(
ProgAttachLink::new(prog_fd, cgroup_fd, attach_type),
// TODO (AM)
ProgAttachLink::new(prog_fd.as_raw_fd(), cgroup_fd, attach_type),
)))
}
}

@ -1,11 +1,7 @@
//! Cgroup socket address programs.
pub use aya_obj::programs::CgroupSockAddrAttachType;
use std::{
hash::Hash,
os::fd::{AsRawFd, RawFd},
path::Path,
};
use std::{hash::Hash, os::fd::AsRawFd, path::Path};
use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
@ -74,28 +70,30 @@ impl CgroupSockAddr {
let attach_type = self.data.expected_attach_type.unwrap();
let k_ver = kernel_version().unwrap();
if k_ver >= (5, 7, 0) {
let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
// TODO (AM)
let link_fd = bpf_link_create(prog_fd.as_raw_fd(), cgroup_fd, attach_type, None, 0)
.map_err(|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
},
)? as RawFd;
})?;
self.data
.links
.insert(CgroupSockAddrLink::new(CgroupSockAddrLinkInner::Fd(
FdLink::new(link_fd),
)))
} else {
bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| {
ProgramError::SyscallError {
// TODO (AM)
bpf_prog_attach(prog_fd.as_raw_fd(), cgroup_fd, attach_type).map_err(
|(_, io_error)| ProgramError::SyscallError {
call: "bpf_prog_attach".to_owned(),
io_error,
}
})?;
},
)?;
self.data.links.insert(CgroupSockAddrLink::new(
CgroupSockAddrLinkInner::ProgAttach(ProgAttachLink::new(
prog_fd,
// TODO (AM)
prog_fd.as_raw_fd(),
cgroup_fd,
attach_type,
)),

@ -1,11 +1,7 @@
//! Cgroup socket option programs.
pub use aya_obj::programs::CgroupSockoptAttachType;
use std::{
hash::Hash,
os::fd::{AsRawFd, RawFd},
path::Path,
};
use std::{hash::Hash, os::fd::AsRawFd, path::Path};
use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCKOPT,
@ -71,29 +67,31 @@ impl CgroupSockopt {
let attach_type = self.data.expected_attach_type.unwrap();
let k_ver = kernel_version().unwrap();
if k_ver >= (5, 7, 0) {
let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
// TODO (AM)
let link_fd = bpf_link_create(prog_fd.as_raw_fd(), cgroup_fd, attach_type, None, 0)
.map_err(|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
},
)? as RawFd;
})?;
self.data
.links
.insert(CgroupSockoptLink::new(CgroupSockoptLinkInner::Fd(
FdLink::new(link_fd),
)))
} else {
bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| {
ProgramError::SyscallError {
// TODO (AM)
bpf_prog_attach(prog_fd.as_raw_fd(), cgroup_fd, attach_type).map_err(
|(_, io_error)| ProgramError::SyscallError {
call: "bpf_prog_attach".to_owned(),
io_error,
}
})?;
},
)?;
self.data
.links
.insert(CgroupSockoptLink::new(CgroupSockoptLinkInner::ProgAttach(
ProgAttachLink::new(prog_fd, cgroup_fd, attach_type),
// TODO (AM)
ProgAttachLink::new(prog_fd.as_raw_fd(), cgroup_fd, attach_type),
)))
}
}

@ -1,8 +1,5 @@
//! Cgroup sysctl programs.
use std::{
hash::Hash,
os::fd::{AsRawFd, RawFd},
};
use std::{hash::Hash, os::fd::AsRawFd};
use crate::{
generated::{bpf_attach_type::BPF_CGROUP_SYSCTL, bpf_prog_type::BPF_PROG_TYPE_CGROUP_SYSCTL},
@ -66,29 +63,32 @@ impl CgroupSysctl {
let k_ver = kernel_version().unwrap();
if k_ver >= (5, 7, 0) {
let link_fd = bpf_link_create(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL, None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
},
)? as RawFd;
// TODO (AM)
let link_fd =
bpf_link_create(prog_fd.as_raw_fd(), cgroup_fd, BPF_CGROUP_SYSCTL, None, 0)
.map_err(|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
})?;
self.data
.links
.insert(CgroupSysctlLink::new(CgroupSysctlLinkInner::Fd(
FdLink::new(link_fd),
)))
} else {
bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL).map_err(|(_, io_error)| {
ProgramError::SyscallError {
// TODO (AM)
bpf_prog_attach(prog_fd.as_raw_fd(), cgroup_fd, BPF_CGROUP_SYSCTL).map_err(
|(_, io_error)| ProgramError::SyscallError {
call: "bpf_prog_attach".to_owned(),
io_error,
}
})?;
},
)?;
self.data
.links
.insert(CgroupSysctlLink::new(CgroupSysctlLinkInner::ProgAttach(
ProgAttachLink::new(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL),
// TODO (AM)
ProgAttachLink::new(prog_fd.as_raw_fd(), cgroup_fd, BPF_CGROUP_SYSCTL),
)))
}
}

@ -42,9 +42,11 @@ pub enum ExtensionError {
/// 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")?;
/// ext.attach()?;
/// // TODO (AM): can't borrow here becauase prog_fd is holding a reference already
/// // need to confirm what the API wants to be
/// // let ext: &mut Extension = bpf.program_mut("extension").unwrap().try_into()?;
/// // ext.load(prog_fd, "function_to_replace")?;
/// // ext.attach()?;
/// Ok::<(), aya::BpfError>(())
/// ```
#[derive(Debug)]
@ -90,11 +92,18 @@ impl Extension {
let target_fd = self.data.attach_prog_fd.ok_or(ProgramError::NotLoaded)?;
let btf_id = self.data.attach_btf_id.ok_or(ProgramError::NotLoaded)?;
// the attach type must be set as 0, which is bpf_attach_type::BPF_CGROUP_INET_INGRESS
let link_fd = bpf_link_create(prog_fd, target_fd, BPF_CGROUP_INET_INGRESS, Some(btf_id), 0)
.map_err(|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
})? as RawFd;
// TODO (AM)
let link_fd = bpf_link_create(
prog_fd.as_raw_fd(),
target_fd,
BPF_CGROUP_INET_INGRESS,
Some(btf_id),
0,
)
.map_err(|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
})?;
self.data
.links
.insert(ExtensionLink::new(FdLink::new(link_fd)))
@ -120,11 +129,18 @@ impl Extension {
let (_, btf_id) = get_btf_info(target_fd, func_name)?;
let prog_fd = self.data.fd_or_err()?;
// the attach type must be set as 0, which is bpf_attach_type::BPF_CGROUP_INET_INGRESS
let link_fd = bpf_link_create(prog_fd, target_fd, BPF_CGROUP_INET_INGRESS, Some(btf_id), 0)
.map_err(|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
})? as RawFd;
// TODO (AM)
let link_fd = bpf_link_create(
prog_fd.as_raw_fd(),
target_fd,
BPF_CGROUP_INET_INGRESS,
Some(btf_id),
0,
)
.map_err(|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
})?;
self.data
.links
.insert(ExtensionLink::new(FdLink::new(link_fd)))

@ -6,7 +6,7 @@ use std::{
collections::{hash_map::Entry, HashMap},
ffi::CString,
io,
os::fd::RawFd,
os::fd::{AsRawFd, OwnedFd, RawFd},
path::{Path, PathBuf},
};
@ -84,11 +84,11 @@ pub struct FdLinkId(pub(crate) RawFd);
/// A file descriptor link.
#[derive(Debug)]
pub struct FdLink {
pub(crate) fd: RawFd,
pub(crate) fd: OwnedFd,
}
impl FdLink {
pub(crate) fn new(fd: RawFd) -> FdLink {
pub(crate) fn new(fd: OwnedFd) -> FdLink {
FdLink { fd }
}
@ -128,9 +128,12 @@ impl FdLink {
error: e.to_string(),
}
})?;
bpf_pin_object(self.fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError {
name: "BPF_OBJ_PIN".to_string(),
io_error,
// TODO (AM)
bpf_pin_object(self.fd.as_raw_fd(), &path_string).map_err(|(_, io_error)| {
PinError::SyscallError {
name: "BPF_OBJ_PIN".to_string(),
io_error,
}
})?;
Ok(PinnedLink::new(PathBuf::from(path.as_ref()), self))
}
@ -140,7 +143,8 @@ impl Link for FdLink {
type Id = FdLinkId;
fn id(&self) -> Self::Id {
FdLinkId(self.fd)
// TODO (AM)
FdLinkId(self.fd.as_raw_fd())
}
fn detach(self) -> Result<(), ProgramError> {
@ -159,12 +163,6 @@ impl From<PinnedLink> for FdLink {
}
}
impl Drop for FdLink {
fn drop(&mut self) {
unsafe { close(self.fd) };
}
}
/// A pinned file descriptor link.
///
/// This link has been pinned to the BPF filesystem. On drop, the file descriptor that backs
@ -189,7 +187,7 @@ impl PinnedLink {
call: "BPF_OBJ_GET".to_string(),
code,
io_error,
})? as RawFd;
})?;
Ok(PinnedLink::new(
path.as_ref().to_path_buf(),
FdLink::new(fd),
@ -329,7 +327,7 @@ pub enum LinkError {
#[cfg(test)]
mod tests {
use std::{cell::RefCell, env, fs::File, mem, os::unix::io::AsRawFd, rc::Rc};
use std::{cell::RefCell, env, fs::File, rc::Rc};
use crate::{programs::ProgramError, sys::override_syscall};
@ -469,10 +467,7 @@ mod tests {
fn test_pin() {
let dir = env::temp_dir();
let f1 = File::create(dir.join("f1")).expect("unable to create file in tmpdir");
let fd_link = FdLink::new(f1.as_raw_fd());
// leak the fd, it will get closed when our pinned link is dropped
mem::forget(f1);
let fd_link = FdLink::new(f1.into());
// override syscall to allow for pin to happen in our tmpdir
override_syscall(|_| Ok(0));

@ -64,14 +64,18 @@ impl LircMode2 {
let prog_fd = self.data.fd_or_err()?;
let lircdev_fd = lircdev.as_raw_fd();
bpf_prog_attach(prog_fd, lircdev_fd, BPF_LIRC_MODE2).map_err(|(_, io_error)| {
ProgramError::SyscallError {
// TODO (AM)
bpf_prog_attach(prog_fd.as_raw_fd(), lircdev_fd, BPF_LIRC_MODE2).map_err(
|(_, io_error)| ProgramError::SyscallError {
call: "bpf_prog_attach".to_owned(),
io_error,
}
})?;
},
)?;
self.data.links.insert(LircLink::new(prog_fd, lircdev_fd))
// TODO (AM)
self.data
.links
.insert(LircLink::new(prog_fd.as_raw_fd(), lircdev_fd))
}
/// Detaches the program.

@ -68,7 +68,10 @@ use libc::ENOSPC;
use std::{
ffi::CString,
io,
os::unix::io::{AsRawFd, RawFd},
os::{
fd::{AsFd, BorrowedFd, OwnedFd},
unix::io::{AsRawFd, RawFd},
},
path::{Path, PathBuf},
};
use thiserror::Error;
@ -215,11 +218,17 @@ pub enum ProgramError {
/// A [`Program`] file descriptor.
#[derive(Copy, Clone)]
pub struct ProgramFd(RawFd);
pub struct ProgramFd<'f>(BorrowedFd<'f>);
impl AsRawFd for ProgramFd {
impl AsRawFd for ProgramFd<'_> {
fn as_raw_fd(&self) -> RawFd {
self.0
self.0.as_raw_fd()
}
}
impl AsFd for ProgramFd<'_> {
fn as_fd(&self) -> BorrowedFd<'_> {
self.0.as_fd()
}
}
@ -406,7 +415,7 @@ impl Program {
pub(crate) struct ProgramData<T: Link> {
pub(crate) name: Option<String>,
pub(crate) obj: Option<(obj::Program, obj::Function)>,
pub(crate) fd: Option<RawFd>,
pub(crate) fd: Option<OwnedFd>,
pub(crate) links: LinkMap<T>,
pub(crate) expected_attach_type: Option<bpf_attach_type>,
pub(crate) attach_btf_obj_fd: Option<u32>,
@ -443,7 +452,7 @@ impl<T: Link> ProgramData<T> {
pub(crate) fn from_bpf_prog_info(
name: Option<String>,
fd: RawFd,
fd: OwnedFd,
path: &Path,
info: bpf_prog_info,
) -> Result<ProgramData<T>, ProgramError> {
@ -489,11 +498,14 @@ impl<T: Link> ProgramData<T> {
bpf_get_object(&path_string).map_err(|(_, io_error)| ProgramError::SyscallError {
call: "bpf_obj_get".to_owned(),
io_error,
})? as RawFd;
})?;
let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| ProgramError::SyscallError {
call: "bpf_prog_get_info_by_fd".to_owned(),
io_error,
// TODO: AM
let info = bpf_prog_get_info_by_fd(fd.as_raw_fd()).map_err(|io_error| {
ProgramError::SyscallError {
call: "bpf_prog_get_info_by_fd".to_owned(),
io_error,
}
})?;
let info = ProgramInfo(info);
@ -503,8 +515,11 @@ impl<T: Link> ProgramData<T> {
}
impl<T: Link> ProgramData<T> {
fn fd_or_err(&self) -> Result<RawFd, ProgramError> {
self.fd.ok_or(ProgramError::NotLoaded)
fn fd_or_err(&self) -> Result<BorrowedFd<'_>, ProgramError> {
self.fd
.as_ref()
.map(|f| f.as_fd())
.ok_or(ProgramError::NotLoaded)
}
pub(crate) fn take_link(&mut self, link_id: T::Id) -> Result<T, ProgramError> {
@ -514,10 +529,7 @@ impl<T: Link> ProgramData<T> {
fn unload_program<T: Link>(data: &mut ProgramData<T>) -> Result<(), ProgramError> {
data.links.remove_all()?;
let fd = data.fd.take().ok_or(ProgramError::NotLoaded)?;
unsafe {
libc::close(fd);
}
let _ = data.fd.take().ok_or(ProgramError::NotLoaded)?;
Ok(())
}
@ -525,7 +537,7 @@ fn pin_program<T: Link, P: AsRef<Path>>(
data: &mut ProgramData<T>,
path: P,
) -> Result<(), PinError> {
let fd = data.fd.ok_or(PinError::NoFd {
let fd = data.fd.as_ref().map(|f| f.as_fd()).ok_or(PinError::NoFd {
name: data
.name
.as_ref()
@ -537,9 +549,12 @@ fn pin_program<T: Link, P: AsRef<Path>>(
error: e.to_string(),
}
})?;
bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError {
name: "BPF_OBJ_PIN".to_string(),
io_error,
// TODO (AM)
bpf_pin_object(fd.as_raw_fd(), &path_string).map_err(|(_, io_error)| {
PinError::SyscallError {
name: "BPF_OBJ_PIN".to_string(),
io_error,
}
})?;
Ok(())
}
@ -620,7 +635,7 @@ fn load_program<T: Link>(
match ret {
Ok(prog_fd) => {
*fd = Some(prog_fd as RawFd);
*fd = Some(prog_fd);
Ok(())
}
Err((_, io_error)) => {
@ -729,8 +744,8 @@ macro_rules! impl_fd {
$(
impl $struct_name {
/// Returns the file descriptor of this Program.
pub fn fd(&self) -> Option<ProgramFd> {
self.data.fd.map(|fd| ProgramFd(fd))
pub fn fd(&self) -> Option<ProgramFd<'_>> {
self.data.fd.as_ref().map(|fd| ProgramFd(fd.as_fd()))
}
}
)+
@ -961,15 +976,16 @@ impl ProgramInfo {
bpf_get_object(&path_string).map_err(|(_, io_error)| ProgramError::SyscallError {
call: "BPF_OBJ_GET".to_owned(),
io_error,
})? as RawFd;
})?;
let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| ProgramError::SyscallError {
call: "bpf_prog_get_info_by_fd".to_owned(),
io_error,
// TODO (AM)
let info = bpf_prog_get_info_by_fd(fd.as_raw_fd()).map_err(|io_error| {
ProgramError::SyscallError {
call: "bpf_prog_get_info_by_fd".to_owned(),
io_error,
}
})?;
unsafe {
libc::close(fd);
}
Ok(ProgramInfo(info))
}
}

@ -80,7 +80,7 @@ pub(crate) fn perf_attach(prog_fd: RawFd, fd: RawFd) -> Result<PerfLinkInner, Pr
call: "bpf_link_create".to_owned(),
io_error,
}
})? as RawFd;
})?;
Ok(PerfLinkInner::FdLink(FdLink::new(link_fd)))
} else {
perf_attach_either(prog_fd, fd, None, None)

@ -1,5 +1,7 @@
//! Perf event programs.
use std::os::fd::AsRawFd;
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,
};
@ -169,7 +171,8 @@ impl PerfEvent {
io_error,
})? as i32;
let link = perf_attach(self.data.fd_or_err()?, fd)?;
// TODO (AM)
let link = perf_attach(self.data.fd_or_err()?.as_raw_fd(), fd)?;
self.data.links.insert(PerfEventLink::new(link))
}

@ -2,6 +2,7 @@ use libc::pid_t;
use std::{
fs::{self, OpenOptions},
io::{self, Write},
os::fd::AsRawFd,
path::Path,
process,
sync::atomic::{AtomicUsize, Ordering},
@ -53,7 +54,8 @@ pub(crate) fn attach<T: Link + From<PerfLinkInner>>(
if k_ver < (4, 17, 0) {
let (fd, event_alias) = create_as_trace_point(kind, fn_name, offset, pid)?;
let link = T::from(perf_attach_debugfs(
program_data.fd_or_err()?,
// TODO (AM)
program_data.fd_or_err()?.as_raw_fd(),
fd,
kind,
event_alias,
@ -62,7 +64,8 @@ pub(crate) fn attach<T: Link + From<PerfLinkInner>>(
};
let fd = create_as_probe(kind, fn_name, offset, pid)?;
let link = T::from(perf_attach(program_data.fd_or_err()?, fd)?);
// TODO (AM)
let link = T::from(perf_attach(program_data.fd_or_err()?.as_raw_fd(), fd)?);
program_data.links.insert(link)
}

@ -1,4 +1,4 @@
use std::os::fd::{AsRawFd, RawFd};
use std::os::fd::AsRawFd;
use crate::{
generated::{bpf_attach_type::BPF_SK_LOOKUP, bpf_prog_type::BPF_PROG_TYPE_SK_LOOKUP},
@ -64,12 +64,12 @@ impl SkLookup {
let prog_fd = self.data.fd_or_err()?;
let netns_fd = netns.as_raw_fd();
let link_fd = bpf_link_create(prog_fd, netns_fd, BPF_SK_LOOKUP, None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
// TODO (AM)
let link_fd = bpf_link_create(prog_fd.as_raw_fd(), netns_fd, BPF_SK_LOOKUP, None, 0)
.map_err(|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
},
)? as RawFd;
})?;
self.data
.links
.insert(SkLookupLink::new(FdLink::new(link_fd)))

@ -82,14 +82,16 @@ impl SkMsg {
let prog_fd = self.data.fd_or_err()?;
let map_fd = map.as_raw_fd();
bpf_prog_attach(prog_fd, map_fd, BPF_SK_MSG_VERDICT).map_err(|(_, io_error)| {
ProgramError::SyscallError {
// TODO (AM)
bpf_prog_attach(prog_fd.as_raw_fd(), map_fd, BPF_SK_MSG_VERDICT).map_err(
|(_, io_error)| ProgramError::SyscallError {
call: "bpf_prog_attach".to_owned(),
io_error,
}
})?;
},
)?;
self.data.links.insert(SkMsgLink::new(ProgAttachLink::new(
prog_fd,
// TODO (AM)
prog_fd.as_raw_fd(),
map_fd,
BPF_SK_MSG_VERDICT,
)))

@ -78,14 +78,16 @@ impl SkSkb {
SkSkbKind::StreamParser => BPF_SK_SKB_STREAM_PARSER,
SkSkbKind::StreamVerdict => BPF_SK_SKB_STREAM_VERDICT,
};
bpf_prog_attach(prog_fd, map_fd, attach_type).map_err(|(_, io_error)| {
// TODO (AM)
bpf_prog_attach(prog_fd.as_raw_fd(), map_fd, attach_type).map_err(|(_, io_error)| {
ProgramError::SyscallError {
call: "bpf_prog_attach".to_owned(),
io_error,
}
})?;
// TODO (AM)
self.data.links.insert(SkSkbLink::new(ProgAttachLink::new(
prog_fd,
prog_fd.as_raw_fd(),
map_fd,
attach_type,
)))

@ -62,14 +62,16 @@ impl SockOps {
let prog_fd = self.data.fd_or_err()?;
let cgroup_fd = cgroup.as_raw_fd();
bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SOCK_OPS).map_err(|(_, io_error)| {
ProgramError::SyscallError {
// TODO (AM)
bpf_prog_attach(prog_fd.as_raw_fd(), cgroup_fd, BPF_CGROUP_SOCK_OPS).map_err(
|(_, io_error)| ProgramError::SyscallError {
call: "bpf_prog_attach".to_owned(),
io_error,
}
})?;
},
)?;
// TODO (AM)
self.data.links.insert(SockOpsLink::new(ProgAttachLink::new(
prog_fd,
prog_fd.as_raw_fd(),
cgroup_fd,
BPF_CGROUP_SOCK_OPS,
)))

@ -92,6 +92,8 @@ impl SocketFilter {
.into());
}
// TODO (AM)
let prog_fd = prog_fd.as_raw_fd();
self.data.links.insert(SocketFilterLink { socket, prog_fd })
}

@ -4,6 +4,7 @@ use thiserror::Error;
use std::{
ffi::{CStr, CString},
io,
os::fd::AsRawFd,
path::Path,
};
@ -158,7 +159,8 @@ impl SchedClassifier {
netlink_qdisc_attach(
if_index as i32,
&attach_type,
prog_fd,
// TODO (AM)
prog_fd.as_raw_fd(),
&self.name,
options.priority,
options.handle,

@ -1,5 +1,5 @@
//! Tracepoint programs.
use std::{fs, io, path::Path};
use std::{fs, io, os::fd::AsRawFd, path::Path};
use thiserror::Error;
use crate::{
@ -87,7 +87,8 @@ impl TracePoint {
}
})? as i32;
let link = perf_attach(self.data.fd_or_err()?, fd)?;
// TODO (AM)
let link = perf_attach(self.data.fd_or_err()?.as_raw_fd(), fd)?;
self.data.links.insert(TracePointLink::new(link))
}

@ -1,5 +1,5 @@
//! Common functions shared between multiple eBPF program types.
use std::{ffi::CStr, io, os::unix::io::RawFd, path::Path};
use std::{ffi::CStr, io, os::fd::AsRawFd, path::Path};
use crate::{
programs::{FdLink, Link, ProgramData, ProgramError},
@ -13,12 +13,14 @@ pub(crate) fn attach_raw_tracepoint<T: Link + From<FdLink>>(
) -> Result<T::Id, ProgramError> {
let prog_fd = program_data.fd_or_err()?;
let pfd = bpf_raw_tracepoint_open(tp_name, prog_fd).map_err(|(_code, io_error)| {
ProgramError::SyscallError {
call: "bpf_raw_tracepoint_open".to_owned(),
io_error,
}
})? as RawFd;
// TODO (AM)
let pfd =
bpf_raw_tracepoint_open(tp_name, prog_fd.as_raw_fd()).map_err(|(_code, io_error)| {
ProgramError::SyscallError {
call: "bpf_raw_tracepoint_open".to_owned(),
io_error,
}
})?;
program_data.links.insert(FdLink::new(pfd).into())
}

@ -1,7 +1,13 @@
//! eXpress Data Path (XDP) programs.
use bitflags;
use libc::if_nametoindex;
use std::{convert::TryFrom, ffi::CString, hash::Hash, io, mem, os::unix::io::RawFd};
use std::{
convert::TryFrom,
ffi::CString,
hash::Hash,
io,
os::{fd::AsRawFd, unix::io::RawFd},
};
use thiserror::Error;
use crate::{
@ -128,19 +134,23 @@ impl Xdp {
let k_ver = kernel_version().unwrap();
if k_ver >= (5, 9, 0) {
let link_fd = bpf_link_create(prog_fd, if_index, BPF_XDP, None, flags.bits()).map_err(
|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
},
)? as RawFd;
// TODO (AM)
let link_fd =
bpf_link_create(prog_fd.as_raw_fd(), if_index, BPF_XDP, None, flags.bits())
.map_err(|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_create".to_owned(),
io_error,
})?;
self.data
.links
.insert(XdpLink::new(XdpLinkInner::FdLink(FdLink::new(link_fd))))
} else {
unsafe { netlink_set_xdp_fd(if_index, prog_fd, None, flags.bits()) }
// TODO (AM)
unsafe { netlink_set_xdp_fd(if_index, prog_fd.as_raw_fd(), None, flags.bits()) }
.map_err(|io_error| XdpError::NetlinkError { io_error })?;
// TODO (AM)
let prog_fd = prog_fd.as_raw_fd();
self.data
.links
.insert(XdpLink::new(XdpLinkInner::NlLink(NlLink {
@ -171,20 +181,19 @@ impl Xdp {
/// Ownership of the link will transfer to this program.
pub fn attach_to_link(&mut self, link: XdpLink) -> Result<XdpLinkId, ProgramError> {
let prog_fd = self.data.fd_or_err()?;
match link.inner() {
match link.into_inner() {
XdpLinkInner::FdLink(fd_link) => {
let link_fd = fd_link.fd;
bpf_link_update(link_fd, prog_fd, None, 0).map_err(|(_, io_error)| {
ProgramError::SyscallError {
// TODO (AM)
bpf_link_update(fd_link.fd.as_raw_fd(), prog_fd.as_raw_fd(), None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
call: "bpf_link_update".to_string(),
io_error,
}
})?;
// dispose of link and avoid detach on drop
mem::forget(link);
},
)?;
self.data
.links
.insert(XdpLink::new(XdpLinkInner::FdLink(FdLink::new(link_fd))))
.insert(XdpLink::new(XdpLinkInner::FdLink(FdLink::new(fd_link.fd))))
}
XdpLinkInner::NlLink(nl_link) => {
let if_index = nl_link.if_index;
@ -192,11 +201,17 @@ impl Xdp {
let flags = nl_link.flags;
let replace_flags = flags | XdpFlags::REPLACE;
unsafe {
netlink_set_xdp_fd(if_index, prog_fd, Some(old_prog_fd), replace_flags.bits())
.map_err(|io_error| XdpError::NetlinkError { io_error })?;
// TODO (AM)
netlink_set_xdp_fd(
if_index,
prog_fd.as_raw_fd(),
Some(old_prog_fd),
replace_flags.bits(),
)
.map_err(|io_error| XdpError::NetlinkError { io_error })?;
}
// dispose of link and avoid detach on drop
mem::forget(link);
// TODO (AM)
let prog_fd = prog_fd.as_raw_fd();
self.data
.links
.insert(XdpLink::new(XdpLinkInner::NlLink(NlLink {
@ -209,6 +224,7 @@ impl Xdp {
}
}
// TODO (AM): implement Drop to force detach?
#[derive(Debug)]
pub(crate) struct NlLink {
if_index: i32,
@ -283,7 +299,8 @@ impl TryFrom<FdLink> for XdpLink {
fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
// unwrap of fd_link.fd will not panic since it's only None when being dropped.
let info =
bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| LinkError::SyscallError {
// TODO (AM)
bpf_link_get_info_by_fd(fd_link.fd.as_raw_fd()).map_err(|io_error| LinkError::SyscallError {
call: "BPF_OBJ_GET_INFO_BY_FD".to_string(),
code: 0,
io_error,

@ -3,7 +3,10 @@ use std::{
ffi::{CStr, CString},
io,
mem::{self, MaybeUninit},
os::unix::io::RawFd,
os::{
fd::{AsRawFd, FromRawFd, OwnedFd},
unix::io::RawFd,
},
slice,
};
@ -34,7 +37,11 @@ use crate::{
type Result<T> = std::result::Result<T, (c_long, io::Error)>;
pub(crate) fn bpf_create_map(name: &CStr, def: &obj::Map, btf_fd: Option<RawFd>) -> SysResult {
pub(crate) fn bpf_create_map(
name: &CStr,
def: &obj::Map,
btf_fd: Option<RawFd>,
) -> Result<OwnedFd> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_1 };
@ -88,7 +95,9 @@ pub(crate) fn bpf_create_map(name: &CStr, def: &obj::Map, btf_fd: Option<RawFd>)
.copy_from_slice(unsafe { slice::from_raw_parts(name.as_ptr(), name_len) });
}
sys_bpf(bpf_cmd::BPF_MAP_CREATE, &attr)
let fd = sys_bpf(bpf_cmd::BPF_MAP_CREATE, &attr)? as RawFd;
// SAFETY: BPF_MAP_CREATE creates a new file descriptor
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
}
pub(crate) fn bpf_pin_object(fd: RawFd, path: &CStr) -> SysResult {
@ -99,11 +108,13 @@ pub(crate) fn bpf_pin_object(fd: RawFd, path: &CStr) -> SysResult {
sys_bpf(bpf_cmd::BPF_OBJ_PIN, &attr)
}
pub(crate) fn bpf_get_object(path: &CStr) -> SysResult {
pub(crate) fn bpf_get_object(path: &CStr) -> Result<OwnedFd> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_4 };
u.pathname = path.as_ptr() as u64;
sys_bpf(bpf_cmd::BPF_OBJ_GET, &attr)
let fd = sys_bpf(bpf_cmd::BPF_OBJ_GET, &attr)? as RawFd;
// SAFETY: BPF_OBJ_GET creates a new file descriptor
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
}
pub(crate) struct BpfLoadProgramAttrs<'a> {
@ -128,7 +139,7 @@ pub(crate) fn bpf_load_program(
aya_attr: &BpfLoadProgramAttrs,
logger: &mut VerifierLog,
verifier_log_level: u32,
) -> SysResult {
) -> Result<OwnedFd> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_3 };
@ -187,7 +198,9 @@ pub(crate) fn bpf_load_program(
if let Some(v) = aya_attr.attach_btf_id {
u.attach_btf_id = v;
}
sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr)
let fd = sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr)? as RawFd;
// SAFETY: BPF_PROG_LOAD returns a new fd
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
}
fn lookup<K: Pod, V: Pod>(
@ -366,7 +379,7 @@ pub(crate) fn bpf_link_create(
attach_type: bpf_attach_type,
btf_id: Option<u32>,
flags: u32,
) -> SysResult {
) -> Result<OwnedFd> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.link_create.__bindgen_anon_1.prog_fd = prog_fd as u32;
@ -377,7 +390,9 @@ pub(crate) fn bpf_link_create(
attr.link_create.__bindgen_anon_3.target_btf_id = btf_id;
}
sys_bpf(bpf_cmd::BPF_LINK_CREATE, &attr)
let fd = sys_bpf(bpf_cmd::BPF_LINK_CREATE, &attr)? as RawFd;
// Safety: BPF_LINK_CREATE returns a new file descriptor
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
}
// since kernel 5.7
@ -528,7 +543,7 @@ pub(crate) fn btf_obj_get_info_by_fd(prog_fd: RawFd, buf: &mut [u8]) -> io::Resu
}
}
pub(crate) fn bpf_raw_tracepoint_open(name: Option<&CStr>, prog_fd: RawFd) -> SysResult {
pub(crate) fn bpf_raw_tracepoint_open(name: Option<&CStr>, prog_fd: RawFd) -> Result<OwnedFd> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.raw_tracepoint.name = match name {
@ -537,7 +552,9 @@ pub(crate) fn bpf_raw_tracepoint_open(name: Option<&CStr>, prog_fd: RawFd) -> Sy
};
attr.raw_tracepoint.prog_fd = prog_fd as u32;
sys_bpf(bpf_cmd::BPF_RAW_TRACEPOINT_OPEN, &attr)
let fd = sys_bpf(bpf_cmd::BPF_RAW_TRACEPOINT_OPEN, &attr)? as RawFd;
// Safety: BPF_RAW_TRACEPOINT_OPEN returns a new fd
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
}
pub(crate) fn bpf_load_btf(raw_btf: &[u8], log: &mut VerifierLog) -> SysResult {
@ -694,22 +711,27 @@ pub(crate) fn is_bpf_global_data_supported() -> bool {
btf_fd: None,
};
if let Ok(map_fd) = map_data.create("aya_global") {
insns[0].imm = map_fd;
if map_data.create("aya_global").is_err() {
return false;
}
let gpl = b"GPL\0";
u.license = gpl.as_ptr() as u64;
u.insn_cnt = insns.len() as u32;
u.insns = insns.as_ptr() as u64;
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_SOCKET_FILTER as u32;
// OK: we just created this fd
let map_fd = map_data.fd.as_ref().unwrap();
if let Ok(v) = sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr) {
let fd = v as RawFd;
insns[0].imm = map_fd.as_raw_fd();
unsafe { close(fd) };
let gpl = b"GPL\0";
u.license = gpl.as_ptr() as u64;
u.insn_cnt = insns.len() as u32;
u.insns = insns.as_ptr() as u64;
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_SOCKET_FILTER as u32;
return true;
}
if let Ok(v) = sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr) {
let fd = v as RawFd;
unsafe { close(fd) };
return true;
}
false
@ -982,14 +1004,11 @@ pub(crate) fn bpf_prog_get_next_id(id: u32) -> Result<Option<u32>> {
}
}
pub(crate) fn retry_with_verifier_logs<F>(
pub(crate) fn retry_with_verifier_logs<T>(
max_retries: usize,
log: &mut VerifierLog,
f: F,
) -> SysResult
where
F: Fn(&mut VerifierLog) -> SysResult,
{
f: impl Fn(&mut VerifierLog) -> Result<T>,
) -> Result<T> {
// 1. Try the syscall
let ret = f(log);
if ret.is_ok() {

Loading…
Cancel
Save