sys: extract common SyscallError

We currently have 4 copies of this.
reviewable/pr712/r14
Tamir Duberstein 1 year ago
parent 4cb3ea6e8f
commit de8519a380
No known key found for this signature in database

@ -42,6 +42,7 @@ use crate::{
is_btf_float_supported, is_btf_func_global_supported, is_btf_func_supported,
is_btf_supported, is_btf_type_tag_supported, is_perf_link_supported,
is_probe_read_kernel_supported, is_prog_name_supported, retry_with_verifier_logs,
SyscallError,
},
util::{bytes_of, bytes_of_slice, possible_cpus, POSSIBLE_CPUS},
};
@ -505,16 +506,19 @@ impl<'a> BpfLoader<'a> {
};
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 {
.map_err(|(_, io_error)| SyscallError {
call: "bpf_map_update_elem",
io_error,
})?;
})
.map_err(MapError::from)?;
}
if map.obj.section_kind() == BpfSectionKind::Rodata {
bpf_map_freeze(fd).map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_freeze",
io_error,
})?;
bpf_map_freeze(fd)
.map_err(|(_, io_error)| SyscallError {
call: "bpf_map_freeze",
io_error,
})
.map_err(MapError::from)?;
}
maps.insert(name, map);
}

@ -5,7 +5,7 @@ use std::{
use crate::{
maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError},
sys::{bpf_map_lookup_elem, bpf_map_update_elem},
sys::{bpf_map_lookup_elem, bpf_map_update_elem, SyscallError},
Pod,
};
@ -65,12 +65,11 @@ 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 {
let value =
bpf_map_lookup_elem(fd, index, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem",
io_error,
}
})?;
})?;
value.ok_or(MapError::KeyNotFound)
}
@ -93,7 +92,7 @@ impl<T: BorrowMut<MapData>, V: Pod> Array<T, V> {
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 {
SyscallError {
call: "bpf_map_update_elem",
io_error,
}

@ -5,7 +5,7 @@ use std::{
use crate::{
maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError, PerCpuValues},
sys::{bpf_map_lookup_elem_per_cpu, bpf_map_update_elem_per_cpu},
sys::{bpf_map_lookup_elem_per_cpu, bpf_map_update_elem_per_cpu, SyscallError},
Pod,
};
@ -85,7 +85,7 @@ impl<T: Borrow<MapData>, V: Pod> PerCpuArray<T, V> {
let fd = data.fd_or_err()?;
let value = bpf_map_lookup_elem_per_cpu(fd, index, flags).map_err(|(_, io_error)| {
MapError::SyscallError {
SyscallError {
call: "bpf_map_lookup_elem",
io_error,
}
@ -113,7 +113,7 @@ impl<T: BorrowMut<MapData>, V: Pod> PerCpuArray<T, V> {
let fd = data.fd_or_err()?;
bpf_map_update_elem_per_cpu(fd, &index, &values, flags).map_err(|(_, io_error)| {
MapError::SyscallError {
SyscallError {
call: "bpf_map_update_elem",
io_error,
}

@ -8,7 +8,7 @@ use std::{
use crate::{
maps::{check_bounds, check_kv_size, MapData, MapError, MapKeys},
programs::ProgramFd,
sys::{bpf_map_delete_elem, bpf_map_update_elem},
sys::{bpf_map_delete_elem, bpf_map_update_elem, SyscallError},
};
/// An array of eBPF program file descriptors used as a jump table.
@ -80,7 +80,7 @@ impl<T: BorrowMut<MapData>> ProgramArray<T> {
let prog_fd = program.as_raw_fd();
bpf_map_update_elem(fd, Some(&index), &prog_fd, flags).map_err(|(_, io_error)| {
MapError::SyscallError {
SyscallError {
call: "bpf_map_update_elem",
io_error,
}
@ -99,9 +99,12 @@ impl<T: BorrowMut<MapData>> ProgramArray<T> {
bpf_map_delete_elem(fd, index)
.map(|_| ())
.map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_delete_elem",
io_error,
.map_err(|(_, io_error)| {
SyscallError {
call: "bpf_map_delete_elem",
io_error,
}
.into()
})
}
}

@ -3,7 +3,7 @@ use std::{borrow::Borrow, marker::PhantomData};
use crate::{
maps::{check_v_size, MapData, MapError},
sys::{bpf_map_lookup_elem_ptr, bpf_map_push_elem},
sys::{bpf_map_lookup_elem_ptr, bpf_map_push_elem, SyscallError},
Pod,
};
@ -54,7 +54,7 @@ impl<T: Borrow<MapData>, V: Pod> BloomFilter<T, V> {
let fd = self.inner.borrow().fd_or_err()?;
bpf_map_lookup_elem_ptr::<u32, _>(fd, None, &mut value, flags)
.map_err(|(_, io_error)| MapError::SyscallError {
.map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem",
io_error,
})?
@ -65,11 +65,9 @@ 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)| {
MapError::SyscallError {
call: "bpf_map_push_elem",
io_error,
}
bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_push_elem",
io_error,
})?;
Ok(())
}
@ -212,7 +210,7 @@ mod tests {
assert_matches!(
bloom_filter.insert(1, 0),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_push_elem" && io_error.raw_os_error() == Some(EFAULT)
Err(MapError::SyscallError(SyscallError { call: "bpf_map_push_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT)
);
}
@ -250,7 +248,7 @@ mod tests {
assert_matches!(
bloom_filter.contains(&1, 0),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT)
Err(MapError::SyscallError(SyscallError { call: "bpf_map_lookup_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT)
);
}

@ -5,7 +5,7 @@ use std::{
use crate::{
maps::{check_kv_size, hash_map, IterableMap, MapData, MapError, MapIter, MapKeys},
sys::bpf_map_lookup_elem,
sys::{bpf_map_lookup_elem, SyscallError},
Pod,
};
@ -54,11 +54,9 @@ 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)| {
MapError::SyscallError {
call: "bpf_map_lookup_elem",
io_error,
}
let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem",
io_error,
})?;
value.ok_or(MapError::KeyNotFound)
}
@ -292,7 +290,7 @@ mod tests {
assert_matches!(
hm.insert(1, 42, 0),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_update_elem" && io_error.raw_os_error() == Some(EFAULT)
Err(MapError::SyscallError(SyscallError { call: "bpf_map_update_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT)
);
}
@ -352,7 +350,7 @@ mod tests {
assert_matches!(
hm.remove(&1),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_delete_elem" && io_error.raw_os_error() == Some(EFAULT)
Err(MapError::SyscallError(SyscallError { call: "bpf_map_delete_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT)
);
}
@ -390,7 +388,7 @@ mod tests {
assert_matches!(
hm.get(&1, 0),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT)
Err(MapError::SyscallError(SyscallError { call: "bpf_map_lookup_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT)
);
}
@ -535,7 +533,10 @@ mod tests {
assert_matches!(keys.next(), Some(Ok(20)));
assert_matches!(
keys.next(),
Some(Err(MapError::SyscallError { call, .. })) if call == "bpf_map_get_next_key"
Some(Err(MapError::SyscallError(SyscallError {
call: "bpf_map_get_next_key",
io_error: _
})))
);
assert_matches!(keys.next(), None);
}
@ -647,7 +648,10 @@ mod tests {
assert_matches!(iter.next(), Some(Ok((20, 200))));
assert_matches!(
iter.next(),
Some(Err(MapError::SyscallError { call, .. })) if call == "bpf_map_get_next_key"
Some(Err(MapError::SyscallError(SyscallError {
call: "bpf_map_get_next_key",
io_error: _
})))
);
assert_matches!(iter.next(), None);
}
@ -691,7 +695,10 @@ mod tests {
assert_matches!(iter.next(), Some(Ok((10, 100))));
assert_matches!(
iter.next(),
Some(Err(MapError::SyscallError { call, .. })) if call == "bpf_map_lookup_elem"
Some(Err(MapError::SyscallError(SyscallError {
call: "bpf_map_lookup_elem",
io_error: _
})))
);
assert_matches!(iter.next(), Some(Ok((30, 300))));
assert_matches!(iter.next(), None);

@ -1,7 +1,7 @@
//! Hash map types.
use crate::{
maps::MapError,
sys::{bpf_map_delete_elem, bpf_map_update_elem},
sys::{bpf_map_delete_elem, bpf_map_update_elem, SyscallError},
Pod,
};
@ -21,11 +21,9 @@ 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)| {
MapError::SyscallError {
call: "bpf_map_update_elem",
io_error,
}
bpf_map_update_elem(fd, Some(key), value, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_update_elem",
io_error,
})?;
Ok(())
@ -35,8 +33,11 @@ pub(crate) fn remove<K: Pod>(map: &MapData, key: &K) -> Result<(), MapError> {
let fd = map.fd_or_err()?;
bpf_map_delete_elem(fd, key)
.map(|_| ())
.map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_delete_elem",
io_error,
.map_err(|(_, io_error)| {
SyscallError {
call: "bpf_map_delete_elem",
io_error,
}
.into()
})
}

@ -8,7 +8,7 @@ use crate::{
maps::{
check_kv_size, hash_map, IterableMap, MapData, MapError, MapIter, MapKeys, PerCpuValues,
},
sys::{bpf_map_lookup_elem_per_cpu, bpf_map_update_elem_per_cpu},
sys::{bpf_map_lookup_elem_per_cpu, bpf_map_update_elem_per_cpu, SyscallError},
Pod,
};
@ -64,12 +64,11 @@ 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 {
let values =
bpf_map_lookup_elem_per_cpu(fd, key, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem",
io_error,
}
})?;
})?;
values.ok_or(MapError::KeyNotFound)
}
@ -123,7 +122,7 @@ impl<T: BorrowMut<MapData>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
) -> Result<(), MapError> {
let fd = self.inner.borrow_mut().fd_or_err()?;
bpf_map_update_elem_per_cpu(fd, key.borrow(), &values, flags).map_err(
|(_, io_error)| MapError::SyscallError {
|(_, io_error)| SyscallError {
call: "bpf_map_update_elem",
io_error,
},

@ -6,7 +6,7 @@ use std::{
use crate::{
maps::{check_kv_size, IterableMap, MapData, MapError, MapIter, MapKeys},
sys::{bpf_map_delete_elem, bpf_map_lookup_elem, bpf_map_update_elem},
sys::{bpf_map_delete_elem, bpf_map_lookup_elem, bpf_map_update_elem, SyscallError},
Pod,
};
@ -129,11 +129,9 @@ 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)| {
MapError::SyscallError {
call: "bpf_map_lookup_elem",
io_error,
}
let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem",
io_error,
})?;
value.ok_or(MapError::KeyNotFound)
}
@ -161,7 +159,7 @@ impl<T: BorrowMut<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
) -> 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 {
SyscallError {
call: "bpf_map_update_elem",
io_error,
}
@ -177,9 +175,12 @@ impl<T: BorrowMut<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
let fd = self.inner.borrow().fd_or_err()?;
bpf_map_delete_elem(fd, key)
.map(|_| ())
.map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_delete_elem",
io_error,
.map_err(|(_, io_error)| {
SyscallError {
call: "bpf_map_delete_elem",
io_error,
}
.into()
})
}
}
@ -349,7 +350,7 @@ mod tests {
let key = Key::new(16, u32::from(ipaddr).to_be());
assert_matches!(
trie.insert(&key, 1, 0),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_update_elem" && io_error.raw_os_error() == Some(EFAULT)
Err(MapError::SyscallError(SyscallError { call: "bpf_map_update_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT)
);
}
@ -391,7 +392,7 @@ mod tests {
let key = Key::new(16, u32::from(ipaddr).to_be());
assert_matches!(
trie.remove(&key),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_delete_elem" && io_error.raw_os_error() == Some(EFAULT)
Err(MapError::SyscallError(SyscallError { call: "bpf_map_delete_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT)
);
}
@ -432,7 +433,7 @@ mod tests {
assert_matches!(
trie.get(&key, 0),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT)
Err(MapError::SyscallError(SyscallError { call: "bpf_map_lookup_elem", io_error })) if io_error.raw_os_error() == Some(EFAULT)
);
}

@ -58,7 +58,7 @@ use crate::{
pin::PinError,
sys::{
bpf_create_map, bpf_get_object, bpf_map_get_info_by_fd, bpf_map_get_next_key,
bpf_pin_object,
bpf_pin_object, SyscallError,
},
util::nr_cpus,
PinningType, Pod,
@ -167,13 +167,8 @@ pub enum MapError {
ProgramNotLoaded,
/// Syscall failed
#[error("the `{call}` syscall failed")]
SyscallError {
/// Syscall Name
call: &'static str,
/// Original io::Error
io_error: io::Error,
},
#[error(transparent)]
SyscallError(#[from] SyscallError),
/// Could not pin map by name
#[error("map `{name:?}` requested pinning by name. pinning failed")]
@ -538,7 +533,7 @@ impl MapData {
}
let map_path = path.as_ref().join(name);
let path_string = CString::new(map_path.to_str().unwrap()).unwrap();
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| MapError::SyscallError {
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError {
call: "BPF_OBJ_GET",
io_error,
})? as RawFd;
@ -560,12 +555,12 @@ impl MapData {
}
})?;
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| MapError::SyscallError {
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError {
call: "BPF_OBJ_GET",
io_error,
})? as RawFd;
let info = bpf_map_get_info_by_fd(fd).map_err(|io_error| MapError::SyscallError {
let info = bpf_map_get_info_by_fd(fd).map_err(|io_error| SyscallError {
call: "BPF_MAP_GET_INFO_BY_FD",
io_error,
})?;
@ -584,7 +579,7 @@ impl MapData {
/// 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 {
let info = bpf_map_get_info_by_fd(fd).map_err(|io_error| SyscallError {
call: "BPF_OBJ_GET",
io_error,
})?;
@ -614,8 +609,8 @@ impl MapData {
error: e.to_string(),
}
})?;
bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError {
name: "BPF_OBJ_PIN",
bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| SyscallError {
call: "BPF_OBJ_PIN",
io_error,
})?;
self.pinned = true;
@ -692,21 +687,19 @@ impl<K: Pod> Iterator for MapKeys<'_, K> {
}
};
match bpf_map_get_next_key(fd, self.key.as_ref()) {
Ok(Some(key)) => {
self.key = Some(key);
Some(Ok(key))
}
Ok(None) => {
self.key = None;
None
}
Err((_, io_error)) => {
let key =
bpf_map_get_next_key(fd, self.key.as_ref()).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_get_next_key",
io_error,
});
match key {
Err(err) => {
self.err = true;
Some(Err(MapError::SyscallError {
call: "bpf_map_get_next_key",
io_error,
}))
Some(Err(err.into()))
}
Ok(key) => {
self.key = key;
key.map(Ok)
}
}
}

@ -6,7 +6,7 @@ use std::{
use crate::{
maps::{check_kv_size, MapData, MapError},
sys::{bpf_map_lookup_and_delete_elem, bpf_map_push_elem},
sys::{bpf_map_lookup_and_delete_elem, bpf_map_push_elem, SyscallError},
Pod,
};
@ -65,7 +65,7 @@ impl<T: BorrowMut<MapData>, V: Pod> Queue<T, V> {
let fd = self.inner.borrow().fd_or_err()?;
let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err(
|(_, io_error)| MapError::SyscallError {
|(_, io_error)| SyscallError {
call: "bpf_map_lookup_and_delete_elem",
io_error,
},
@ -80,11 +80,9 @@ 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)| {
MapError::SyscallError {
call: "bpf_map_push_elem",
io_error,
}
bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_push_elem",
io_error,
})?;
Ok(())
}

@ -8,7 +8,7 @@ use crate::{
maps::{
check_kv_size, hash_map, sock::SockMapFd, IterableMap, MapData, MapError, MapIter, MapKeys,
},
sys::bpf_map_lookup_elem,
sys::{bpf_map_lookup_elem, SyscallError},
Pod,
};
@ -83,11 +83,9 @@ 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)| {
MapError::SyscallError {
call: "bpf_map_lookup_elem",
io_error,
}
let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem",
io_error,
})?;
value.ok_or(MapError::KeyNotFound)
}

@ -7,7 +7,7 @@ use std::{
use crate::{
maps::{check_bounds, check_kv_size, sock::SockMapFd, MapData, MapError, MapKeys},
sys::{bpf_map_delete_elem, bpf_map_update_elem},
sys::{bpf_map_delete_elem, bpf_map_update_elem, SyscallError},
};
/// An array of TCP or UDP sockets.
@ -76,7 +76,7 @@ impl<T: BorrowMut<MapData>> SockMap<T> {
let fd = data.fd_or_err()?;
check_bounds(data, index)?;
bpf_map_update_elem(fd, Some(&index), &socket.as_raw_fd(), flags).map_err(
|(_, io_error)| MapError::SyscallError {
|(_, io_error)| SyscallError {
call: "bpf_map_update_elem",
io_error,
},
@ -91,9 +91,12 @@ impl<T: BorrowMut<MapData>> SockMap<T> {
check_bounds(data, *index)?;
bpf_map_delete_elem(fd, index)
.map(|_| ())
.map_err(|(_, io_error)| MapError::SyscallError {
call: "bpf_map_delete_elem",
io_error,
.map_err(|(_, io_error)| {
SyscallError {
call: "bpf_map_delete_elem",
io_error,
}
.into()
})
}
}

@ -6,7 +6,7 @@ use std::{
use crate::{
maps::{check_kv_size, MapData, MapError},
sys::{bpf_map_lookup_and_delete_elem, bpf_map_update_elem},
sys::{bpf_map_lookup_and_delete_elem, bpf_map_update_elem, SyscallError},
Pod,
};
@ -65,7 +65,7 @@ impl<T: BorrowMut<MapData>, V: Pod> Stack<T, V> {
let fd = self.inner.borrow().fd_or_err()?;
let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err(
|(_, io_error)| MapError::SyscallError {
|(_, io_error)| SyscallError {
call: "bpf_map_lookup_and_delete_elem",
io_error,
},
@ -81,7 +81,7 @@ impl<T: BorrowMut<MapData>, V: Pod> Stack<T, V> {
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 {
SyscallError {
call: "bpf_map_update_elem",
io_error,
}

@ -5,7 +5,7 @@ use std::{borrow::Borrow, collections::BTreeMap, fs, io, mem, path::Path, str::F
use crate::{
maps::{IterableMap, MapData, MapError, MapIter, MapKeys},
sys::bpf_map_lookup_elem_ptr,
sys::{bpf_map_lookup_elem_ptr, SyscallError},
};
/// A hash map of kernel or user space stack traces.
@ -77,11 +77,9 @@ impl<T: Borrow<MapData>> StackTraceMap<T> {
}
let max_stack_depth =
sysctl::<usize>("kernel/perf_event_max_stack").map_err(|io_error| {
MapError::SyscallError {
call: "sysctl",
io_error,
}
sysctl::<usize>("kernel/perf_event_max_stack").map_err(|io_error| SyscallError {
call: "sysctl",
io_error,
})?;
let size = data.obj.value_size() as usize;
if size > max_stack_depth * mem::size_of::<u64>() {
@ -106,7 +104,7 @@ impl<T: Borrow<MapData>> StackTraceMap<T> {
let mut frames = vec![0; self.max_stack_depth];
bpf_map_lookup_elem_ptr(fd, Some(stack_id), frames.as_mut_ptr(), flags)
.map_err(|(_, io_error)| MapError::SyscallError {
.map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem",
io_error,
})?

@ -1,5 +1,6 @@
//! Pinning BPF objects to the BPF filesystem.
use std::io;
use crate::sys::SyscallError;
use thiserror::Error;
/// An error ocurred working with a pinned BPF object.
@ -24,12 +25,6 @@ pub enum PinError {
error: String,
},
/// An error ocurred making a syscall.
#[error("{name} failed")]
SyscallError {
/// The syscall name.
name: &'static str,
/// The [`io::Error`] returned by the syscall.
#[source]
io_error: io::Error,
},
#[error(transparent)]
SyscallError(#[from] SyscallError),
}

@ -8,7 +8,7 @@ use crate::{
programs::{
define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError,
},
sys::{bpf_link_create, bpf_prog_attach},
sys::{bpf_link_create, bpf_prog_attach, SyscallError},
};
/// A program used to watch or prevent device interaction from a cgroup.
@ -66,7 +66,7 @@ impl CgroupDevice {
if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) {
let link_fd = bpf_link_create(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE, None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
|(_, io_error)| SyscallError {
call: "bpf_link_create",
io_error,
},
@ -78,7 +78,7 @@ impl CgroupDevice {
)))
} else {
bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE).map_err(|(_, io_error)| {
ProgramError::SyscallError {
SyscallError {
call: "bpf_prog_attach",
io_error,
}

@ -15,7 +15,7 @@ use crate::{
programs::{
define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError,
},
sys::{bpf_link_create, bpf_prog_attach},
sys::{bpf_link_create, bpf_prog_attach, SyscallError},
VerifierLogLevel,
};
@ -101,7 +101,7 @@ impl CgroupSkb {
};
if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) {
let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
|(_, io_error)| SyscallError {
call: "bpf_link_create",
io_error,
},
@ -113,7 +113,7 @@ impl CgroupSkb {
))))
} else {
bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| {
ProgramError::SyscallError {
SyscallError {
call: "bpf_prog_attach",
io_error,
}

@ -14,7 +14,7 @@ use crate::{
programs::{
define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError,
},
sys::{bpf_link_create, bpf_prog_attach},
sys::{bpf_link_create, bpf_prog_attach, SyscallError},
VerifierLogLevel,
};
@ -76,7 +76,7 @@ impl CgroupSock {
let attach_type = self.data.expected_attach_type.unwrap();
if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) {
let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
|(_, io_error)| SyscallError {
call: "bpf_link_create",
io_error,
},
@ -88,7 +88,7 @@ impl CgroupSock {
))))
} else {
bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| {
ProgramError::SyscallError {
SyscallError {
call: "bpf_prog_attach",
io_error,
}

@ -14,7 +14,7 @@ use crate::{
programs::{
define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError,
},
sys::{bpf_link_create, bpf_prog_attach},
sys::{bpf_link_create, bpf_prog_attach, SyscallError},
VerifierLogLevel,
};
@ -77,7 +77,7 @@ impl CgroupSockAddr {
let attach_type = self.data.expected_attach_type.unwrap();
if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) {
let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
|(_, io_error)| SyscallError {
call: "bpf_link_create",
io_error,
},
@ -89,7 +89,7 @@ impl CgroupSockAddr {
)))
} else {
bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| {
ProgramError::SyscallError {
SyscallError {
call: "bpf_prog_attach",
io_error,
}

@ -14,7 +14,7 @@ use crate::{
programs::{
define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError,
},
sys::{bpf_link_create, bpf_prog_attach},
sys::{bpf_link_create, bpf_prog_attach, SyscallError},
VerifierLogLevel,
};
@ -74,7 +74,7 @@ impl CgroupSockopt {
let attach_type = self.data.expected_attach_type.unwrap();
if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) {
let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
|(_, io_error)| SyscallError {
call: "bpf_link_create",
io_error,
},
@ -86,7 +86,7 @@ impl CgroupSockopt {
)))
} else {
bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| {
ProgramError::SyscallError {
SyscallError {
call: "bpf_prog_attach",
io_error,
}

@ -11,7 +11,7 @@ use crate::{
programs::{
define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError,
},
sys::{bpf_link_create, bpf_prog_attach},
sys::{bpf_link_create, bpf_prog_attach, SyscallError},
};
/// A program used to watch for sysctl changes.
@ -68,7 +68,7 @@ impl CgroupSysctl {
if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) {
let link_fd = bpf_link_create(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL, None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
|(_, io_error)| SyscallError {
call: "bpf_link_create",
io_error,
},
@ -80,7 +80,7 @@ impl CgroupSysctl {
)))
} else {
bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL).map_err(|(_, io_error)| {
ProgramError::SyscallError {
SyscallError {
call: "bpf_prog_attach",
io_error,
}

@ -10,7 +10,7 @@ use crate::{
programs::{
define_link_wrapper, load_program, FdLink, FdLinkId, ProgramData, ProgramError, ProgramFd,
},
sys::{self, bpf_link_create},
sys::{self, bpf_link_create, SyscallError},
Btf,
};
@ -91,7 +91,7 @@ impl Extension {
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 {
.map_err(|(_, io_error)| SyscallError {
call: "bpf_link_create",
io_error,
})? as RawFd;
@ -121,7 +121,7 @@ impl Extension {
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 {
.map_err(|(_, io_error)| SyscallError {
call: "bpf_link_create",
io_error,
})? as RawFd;
@ -151,11 +151,10 @@ impl Extension {
/// with the name `func_name` within that BTF object.
fn get_btf_info(prog_fd: i32, func_name: &str) -> Result<(RawFd, u32), ProgramError> {
// retrieve program information
let info =
sys::bpf_prog_get_info_by_fd(prog_fd).map_err(|io_error| ProgramError::SyscallError {
call: "bpf_prog_get_info_by_fd",
io_error,
})?;
let info = sys::bpf_prog_get_info_by_fd(prog_fd).map_err(|io_error| SyscallError {
call: "bpf_prog_get_info_by_fd",
io_error,
})?;
// btf_id refers to the ID of the program btf that was loaded with bpf(BPF_BTF_LOAD)
if info.btf_id == 0 {
@ -163,11 +162,10 @@ fn get_btf_info(prog_fd: i32, func_name: &str) -> Result<(RawFd, u32), ProgramEr
}
// the bpf fd of the BTF object
let btf_fd =
sys::bpf_btf_get_fd_by_id(info.btf_id).map_err(|io_error| ProgramError::SyscallError {
call: "bpf_btf_get_fd_by_id",
io_error,
})?;
let btf_fd = sys::bpf_btf_get_fd_by_id(info.btf_id).map_err(|io_error| SyscallError {
call: "bpf_btf_get_fd_by_id",
io_error,
})?;
// we need to read the btf bytes into a buffer but we don't know the size ahead of time.
// assume 4kb. if this is too small we can resize based on the size obtained in the response.
@ -176,18 +174,17 @@ fn get_btf_info(prog_fd: i32, func_name: &str) -> Result<(RawFd, u32), ProgramEr
Ok(info) => {
if info.btf_size > buf.len() as u32 {
buf.resize(info.btf_size as usize, 0u8);
let btf_info = sys::btf_obj_get_info_by_fd(btf_fd, &buf).map_err(|io_error| {
ProgramError::SyscallError {
let btf_info =
sys::btf_obj_get_info_by_fd(btf_fd, &buf).map_err(|io_error| SyscallError {
call: "bpf_prog_get_info_by_fd",
io_error,
}
})?;
})?;
Ok(btf_info)
} else {
Ok(info)
}
}
Err(io_error) => Err(ProgramError::SyscallError {
Err(io_error) => Err(SyscallError {
call: "bpf_prog_get_info_by_fd",
io_error,
}),

@ -10,7 +10,7 @@ use crate::{
probe::{attach, ProbeKind},
FdLink, LinkError, ProgramData, ProgramError,
},
sys::bpf_link_get_info_by_fd,
sys::{bpf_link_get_info_by_fd, SyscallError},
VerifierLogLevel,
};
@ -137,12 +137,10 @@ impl TryFrom<FdLink> for KProbeLink {
type Error = LinkError;
fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
let info =
bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| LinkError::SyscallError {
call: "BPF_OBJ_GET_INFO_BY_FD",
code: 0,
io_error,
})?;
let info = bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| SyscallError {
call: "BPF_OBJ_GET_INFO_BY_FD",
io_error,
})?;
if info.type_ == (bpf_link_type::BPF_LINK_TYPE_KPROBE_MULTI as u32) {
return Ok(KProbeLink::new(PerfLinkInner::FdLink(fd_link)));
}

@ -14,7 +14,7 @@ use crate::{
generated::bpf_attach_type,
pin::PinError,
programs::ProgramError,
sys::{bpf_get_object, bpf_pin_object, bpf_prog_detach},
sys::{bpf_get_object, bpf_pin_object, bpf_prog_detach, SyscallError},
};
/// A Link.
@ -152,8 +152,8 @@ impl FdLink {
error: e.to_string(),
}
})?;
bpf_pin_object(self.fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError {
name: "BPF_OBJ_PIN",
bpf_pin_object(self.fd, &path_string).map_err(|(_, io_error)| SyscallError {
call: "BPF_OBJ_PIN",
io_error,
})?;
Ok(PinnedLink::new(PathBuf::from(path.as_ref()), self))
@ -208,12 +208,12 @@ impl PinnedLink {
/// Creates a [`crate::programs::links::PinnedLink`] from a valid path on bpffs.
pub fn from_pin<P: AsRef<Path>>(path: P) -> Result<Self, LinkError> {
let path_string = CString::new(path.as_ref().to_string_lossy().to_string()).unwrap();
let fd =
bpf_get_object(&path_string).map_err(|(code, io_error)| LinkError::SyscallError {
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| {
LinkError::SyscallError(SyscallError {
call: "BPF_OBJ_GET",
code,
io_error,
})? as RawFd;
})
})? as RawFd;
Ok(PinnedLink::new(
path.as_ref().to_path_buf(),
FdLink::new(fd),
@ -339,16 +339,8 @@ pub enum LinkError {
#[error("Invalid link")]
InvalidLink,
/// Syscall failed.
#[error("the `{call}` syscall failed with code {code}")]
SyscallError {
/// Syscall Name.
call: &'static str,
/// Error code.
code: libc::c_long,
#[source]
/// Original io::Error.
io_error: io::Error,
},
#[error(transparent)]
SyscallError(#[from] SyscallError),
}
#[cfg(test)]

@ -4,7 +4,10 @@ use std::os::fd::{AsRawFd, IntoRawFd as _, RawFd};
use crate::{
generated::{bpf_attach_type::BPF_LIRC_MODE2, bpf_prog_type::BPF_PROG_TYPE_LIRC_MODE2},
programs::{load_program, query, Link, ProgramData, ProgramError, ProgramInfo},
sys::{bpf_prog_attach, bpf_prog_detach, bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd},
sys::{
bpf_prog_attach, bpf_prog_detach, bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd,
SyscallError,
},
};
use libc::{close, dup};
@ -65,7 +68,7 @@ impl LircMode2 {
let lircdev_fd = lircdev.as_raw_fd();
bpf_prog_attach(prog_fd, lircdev_fd, BPF_LIRC_MODE2).map_err(|(_, io_error)| {
ProgramError::SyscallError {
SyscallError {
call: "bpf_prog_attach",
io_error,
}
@ -96,7 +99,7 @@ impl LircMode2 {
let mut prog_fds = Vec::with_capacity(prog_ids.len());
for id in prog_ids {
let fd = bpf_prog_get_fd_by_id(id).map_err(|io_error| ProgramError::SyscallError {
let fd = bpf_prog_get_fd_by_id(id).map_err(|io_error| SyscallError {
call: "bpf_prog_get_fd_by_id",
io_error,
})?;
@ -132,13 +135,15 @@ impl LircLink {
/// Get ProgramInfo from this link
pub fn info(&self) -> Result<ProgramInfo, ProgramError> {
match bpf_prog_get_info_by_fd(self.prog_fd) {
Ok(info) => Ok(ProgramInfo(info)),
Err(io_error) => Err(ProgramError::SyscallError {
call: "bpf_prog_get_info_by_fd",
io_error,
}),
}
bpf_prog_get_info_by_fd(self.prog_fd)
.map(ProgramInfo)
.map_err(|io_error| {
SyscallError {
call: "bpf_prog_get_info_by_fd",
io_error,
}
.into()
})
}
}

@ -64,7 +64,6 @@ pub mod uprobe;
mod utils;
pub mod xdp;
use crate::util::KernelVersion;
use libc::ENOSPC;
use std::{
ffi::CString,
@ -112,8 +111,9 @@ use crate::{
sys::{
bpf_btf_get_fd_by_id, bpf_get_object, bpf_load_program, bpf_pin_object,
bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd, bpf_prog_get_next_id, bpf_prog_query,
retry_with_verifier_logs, BpfLoadProgramAttrs,
retry_with_verifier_logs, BpfLoadProgramAttrs, SyscallError,
},
util::KernelVersion,
VerifierLogLevel,
};
@ -147,14 +147,8 @@ pub enum ProgramError {
},
/// A syscall failed.
#[error("`{call}` failed")]
SyscallError {
/// The name of the syscall which failed.
call: &'static str,
/// The [`io::Error`] returned by the syscall.
#[source]
io_error: io::Error,
},
#[error(transparent)]
SyscallError(#[from] SyscallError),
/// The network interface does not exist.
#[error("unknown network interface {name}")]
@ -456,12 +450,11 @@ impl<T: Link> ProgramData<T> {
None
};
let attach_btf_obj_fd = if info.attach_btf_obj_id > 0 {
let fd = bpf_btf_get_fd_by_id(info.attach_btf_obj_id).map_err(|io_error| {
ProgramError::SyscallError {
let fd =
bpf_btf_get_fd_by_id(info.attach_btf_obj_id).map_err(|io_error| SyscallError {
call: "bpf_btf_get_fd_by_id",
io_error,
}
})?;
})?;
Some(fd as u32)
} else {
None
@ -489,13 +482,12 @@ impl<T: Link> ProgramData<T> {
) -> Result<ProgramData<T>, ProgramError> {
let path_string =
CString::new(path.as_ref().as_os_str().to_string_lossy().as_bytes()).unwrap();
let fd =
bpf_get_object(&path_string).map_err(|(_, io_error)| ProgramError::SyscallError {
call: "bpf_obj_get",
io_error,
})? as RawFd;
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError {
call: "bpf_obj_get",
io_error,
})? as RawFd;
let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| ProgramError::SyscallError {
let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| SyscallError {
call: "bpf_prog_get_info_by_fd",
io_error,
})?;
@ -537,8 +529,8 @@ fn pin_program<T: Link, P: AsRef<Path>>(data: &ProgramData<T>, path: P) -> Resul
error: e.to_string(),
}
})?;
bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError {
name: "BPF_OBJ_PIN",
bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| SyscallError {
call: "BPF_OBJ_PIN",
io_error,
})?;
Ok(())
@ -665,15 +657,17 @@ pub(crate) fn query<T: AsRawFd>(
prog_ids.resize(prog_cnt as usize, 0);
return Ok(prog_ids);
}
Err((_, io_error)) if retries == 0 && io_error.raw_os_error() == Some(ENOSPC) => {
prog_ids.resize(prog_cnt as usize, 0);
retries += 1;
}
Err((_, io_error)) => {
return Err(ProgramError::SyscallError {
call: "bpf_prog_query",
io_error,
});
if retries == 0 && io_error.raw_os_error() == Some(ENOSPC) {
prog_ids.resize(prog_cnt as usize, 0);
retries += 1;
} else {
return Err(SyscallError {
call: "bpf_prog_query",
io_error,
}
.into());
}
}
}
}
@ -951,24 +945,22 @@ impl ProgramInfo {
///
/// The returned fd must be closed when no longer needed.
pub fn fd(&self) -> Result<RawFd, ProgramError> {
let fd =
bpf_prog_get_fd_by_id(self.0.id).map_err(|io_error| ProgramError::SyscallError {
call: "bpf_prog_get_fd_by_id",
io_error,
})?;
let fd = bpf_prog_get_fd_by_id(self.0.id).map_err(|io_error| SyscallError {
call: "bpf_prog_get_fd_by_id",
io_error,
})?;
Ok(fd.into_raw_fd())
}
/// Loads a program from a pinned path in bpffs.
pub fn from_pin<P: AsRef<Path>>(path: P) -> Result<ProgramInfo, ProgramError> {
let path_string = CString::new(path.as_ref().to_str().unwrap()).unwrap();
let fd =
bpf_get_object(&path_string).map_err(|(_, io_error)| ProgramError::SyscallError {
call: "BPF_OBJ_GET",
io_error,
})? as RawFd;
let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| SyscallError {
call: "BPF_OBJ_GET",
io_error,
})? as RawFd;
let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| ProgramError::SyscallError {
let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| SyscallError {
call: "bpf_prog_get_info_by_fd",
io_error,
})?;
@ -999,18 +991,19 @@ impl Iterator for ProgramsIter {
self.current = next;
Some(
bpf_prog_get_fd_by_id(next)
.map_err(|io_error| ProgramError::SyscallError {
.map_err(|io_error| SyscallError {
call: "bpf_prog_get_fd_by_id",
io_error,
})
.and_then(|fd| {
bpf_prog_get_info_by_fd(fd.as_raw_fd())
.map_err(|io_error| ProgramError::SyscallError {
.map_err(|io_error| SyscallError {
call: "bpf_prog_get_info_by_fd",
io_error,
})
.map(ProgramInfo)
}),
})
.map_err(Into::into),
)
}
Ok(None) => None,
@ -1018,10 +1011,11 @@ impl Iterator for ProgramsIter {
// If getting the next program failed, we have to yield None in our next
// iteration to avoid an infinite loop.
self.error = true;
Some(Err(ProgramError::SyscallError {
Some(Err(SyscallError {
call: "bpf_prog_get_fd_by_id",
io_error,
}))
}
.into()))
}
}
}

@ -7,7 +7,7 @@ use crate::{
probe::{detach_debug_fs, ProbeEvent},
FdLink, Link, ProgramError,
},
sys::{bpf_link_create, perf_event_ioctl, SysResult},
sys::{bpf_link_create, perf_event_ioctl, SysResult, SyscallError},
FEATURES, PERF_EVENT_IOC_DISABLE, PERF_EVENT_IOC_ENABLE, PERF_EVENT_IOC_SET_BPF,
};
@ -73,7 +73,7 @@ impl Link for PerfLink {
pub(crate) fn perf_attach(prog_fd: RawFd, fd: OwnedFd) -> Result<PerfLinkInner, ProgramError> {
if FEATURES.bpf_perf_link() {
let link_fd = bpf_link_create(prog_fd, fd.as_raw_fd(), BPF_PERF_EVENT, None, 0).map_err(
|(_, io_error)| ProgramError::SyscallError {
|(_, io_error)| SyscallError {
call: "bpf_link_create",
io_error,
},
@ -98,13 +98,13 @@ fn perf_attach_either(
event: Option<ProbeEvent>,
) -> Result<PerfLinkInner, ProgramError> {
perf_event_ioctl(fd.as_fd(), PERF_EVENT_IOC_SET_BPF, prog_fd).map_err(|(_, io_error)| {
ProgramError::SyscallError {
SyscallError {
call: "PERF_EVENT_IOC_SET_BPF",
io_error,
}
})?;
perf_event_ioctl(fd.as_fd(), PERF_EVENT_IOC_ENABLE, 0).map_err(|(_, io_error)| {
ProgramError::SyscallError {
SyscallError {
call: "PERF_EVENT_IOC_ENABLE",
io_error,
}

@ -19,7 +19,7 @@ use crate::{
perf_attach::{PerfLinkIdInner, PerfLinkInner},
FdLink, LinkError, ProgramData, ProgramError,
},
sys::{bpf_link_get_info_by_fd, perf_event_open},
sys::{bpf_link_get_info_by_fd, perf_event_open, SyscallError},
};
/// The type of perf event
@ -165,7 +165,7 @@ impl PerfEvent {
false,
0,
)
.map_err(|(_code, io_error)| ProgramError::SyscallError {
.map_err(|(_code, io_error)| SyscallError {
call: "perf_event_open",
io_error,
})?;
@ -206,12 +206,10 @@ impl TryFrom<FdLink> for PerfEventLink {
type Error = LinkError;
fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
let info =
bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| LinkError::SyscallError {
call: "BPF_OBJ_GET_INFO_BY_FD",
code: 0,
io_error,
})?;
let info = bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| SyscallError {
call: "BPF_OBJ_GET_INFO_BY_FD",
io_error,
})?;
if info.type_ == (bpf_link_type::BPF_LINK_TYPE_PERF_EVENT as u32) {
return Ok(PerfEventLink::new(PerfLinkInner::FdLink(fd_link)));
}

@ -15,7 +15,7 @@ use crate::{
trace_point::read_sys_fs_trace_point_id, uprobe::UProbeError, utils::find_tracefs_path,
Link, ProgramData, ProgramError,
},
sys::{perf_event_open_probe, perf_event_open_trace_point},
sys::{perf_event_open_probe, perf_event_open_trace_point, SyscallError},
};
static PROBE_NAME_INDEX: AtomicUsize = AtomicUsize::new(0);
@ -118,10 +118,11 @@ fn create_as_probe(
};
perf_event_open_probe(perf_ty, ret_bit, fn_name, offset, pid).map_err(|(_code, io_error)| {
ProgramError::SyscallError {
SyscallError {
call: "perf_event_open",
io_error,
}
.into()
})
}
@ -144,11 +145,9 @@ fn create_as_trace_point(
let category = format!("{}s", kind.pmu());
let tpid = read_sys_fs_trace_point_id(tracefs, &category, &event_alias)?;
let fd = perf_event_open_trace_point(tpid, pid).map_err(|(_code, io_error)| {
ProgramError::SyscallError {
call: "perf_event_open",
io_error,
}
let fd = perf_event_open_trace_point(tpid, pid).map_err(|(_code, io_error)| SyscallError {
call: "perf_event_open",
io_error,
})?;
Ok((fd, event_alias))

@ -3,7 +3,7 @@ use std::os::fd::{AsRawFd, RawFd};
use crate::{
generated::{bpf_attach_type::BPF_SK_LOOKUP, bpf_prog_type::BPF_PROG_TYPE_SK_LOOKUP},
programs::{define_link_wrapper, load_program, FdLinkId, ProgramData, ProgramError},
sys::bpf_link_create,
sys::{bpf_link_create, SyscallError},
};
use super::links::FdLink;
@ -65,7 +65,7 @@ impl SkLookup {
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 {
|(_, io_error)| SyscallError {
call: "bpf_link_create",
io_error,
},

@ -9,7 +9,7 @@ use crate::{
define_link_wrapper, load_program, ProgAttachLink, ProgAttachLinkId, ProgramData,
ProgramError,
},
sys::bpf_prog_attach,
sys::{bpf_prog_attach, SyscallError},
};
/// A program used to intercept messages sent with `sendmsg()`/`sendfile()`.
@ -83,7 +83,7 @@ impl SkMsg {
let map_fd = map.as_raw_fd();
bpf_prog_attach(prog_fd, map_fd, BPF_SK_MSG_VERDICT).map_err(|(_, io_error)| {
ProgramError::SyscallError {
SyscallError {
call: "bpf_prog_attach",
io_error,
}

@ -12,7 +12,7 @@ use crate::{
define_link_wrapper, load_program, ProgAttachLink, ProgAttachLinkId, ProgramData,
ProgramError,
},
sys::bpf_prog_attach,
sys::{bpf_prog_attach, SyscallError},
VerifierLogLevel,
};
@ -79,11 +79,9 @@ 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)| {
ProgramError::SyscallError {
call: "bpf_prog_attach",
io_error,
}
bpf_prog_attach(prog_fd, map_fd, attach_type).map_err(|(_, io_error)| SyscallError {
call: "bpf_prog_attach",
io_error,
})?;
self.data.links.insert(SkSkbLink::new(ProgAttachLink::new(
prog_fd,

@ -7,7 +7,7 @@ use crate::{
define_link_wrapper, load_program, ProgAttachLink, ProgAttachLinkId, ProgramData,
ProgramError,
},
sys::bpf_prog_attach,
sys::{bpf_prog_attach, SyscallError},
};
/// A program used to work with sockets.
@ -63,7 +63,7 @@ impl SockOps {
let cgroup_fd = cgroup.as_raw_fd();
bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SOCK_OPS).map_err(|(_, io_error)| {
ProgramError::SyscallError {
SyscallError {
call: "bpf_prog_attach",
io_error,
}

@ -10,7 +10,7 @@ use crate::{
utils::find_tracefs_path,
FdLink, LinkError, ProgramData, ProgramError,
},
sys::{bpf_link_get_info_by_fd, perf_event_open_trace_point},
sys::{bpf_link_get_info_by_fd, perf_event_open_trace_point, SyscallError},
};
/// The type returned when attaching a [`TracePoint`] fails.
@ -80,12 +80,11 @@ impl TracePoint {
pub fn attach(&mut self, category: &str, name: &str) -> Result<TracePointLinkId, ProgramError> {
let tracefs = find_tracefs_path()?;
let id = read_sys_fs_trace_point_id(tracefs, category, name)?;
let fd = perf_event_open_trace_point(id, None).map_err(|(_code, io_error)| {
ProgramError::SyscallError {
let fd =
perf_event_open_trace_point(id, None).map_err(|(_code, io_error)| SyscallError {
call: "perf_event_open_trace_point",
io_error,
}
})?;
})?;
let link = perf_attach(self.data.fd_or_err()?, fd)?;
self.data.links.insert(TracePointLink::new(link))
@ -132,12 +131,10 @@ impl TryFrom<FdLink> for TracePointLink {
type Error = LinkError;
fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
let info =
bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| LinkError::SyscallError {
call: "BPF_OBJ_GET_INFO_BY_FD",
code: 0,
io_error,
})?;
let info = bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| SyscallError {
call: "BPF_OBJ_GET_INFO_BY_FD",
io_error,
})?;
if info.type_ == (bpf_link_type::BPF_LINK_TYPE_TRACING as u32) {
return Ok(TracePointLink::new(PerfLinkInner::FdLink(fd_link)));
}

@ -21,7 +21,7 @@ use crate::{
probe::{attach, ProbeKind},
FdLink, LinkError, ProgramData, ProgramError,
},
sys::bpf_link_get_info_by_fd,
sys::{bpf_link_get_info_by_fd, SyscallError},
VerifierLogLevel,
};
@ -177,12 +177,10 @@ impl TryFrom<FdLink> for UProbeLink {
type Error = LinkError;
fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
let info =
bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| LinkError::SyscallError {
call: "BPF_OBJ_GET_INFO_BY_FD",
code: 0,
io_error,
})?;
let info = bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| SyscallError {
call: "BPF_OBJ_GET_INFO_BY_FD",
io_error,
})?;
if info.type_ == (bpf_link_type::BPF_LINK_TYPE_TRACING as u32) {
return Ok(UProbeLink::new(PerfLinkInner::FdLink(fd_link)));
}

@ -3,7 +3,7 @@ use std::{ffi::CStr, io, os::fd::RawFd, path::Path};
use crate::{
programs::{FdLink, Link, ProgramData, ProgramError},
sys::bpf_raw_tracepoint_open,
sys::{bpf_raw_tracepoint_open, SyscallError},
};
/// Attaches the program to a raw tracepoint.
@ -13,12 +13,11 @@ 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 {
let pfd =
bpf_raw_tracepoint_open(tp_name, prog_fd).map_err(|(_code, io_error)| SyscallError {
call: "bpf_raw_tracepoint_open",
io_error,
}
})? as RawFd;
})? as RawFd;
program_data.links.insert(FdLink::new(pfd).into())
}

@ -1,6 +1,6 @@
//! eXpress Data Path (XDP) programs.
use crate::util::KernelVersion;
use crate::{sys::SyscallError, util::KernelVersion};
use bitflags;
use libc::if_nametoindex;
use std::{convert::TryFrom, ffi::CString, hash::Hash, io, mem, os::fd::RawFd};
@ -127,7 +127,7 @@ impl Xdp {
if KernelVersion::current().unwrap() >= KernelVersion::new(5, 9, 0) {
let link_fd = bpf_link_create(prog_fd, if_index, BPF_XDP, None, flags.bits()).map_err(
|(_, io_error)| ProgramError::SyscallError {
|(_, io_error)| SyscallError {
call: "bpf_link_create",
io_error,
},
@ -173,7 +173,7 @@ impl Xdp {
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 {
SyscallError {
call: "bpf_link_update",
io_error,
}
@ -279,12 +279,10 @@ 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 {
call: "BPF_OBJ_GET_INFO_BY_FD",
code: 0,
io_error,
})?;
let info = bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| SyscallError {
call: "BPF_OBJ_GET_INFO_BY_FD",
io_error,
})?;
if info.type_ == (bpf_link_type::BPF_LINK_TYPE_XDP as u32) {
return Ok(XdpLink::new(XdpLinkInner::FdLink(fd_link)));
}

@ -905,7 +905,7 @@ pub(crate) fn is_btf_type_tag_supported() -> bool {
bpf_load_btf(btf_bytes.as_slice(), &mut [], Default::default()).is_ok()
}
pub fn sys_bpf(cmd: bpf_cmd, attr: &mut bpf_attr) -> SysResult<c_long> {
fn sys_bpf(cmd: bpf_cmd, attr: &mut bpf_attr) -> SysResult<c_long> {
syscall(Syscall::Bpf { cmd, attr })
}

@ -5,12 +5,12 @@ mod perf_event;
#[cfg(test)]
mod fake;
use libc::{c_int, c_long, pid_t, SYS_bpf, SYS_perf_event_open};
use std::{
io, mem,
os::fd::{AsRawFd as _, BorrowedFd},
};
use libc::{c_int, c_long, pid_t, SYS_bpf, SYS_perf_event_open};
use thiserror::Error;
pub(crate) use bpf::*;
#[cfg(test)]
@ -43,6 +43,16 @@ pub(crate) enum Syscall<'a> {
},
}
#[derive(Debug, Error)]
#[error("`{call}` failed")]
pub struct SyscallError {
/// The name of the syscall which failed.
pub(crate) call: &'static str,
/// The [`io::Error`] returned by the syscall.
#[source]
pub(crate) io_error: io::Error,
}
impl std::fmt::Debug for Syscall<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {

@ -996,9 +996,7 @@ pub aya::maps::MapError::PinError
pub aya::maps::MapError::PinError::error: aya::pin::PinError
pub aya::maps::MapError::PinError::name: core::option::Option<alloc::string::String>
pub aya::maps::MapError::ProgramNotLoaded
pub aya::maps::MapError::SyscallError
pub aya::maps::MapError::SyscallError::call: &'static str
pub aya::maps::MapError::SyscallError::io_error: std::io::error::Error
pub aya::maps::MapError::SyscallError(crate::sys::SyscallError)
pub aya::maps::MapError::Unsupported
pub aya::maps::MapError::Unsupported::map_type: u32
impl core::convert::From<aya::maps::MapError> for aya::BpfError
@ -1764,9 +1762,7 @@ pub aya::pin::PinError::InvalidPinPath
pub aya::pin::PinError::InvalidPinPath::error: alloc::string::String
pub aya::pin::PinError::NoFd
pub aya::pin::PinError::NoFd::name: alloc::string::String
pub aya::pin::PinError::SyscallError
pub aya::pin::PinError::SyscallError::io_error: std::io::error::Error
pub aya::pin::PinError::SyscallError::name: &'static str
pub aya::pin::PinError::SyscallError(crate::sys::SyscallError)
impl core::error::Error for aya::pin::PinError
pub fn aya::pin::PinError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)>
impl core::fmt::Display for aya::pin::PinError
@ -3008,10 +3004,7 @@ pub fn aya::programs::kprobe::KProbeLinkId::from(t: T) -> T
pub mod aya::programs::links
pub enum aya::programs::links::LinkError
pub aya::programs::links::LinkError::InvalidLink
pub aya::programs::links::LinkError::SyscallError
pub aya::programs::links::LinkError::SyscallError::call: &'static str
pub aya::programs::links::LinkError::SyscallError::code: libc::unix::linux_like::linux::gnu::b64::x86_64::not_x32::c_long
pub aya::programs::links::LinkError::SyscallError::io_error: std::io::error::Error
pub aya::programs::links::LinkError::SyscallError(crate::sys::SyscallError)
impl core::error::Error for aya::programs::links::LinkError
pub fn aya::programs::links::LinkError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)>
impl core::fmt::Display for aya::programs::links::LinkError
@ -5174,9 +5167,7 @@ pub aya::programs::ProgramError::MapError(aya::maps::MapError)
pub aya::programs::ProgramError::NotAttached
pub aya::programs::ProgramError::NotLoaded
pub aya::programs::ProgramError::SocketFilterError(aya::programs::SocketFilterError)
pub aya::programs::ProgramError::SyscallError
pub aya::programs::ProgramError::SyscallError::call: &'static str
pub aya::programs::ProgramError::SyscallError::io_error: std::io::error::Error
pub aya::programs::ProgramError::SyscallError(crate::sys::SyscallError)
pub aya::programs::ProgramError::TcError(aya::programs::tc::TcError)
pub aya::programs::ProgramError::TracePointError(aya::programs::trace_point::TracePointError)
pub aya::programs::ProgramError::UProbeError(aya::programs::uprobe::UProbeError)

Loading…
Cancel
Save