s/MiriSafeFd/MockableFd/

The need for this type isn't specific to Miri; it is necessary on
toolchains containing https://github.com/rust-lang/rust/pull/124210 - it
just so happens that today this is nightly only, and so is Miri.
reviewable/pr942/r1
Tamir Duberstein 5 months ago
parent cb6d3bd75d
commit a11b61ebfd

@ -97,37 +97,44 @@ pub use object::Endianness;
pub use sys::netlink_set_link_up; pub use sys::netlink_set_link_up;
// See https://github.com/rust-lang/rust/pull/124210; this structure exists to avoid crashing the // See https://github.com/rust-lang/rust/pull/124210; this structure exists to avoid crashing the
// process when we try to close a fake file descriptor in Miri. // process when we try to close a fake file descriptor.
#[derive(Debug)] #[derive(Debug)]
struct MiriSafeFd { struct MockableFd {
#[cfg(not(miri))] #[cfg(not(test))]
fd: OwnedFd, fd: OwnedFd,
#[cfg(miri)] #[cfg(test)]
fd: Option<OwnedFd>, fd: Option<OwnedFd>,
} }
impl MiriSafeFd { impl MockableFd {
#[cfg(any(test, miri))] #[cfg(test)]
const MOCK_FD: u16 = 1337; const fn mock_signed_fd() -> i32 {
1337
}
#[cfg(test)]
const fn mock_unsigned_fd() -> u32 {
1337
}
#[cfg(not(miri))] #[cfg(not(test))]
fn from_fd(fd: OwnedFd) -> Self { fn from_fd(fd: OwnedFd) -> Self {
Self { fd } Self { fd }
} }
#[cfg(miri)] #[cfg(test)]
fn from_fd(fd: OwnedFd) -> Self { fn from_fd(fd: OwnedFd) -> Self {
Self { fd: Some(fd) } Self { fd: Some(fd) }
} }
#[cfg(not(miri))] #[cfg(not(test))]
fn try_clone(&self) -> std::io::Result<Self> { fn try_clone(&self) -> std::io::Result<Self> {
let Self { fd } = self; let Self { fd } = self;
let fd = fd.try_clone()?; let fd = fd.try_clone()?;
Ok(Self { fd }) Ok(Self { fd })
} }
#[cfg(miri)] #[cfg(test)]
fn try_clone(&self) -> std::io::Result<Self> { fn try_clone(&self) -> std::io::Result<Self> {
let Self { fd } = self; let Self { fd } = self;
let fd = fd.as_ref().map(OwnedFd::try_clone).transpose()?; let fd = fd.as_ref().map(OwnedFd::try_clone).transpose()?;
@ -135,33 +142,34 @@ impl MiriSafeFd {
} }
} }
impl AsFd for MiriSafeFd { impl AsFd for MockableFd {
#[cfg(not(miri))] #[cfg(not(test))]
fn as_fd(&self) -> BorrowedFd<'_> { fn as_fd(&self) -> BorrowedFd<'_> {
let Self { fd } = self; let Self { fd } = self;
fd.as_fd() fd.as_fd()
} }
#[cfg(miri)] #[cfg(test)]
fn as_fd(&self) -> BorrowedFd<'_> { fn as_fd(&self) -> BorrowedFd<'_> {
let Self { fd } = self; let Self { fd } = self;
fd.as_ref().unwrap().as_fd() fd.as_ref().unwrap().as_fd()
} }
} }
impl Drop for MiriSafeFd { impl Drop for MockableFd {
#[cfg(not(miri))] #[cfg(not(test))]
fn drop(&mut self) { fn drop(&mut self) {
// Intentional no-op. // Intentional no-op.
} }
#[cfg(miri)] #[cfg(test)]
fn drop(&mut self) { fn drop(&mut self) {
use std::os::fd::AsRawFd as _; use std::os::fd::AsRawFd as _;
let Self { fd } = self; let Self { fd } = self;
let fd = fd.take().unwrap(); if fd.as_ref().unwrap().as_raw_fd() >= Self::mock_signed_fd() {
assert_eq!(fd.as_raw_fd(), Self::MOCK_FD.into()); let fd: OwnedFd = fd.take().unwrap();
std::mem::forget(fd) std::mem::forget(fd)
} }
}
} }

@ -79,7 +79,7 @@ impl<T: BorrowMut<MapData>, V: Pod> BloomFilter<T, V> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::{ffi::c_long, io}; use std::io;
use assert_matches::assert_matches; use assert_matches::assert_matches;
use libc::{EFAULT, ENOENT}; use libc::{EFAULT, ENOENT};
@ -102,7 +102,7 @@ mod tests {
test_utils::new_obj_map::<u32>(BPF_MAP_TYPE_BLOOM_FILTER) test_utils::new_obj_map::<u32>(BPF_MAP_TYPE_BLOOM_FILTER)
} }
fn sys_error(value: i32) -> SysResult<c_long> { fn sys_error(value: i32) -> SysResult<i64> {
Err((-1, io::Error::from_raw_os_error(value))) Err((-1, io::Error::from_raw_os_error(value)))
} }

@ -103,7 +103,7 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> IterableMap<K, V> for HashMap<T, K, V>
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::{ffi::c_long, io}; use std::io;
use assert_matches::assert_matches; use assert_matches::assert_matches;
use libc::{EFAULT, ENOENT}; use libc::{EFAULT, ENOENT};
@ -126,7 +126,7 @@ mod tests {
test_utils::new_obj_map::<u32>(BPF_MAP_TYPE_HASH) test_utils::new_obj_map::<u32>(BPF_MAP_TYPE_HASH)
} }
fn sys_error(value: i32) -> SysResult<c_long> { fn sys_error(value: i32) -> SysResult<i64> {
Err((-1, io::Error::from_raw_os_error(value))) Err((-1, io::Error::from_raw_os_error(value)))
} }
@ -332,7 +332,7 @@ mod tests {
assert_matches!(keys, Ok(ks) if ks.is_empty()) assert_matches!(keys, Ok(ks) if ks.is_empty())
} }
fn get_next_key(attr: &bpf_attr) -> SysResult<c_long> { fn get_next_key(attr: &bpf_attr) -> SysResult<i64> {
match bpf_key(attr) { match bpf_key(attr) {
None => set_next_key(attr, 10), None => set_next_key(attr, 10),
Some(10) => set_next_key(attr, 20), Some(10) => set_next_key(attr, 20),
@ -344,7 +344,7 @@ mod tests {
Ok(1) Ok(1)
} }
fn lookup_elem(attr: &bpf_attr) -> SysResult<c_long> { fn lookup_elem(attr: &bpf_attr) -> SysResult<i64> {
match bpf_key(attr) { match bpf_key(attr) {
Some(10) => set_ret(attr, 100), Some(10) => set_ret(attr, 100),
Some(20) => set_ret(attr, 200), Some(20) => set_ret(attr, 200),

@ -196,7 +196,7 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> IterableMap<Key<K>, V> for LpmTrie<T, K
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::{ffi::c_long, io, net::Ipv4Addr}; use std::{io, net::Ipv4Addr};
use assert_matches::assert_matches; use assert_matches::assert_matches;
use libc::{EFAULT, ENOENT}; use libc::{EFAULT, ENOENT};
@ -219,7 +219,7 @@ mod tests {
test_utils::new_obj_map::<Key<u32>>(BPF_MAP_TYPE_LPM_TRIE) test_utils::new_obj_map::<Key<u32>>(BPF_MAP_TYPE_LPM_TRIE)
} }
fn sys_error(value: i32) -> SysResult<c_long> { fn sys_error(value: i32) -> SysResult<i64> {
Err((-1, io::Error::from_raw_os_error(value))) Err((-1, io::Error::from_raw_os_error(value)))
} }

@ -49,7 +49,7 @@
//! implement the [Pod] trait. //! implement the [Pod] trait.
use std::{ use std::{
borrow::Borrow, borrow::Borrow,
ffi::{c_long, CString}, ffi::CString,
fmt, io, fmt, io,
marker::PhantomData, marker::PhantomData,
mem, mem,
@ -127,7 +127,7 @@ pub enum MapError {
/// Map name /// Map name
name: String, name: String,
/// Error code /// Error code
code: c_long, code: i64,
#[source] #[source]
/// Original io::Error /// Original io::Error
io_error: io::Error, io_error: io::Error,
@ -211,12 +211,12 @@ impl From<InvalidMapTypeError> for MapError {
/// A map file descriptor. /// A map file descriptor.
#[derive(Debug)] #[derive(Debug)]
pub struct MapFd { pub struct MapFd {
fd: crate::MiriSafeFd, fd: crate::MockableFd,
} }
impl MapFd { impl MapFd {
fn from_fd(fd: OwnedFd) -> Self { fn from_fd(fd: OwnedFd) -> Self {
let fd = crate::MiriSafeFd::from_fd(fd); let fd = crate::MockableFd::from_fd(fd);
Self { fd } Self { fd }
} }
@ -1052,7 +1052,7 @@ mod test_utils {
Syscall::Ebpf { Syscall::Ebpf {
cmd: bpf_cmd::BPF_MAP_CREATE, cmd: bpf_cmd::BPF_MAP_CREATE,
.. ..
} => Ok(crate::MiriSafeFd::MOCK_FD.into()), } => Ok(crate::MockableFd::mock_signed_fd().into()),
call => panic!("unexpected syscall {:?}", call), call => panic!("unexpected syscall {:?}", call),
}); });
MapData::create(obj, "foo", None).unwrap() MapData::create(obj, "foo", None).unwrap()
@ -1103,7 +1103,7 @@ mod tests {
unsafe { attr.__bindgen_anon_6.__bindgen_anon_1.map_id }, unsafe { attr.__bindgen_anon_6.__bindgen_anon_1.map_id },
1234 1234
); );
Ok(crate::MiriSafeFd::MOCK_FD.into()) Ok(crate::MockableFd::mock_signed_fd().into())
} }
Syscall::Ebpf { Syscall::Ebpf {
cmd: bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, cmd: bpf_cmd::BPF_OBJ_GET_INFO_BY_FD,
@ -1111,7 +1111,7 @@ mod tests {
} => { } => {
assert_eq!( assert_eq!(
unsafe { attr.info.bpf_fd }, unsafe { attr.info.bpf_fd },
crate::MiriSafeFd::MOCK_FD.into() crate::MockableFd::mock_unsigned_fd(),
); );
Ok(0) Ok(0)
} }
@ -1123,7 +1123,7 @@ mod tests {
Ok(MapData { Ok(MapData {
obj: _, obj: _,
fd, fd,
}) => assert_eq!(fd.as_fd().as_raw_fd(), crate::MiriSafeFd::MOCK_FD.into()) }) => assert_eq!(fd.as_fd().as_raw_fd(), crate::MockableFd::mock_signed_fd())
); );
} }
@ -1133,7 +1133,7 @@ mod tests {
Syscall::Ebpf { Syscall::Ebpf {
cmd: bpf_cmd::BPF_MAP_CREATE, cmd: bpf_cmd::BPF_MAP_CREATE,
.. ..
} => Ok(crate::MiriSafeFd::MOCK_FD.into()), } => Ok(crate::MockableFd::mock_signed_fd().into()),
_ => Err((-1, io::Error::from_raw_os_error(EFAULT))), _ => Err((-1, io::Error::from_raw_os_error(EFAULT))),
}); });
@ -1142,7 +1142,7 @@ mod tests {
Ok(MapData { Ok(MapData {
obj: _, obj: _,
fd, fd,
}) => assert_eq!(fd.as_fd().as_raw_fd(), crate::MiriSafeFd::MOCK_FD.into()) }) => assert_eq!(fd.as_fd().as_raw_fd(), crate::MockableFd::mock_signed_fd())
); );
} }
@ -1160,7 +1160,7 @@ mod tests {
Syscall::Ebpf { Syscall::Ebpf {
cmd: bpf_cmd::BPF_MAP_CREATE, cmd: bpf_cmd::BPF_MAP_CREATE,
.. ..
} => Ok(42), } => Ok(crate::MockableFd::mock_signed_fd().into()),
Syscall::Ebpf { Syscall::Ebpf {
cmd: bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, cmd: bpf_cmd::BPF_OBJ_GET_INFO_BY_FD,
attr, attr,
@ -1206,13 +1206,15 @@ mod tests {
Syscall::Ebpf { Syscall::Ebpf {
cmd: bpf_cmd::BPF_MAP_GET_FD_BY_ID, cmd: bpf_cmd::BPF_MAP_GET_FD_BY_ID,
attr, attr,
} => Ok((1000 + unsafe { attr.__bindgen_anon_6.__bindgen_anon_1.map_id }) as c_long), } => Ok((unsafe { attr.__bindgen_anon_6.__bindgen_anon_1.map_id }
+ crate::MockableFd::mock_unsigned_fd())
.into()),
Syscall::Ebpf { Syscall::Ebpf {
cmd: bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, cmd: bpf_cmd::BPF_OBJ_GET_INFO_BY_FD,
attr, attr,
} => { } => {
let map_info = unsafe { &mut *(attr.info.info as *mut bpf_map_info) }; let map_info = unsafe { &mut *(attr.info.info as *mut bpf_map_info) };
map_info.id = unsafe { attr.info.bpf_fd } - 1000; map_info.id = unsafe { attr.info.bpf_fd } - crate::MockableFd::mock_unsigned_fd();
map_info.key_size = 32; map_info.key_size = 32;
map_info.value_size = 64; map_info.value_size = 64;
map_info.map_flags = 1234; map_info.map_flags = 1234;
@ -1222,19 +1224,31 @@ mod tests {
_ => Err((-1, io::Error::from_raw_os_error(EFAULT))), _ => Err((-1, io::Error::from_raw_os_error(EFAULT))),
}); });
let loaded_maps: Vec<_> = loaded_maps().collect(); assert_eq!(
assert_eq!(loaded_maps.len(), 5); loaded_maps()
.map(|map_info| {
for (i, map_info) in loaded_maps.into_iter().enumerate() {
let i = i + 1;
let map_info = map_info.unwrap(); let map_info = map_info.unwrap();
assert_eq!(map_info.id(), i as u32); (
assert_eq!(map_info.key_size(), 32); map_info.id(),
assert_eq!(map_info.value_size(), 64); map_info.key_size(),
assert_eq!(map_info.map_flags(), 1234); map_info.value_size(),
assert_eq!(map_info.max_entries(), 99); map_info.map_flags(),
assert_eq!(map_info.fd().unwrap().as_fd().as_raw_fd(), 1000 + i as i32); map_info.max_entries(),
} map_info.fd().unwrap().as_fd().as_raw_fd(),
)
})
.collect::<Vec<_>>(),
(1..6)
.map(|i: u8| (
i.into(),
32,
64,
1234,
99,
crate::MockableFd::mock_signed_fd() + i32::from(i)
))
.collect::<Vec<_>>(),
);
} }
#[test] #[test]

@ -88,7 +88,7 @@ pub(crate) struct PerfBuffer {
buf: AtomicPtr<perf_event_mmap_page>, buf: AtomicPtr<perf_event_mmap_page>,
size: usize, size: usize,
page_size: usize, page_size: usize,
fd: crate::MiriSafeFd, fd: crate::MockableFd,
} }
impl PerfBuffer { impl PerfBuffer {
@ -120,7 +120,7 @@ impl PerfBuffer {
}); });
} }
let fd = crate::MiriSafeFd::from_fd(fd); let fd = crate::MockableFd::from_fd(fd);
let perf_buf = Self { let perf_buf = Self {
buf: AtomicPtr::new(buf as *mut perf_event_mmap_page), buf: AtomicPtr::new(buf as *mut perf_event_mmap_page),
size, size,
@ -303,7 +303,7 @@ mod tests {
fn fake_mmap(buf: &MMappedBuf) { fn fake_mmap(buf: &MMappedBuf) {
override_syscall(|call| match call { override_syscall(|call| match call {
Syscall::PerfEventOpen { .. } | Syscall::PerfEventIoctl { .. } => { Syscall::PerfEventOpen { .. } | Syscall::PerfEventIoctl { .. } => {
Ok(crate::MiriSafeFd::MOCK_FD.into()) Ok(crate::MockableFd::mock_signed_fd().into())
} }
call => panic!("unexpected syscall: {:?}", call), call => panic!("unexpected syscall: {:?}", call),
}); });

@ -1,6 +1,6 @@
use std::{ use std::{
cmp, cmp,
ffi::{c_char, c_long, CStr, CString}, ffi::{c_char, CStr, CString},
io, iter, io, iter,
mem::{self, MaybeUninit}, mem::{self, MaybeUninit},
os::fd::{AsFd as _, AsRawFd as _, BorrowedFd, FromRawFd as _, OwnedFd, RawFd}, os::fd::{AsFd as _, AsRawFd as _, BorrowedFd, FromRawFd as _, OwnedFd, RawFd},
@ -96,7 +96,7 @@ pub(crate) fn bpf_create_map(
unsafe { fd_sys_bpf(bpf_cmd::BPF_MAP_CREATE, &mut attr) } unsafe { fd_sys_bpf(bpf_cmd::BPF_MAP_CREATE, &mut attr) }
} }
pub(crate) fn bpf_pin_object(fd: BorrowedFd<'_>, path: &CStr) -> SysResult<c_long> { pub(crate) fn bpf_pin_object(fd: BorrowedFd<'_>, path: &CStr) -> SysResult<i64> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_4 }; let u = unsafe { &mut attr.__bindgen_anon_4 };
u.bpf_fd = fd.as_raw_fd() as u32; u.bpf_fd = fd.as_raw_fd() as u32;
@ -200,7 +200,7 @@ fn lookup<K: Pod, V: Pod>(
key: Option<&K>, key: Option<&K>,
flags: u64, flags: u64,
cmd: bpf_cmd, cmd: bpf_cmd,
) -> Result<Option<V>, (c_long, io::Error)> { ) -> SysResult<Option<V>> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let mut value = MaybeUninit::zeroed(); let mut value = MaybeUninit::zeroed();
@ -223,7 +223,7 @@ pub(crate) fn bpf_map_lookup_elem<K: Pod, V: Pod>(
fd: BorrowedFd<'_>, fd: BorrowedFd<'_>,
key: &K, key: &K,
flags: u64, flags: u64,
) -> Result<Option<V>, (c_long, io::Error)> { ) -> SysResult<Option<V>> {
lookup(fd, Some(key), flags, bpf_cmd::BPF_MAP_LOOKUP_ELEM) lookup(fd, Some(key), flags, bpf_cmd::BPF_MAP_LOOKUP_ELEM)
} }
@ -231,7 +231,7 @@ pub(crate) fn bpf_map_lookup_and_delete_elem<K: Pod, V: Pod>(
fd: BorrowedFd<'_>, fd: BorrowedFd<'_>,
key: Option<&K>, key: Option<&K>,
flags: u64, flags: u64,
) -> Result<Option<V>, (c_long, io::Error)> { ) -> SysResult<Option<V>> {
lookup(fd, key, flags, bpf_cmd::BPF_MAP_LOOKUP_AND_DELETE_ELEM) lookup(fd, key, flags, bpf_cmd::BPF_MAP_LOOKUP_AND_DELETE_ELEM)
} }
@ -239,7 +239,7 @@ pub(crate) fn bpf_map_lookup_elem_per_cpu<K: Pod, V: Pod>(
fd: BorrowedFd<'_>, fd: BorrowedFd<'_>,
key: &K, key: &K,
flags: u64, flags: u64,
) -> Result<Option<PerCpuValues<V>>, (c_long, io::Error)> { ) -> SysResult<Option<PerCpuValues<V>>> {
let mut mem = PerCpuValues::<V>::alloc_kernel_mem().map_err(|io_error| (-1, io_error))?; let mut mem = PerCpuValues::<V>::alloc_kernel_mem().map_err(|io_error| (-1, io_error))?;
match bpf_map_lookup_elem_ptr(fd, Some(key), mem.as_mut_ptr(), flags) { match bpf_map_lookup_elem_ptr(fd, Some(key), mem.as_mut_ptr(), flags) {
Ok(_) => Ok(Some(unsafe { PerCpuValues::from_kernel_mem(mem) })), Ok(_) => Ok(Some(unsafe { PerCpuValues::from_kernel_mem(mem) })),
@ -253,7 +253,7 @@ pub(crate) fn bpf_map_lookup_elem_ptr<K: Pod, V>(
key: Option<&K>, key: Option<&K>,
value: *mut V, value: *mut V,
flags: u64, flags: u64,
) -> Result<Option<()>, (c_long, io::Error)> { ) -> SysResult<Option<()>> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_2 }; let u = unsafe { &mut attr.__bindgen_anon_2 };
@ -276,7 +276,7 @@ pub(crate) fn bpf_map_update_elem<K: Pod, V: Pod>(
key: Option<&K>, key: Option<&K>,
value: &V, value: &V,
flags: u64, flags: u64,
) -> SysResult<c_long> { ) -> SysResult<i64> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_2 }; let u = unsafe { &mut attr.__bindgen_anon_2 };
@ -294,7 +294,7 @@ pub(crate) fn bpf_map_push_elem<V: Pod>(
fd: BorrowedFd<'_>, fd: BorrowedFd<'_>,
value: &V, value: &V,
flags: u64, flags: u64,
) -> SysResult<c_long> { ) -> SysResult<i64> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_2 }; let u = unsafe { &mut attr.__bindgen_anon_2 };
@ -310,7 +310,7 @@ pub(crate) fn bpf_map_update_elem_ptr<K, V>(
key: *const K, key: *const K,
value: *mut V, value: *mut V,
flags: u64, flags: u64,
) -> SysResult<c_long> { ) -> SysResult<i64> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_2 }; let u = unsafe { &mut attr.__bindgen_anon_2 };
@ -327,12 +327,12 @@ pub(crate) fn bpf_map_update_elem_per_cpu<K: Pod, V: Pod>(
key: &K, key: &K,
values: &PerCpuValues<V>, values: &PerCpuValues<V>,
flags: u64, flags: u64,
) -> SysResult<c_long> { ) -> SysResult<i64> {
let mut mem = values.build_kernel_mem().map_err(|e| (-1, e))?; let mut mem = values.build_kernel_mem().map_err(|e| (-1, e))?;
bpf_map_update_elem_ptr(fd, key, mem.as_mut_ptr(), flags) bpf_map_update_elem_ptr(fd, key, mem.as_mut_ptr(), flags)
} }
pub(crate) fn bpf_map_delete_elem<K: Pod>(fd: BorrowedFd<'_>, key: &K) -> SysResult<c_long> { pub(crate) fn bpf_map_delete_elem<K: Pod>(fd: BorrowedFd<'_>, key: &K) -> SysResult<i64> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_2 }; let u = unsafe { &mut attr.__bindgen_anon_2 };
@ -345,7 +345,7 @@ pub(crate) fn bpf_map_delete_elem<K: Pod>(fd: BorrowedFd<'_>, key: &K) -> SysRes
pub(crate) fn bpf_map_get_next_key<K: Pod>( pub(crate) fn bpf_map_get_next_key<K: Pod>(
fd: BorrowedFd<'_>, fd: BorrowedFd<'_>,
key: Option<&K>, key: Option<&K>,
) -> Result<Option<K>, (c_long, io::Error)> { ) -> SysResult<Option<K>> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let mut next_key = MaybeUninit::uninit(); let mut next_key = MaybeUninit::uninit();
@ -364,7 +364,7 @@ pub(crate) fn bpf_map_get_next_key<K: Pod>(
} }
// since kernel 5.2 // since kernel 5.2
pub(crate) fn bpf_map_freeze(fd: BorrowedFd<'_>) -> SysResult<c_long> { pub(crate) fn bpf_map_freeze(fd: BorrowedFd<'_>) -> SysResult<i64> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_2 }; let u = unsafe { &mut attr.__bindgen_anon_2 };
u.map_fd = fd.as_raw_fd() as u32; u.map_fd = fd.as_raw_fd() as u32;
@ -412,7 +412,7 @@ pub(crate) fn bpf_link_update(
new_prog_fd: BorrowedFd<'_>, new_prog_fd: BorrowedFd<'_>,
old_prog_fd: Option<RawFd>, old_prog_fd: Option<RawFd>,
flags: u32, flags: u32,
) -> SysResult<c_long> { ) -> SysResult<i64> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.link_update.link_fd = link_fd.as_raw_fd() as u32; attr.link_update.link_fd = link_fd.as_raw_fd() as u32;
@ -478,7 +478,7 @@ pub(crate) fn bpf_prog_query(
attach_flags: Option<&mut u32>, attach_flags: Option<&mut u32>,
prog_ids: &mut [u32], prog_ids: &mut [u32],
prog_cnt: &mut u32, prog_cnt: &mut u32,
) -> SysResult<c_long> { ) -> SysResult<i64> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.query.__bindgen_anon_1.target_fd = target_fd as u32; attr.query.__bindgen_anon_1.target_fd = target_fd as u32;
@ -730,7 +730,7 @@ pub(crate) fn is_perf_link_supported() -> bool {
u.prog_type = bpf_prog_type::BPF_PROG_TYPE_TRACEPOINT as u32; u.prog_type = bpf_prog_type::BPF_PROG_TYPE_TRACEPOINT as u32;
if let Ok(fd) = bpf_prog_load(&mut attr) { if let Ok(fd) = bpf_prog_load(&mut attr) {
let fd = crate::MiriSafeFd::from_fd(fd); let fd = crate::MockableFd::from_fd(fd);
let fd = fd.as_fd(); let fd = fd.as_fd();
matches!( matches!(
// Uses an invalid target FD so we get EBADF if supported. // Uses an invalid target FD so we get EBADF if supported.
@ -830,7 +830,7 @@ pub(crate) fn is_prog_id_supported(map_type: bpf_map_type) -> bool {
// SAFETY: BPF_MAP_CREATE returns a new file descriptor. // SAFETY: BPF_MAP_CREATE returns a new file descriptor.
let fd = unsafe { fd_sys_bpf(bpf_cmd::BPF_MAP_CREATE, &mut attr) }; let fd = unsafe { fd_sys_bpf(bpf_cmd::BPF_MAP_CREATE, &mut attr) };
let fd = fd.map(crate::MiriSafeFd::from_fd); let fd = fd.map(crate::MockableFd::from_fd);
fd.is_ok() fd.is_ok()
} }
@ -995,7 +995,7 @@ fn bpf_prog_load(attr: &mut bpf_attr) -> SysResult<OwnedFd> {
unsafe { fd_sys_bpf(bpf_cmd::BPF_PROG_LOAD, attr) } unsafe { fd_sys_bpf(bpf_cmd::BPF_PROG_LOAD, attr) }
} }
fn sys_bpf(cmd: bpf_cmd, attr: &mut bpf_attr) -> SysResult<c_long> { fn sys_bpf(cmd: bpf_cmd, attr: &mut bpf_attr) -> SysResult<i64> {
syscall(Syscall::Ebpf { cmd, attr }) syscall(Syscall::Ebpf { cmd, attr })
} }
@ -1103,7 +1103,7 @@ mod tests {
cmd: bpf_cmd::BPF_LINK_CREATE, cmd: bpf_cmd::BPF_LINK_CREATE,
.. ..
} => Err((-1, io::Error::from_raw_os_error(EBADF))), } => Err((-1, io::Error::from_raw_os_error(EBADF))),
_ => Ok(crate::MiriSafeFd::MOCK_FD.into()), _ => Ok(crate::MockableFd::mock_signed_fd().into()),
}); });
let supported = is_perf_link_supported(); let supported = is_perf_link_supported();
assert!(supported); assert!(supported);
@ -1113,7 +1113,7 @@ mod tests {
cmd: bpf_cmd::BPF_LINK_CREATE, cmd: bpf_cmd::BPF_LINK_CREATE,
.. ..
} => Err((-1, io::Error::from_raw_os_error(EINVAL))), } => Err((-1, io::Error::from_raw_os_error(EINVAL))),
_ => Ok(crate::MiriSafeFd::MOCK_FD.into()), _ => Ok(crate::MockableFd::mock_signed_fd().into()),
}); });
let supported = is_perf_link_supported(); let supported = is_perf_link_supported();
assert!(!supported); assert!(!supported);
@ -1121,7 +1121,7 @@ mod tests {
#[test] #[test]
fn test_prog_id_supported() { fn test_prog_id_supported() {
override_syscall(|_call| Ok(crate::MiriSafeFd::MOCK_FD.into())); override_syscall(|_call| Ok(crate::MockableFd::mock_signed_fd().into()));
// Ensure that the three map types we can check are accepted // Ensure that the three map types we can check are accepted
let supported = is_prog_id_supported(bpf_map_type::BPF_MAP_TYPE_CPUMAP); let supported = is_prog_id_supported(bpf_map_type::BPF_MAP_TYPE_CPUMAP);

@ -1,12 +1,8 @@
use std::{ use std::{cell::RefCell, ffi::c_void, io, ptr};
cell::RefCell,
ffi::{c_long, c_void},
io, ptr,
};
use super::{SysResult, Syscall}; use super::{SysResult, Syscall};
type SyscallFn = unsafe fn(Syscall<'_>) -> SysResult<c_long>; type SyscallFn = unsafe fn(Syscall<'_>) -> SysResult<i64>;
#[cfg(test)] #[cfg(test)]
thread_local! { thread_local! {
@ -15,11 +11,11 @@ thread_local! {
} }
#[cfg(test)] #[cfg(test)]
unsafe fn test_syscall(_call: Syscall<'_>) -> SysResult<c_long> { unsafe fn test_syscall(_call: Syscall<'_>) -> SysResult<i64> {
Err((-1, io::Error::from_raw_os_error(libc::EINVAL))) Err((-1, io::Error::from_raw_os_error(libc::EINVAL)))
} }
#[cfg(test)] #[cfg(test)]
pub(crate) fn override_syscall(call: unsafe fn(Syscall<'_>) -> SysResult<c_long>) { pub(crate) fn override_syscall(call: unsafe fn(Syscall<'_>) -> SysResult<i64>) {
TEST_SYSCALL.with(|test_impl| *test_impl.borrow_mut() = call); TEST_SYSCALL.with(|test_impl| *test_impl.borrow_mut() = call);
} }

@ -6,7 +6,7 @@ mod perf_event;
mod fake; mod fake;
use std::{ use std::{
ffi::{c_int, c_long, c_void}, ffi::{c_int, c_void},
io, mem, io, mem,
os::fd::{AsRawFd as _, BorrowedFd}, os::fd::{AsRawFd as _, BorrowedFd},
}; };
@ -23,7 +23,7 @@ use thiserror::Error;
use crate::generated::{bpf_attr, bpf_cmd, perf_event_attr}; use crate::generated::{bpf_attr, bpf_cmd, perf_event_attr};
pub(crate) type SysResult<T> = Result<T, (c_long, io::Error)>; pub(crate) type SysResult<T> = Result<T, (i64, io::Error)>;
pub(crate) enum Syscall<'a> { pub(crate) enum Syscall<'a> {
Ebpf { Ebpf {
@ -86,12 +86,13 @@ impl std::fmt::Debug for Syscall<'_> {
} }
} }
fn syscall(call: Syscall<'_>) -> SysResult<c_long> { fn syscall(call: Syscall<'_>) -> SysResult<i64> {
#[cfg(test)] #[cfg(test)]
return TEST_SYSCALL.with(|test_impl| unsafe { test_impl.borrow()(call) }); return TEST_SYSCALL.with(|test_impl| unsafe { test_impl.borrow()(call) });
#[cfg_attr(test, allow(unreachable_code))] #[cfg_attr(test, allow(unreachable_code))]
match unsafe { {
let ret = unsafe {
match call { match call {
Syscall::Ebpf { cmd, attr } => { Syscall::Ebpf { cmd, attr } => {
libc::syscall(SYS_bpf, cmd, attr, mem::size_of::<bpf_attr>()) libc::syscall(SYS_bpf, cmd, attr, mem::size_of::<bpf_attr>())
@ -104,16 +105,21 @@ fn syscall(call: Syscall<'_>) -> SysResult<c_long> {
flags, flags,
} => libc::syscall(SYS_perf_event_open, &attr, pid, cpu, group, flags), } => libc::syscall(SYS_perf_event_open, &attr, pid, cpu, group, flags),
Syscall::PerfEventIoctl { fd, request, arg } => { Syscall::PerfEventIoctl { fd, request, arg } => {
let int = libc::ioctl(fd.as_raw_fd(), request.try_into().unwrap(), arg); let ret = libc::ioctl(fd.as_raw_fd(), request.try_into().unwrap(), arg);
#[allow(trivial_numeric_casts)] // `libc::ioctl` returns i32 on x86_64 while `libc::syscall` returns i64.
let int = int as c_long; #[allow(clippy::useless_conversion)]
int ret.into()
} }
} }
} { };
// `libc::syscall` returns i32 on armv7.
#[allow(clippy::useless_conversion)]
match ret.into() {
ret @ 0.. => Ok(ret), ret @ 0.. => Ok(ret),
ret => Err((ret, io::Error::last_os_error())), ret => Err((ret, io::Error::last_os_error())),
} }
}
} }
#[cfg_attr(test, allow(unused_variables))] #[cfg_attr(test, allow(unused_variables))]

@ -1,5 +1,5 @@
use std::{ use std::{
ffi::{c_int, c_long, CString, OsStr}, ffi::{c_int, CString, OsStr},
io, mem, io, mem,
os::fd::{BorrowedFd, FromRawFd as _, OwnedFd}, os::fd::{BorrowedFd, FromRawFd as _, OwnedFd},
}; };
@ -101,11 +101,7 @@ pub(crate) fn perf_event_open_trace_point(id: u32, pid: Option<pid_t>) -> SysRes
perf_event_sys(attr, pid, cpu, PERF_FLAG_FD_CLOEXEC) perf_event_sys(attr, pid, cpu, PERF_FLAG_FD_CLOEXEC)
} }
pub(crate) fn perf_event_ioctl( pub(crate) fn perf_event_ioctl(fd: BorrowedFd<'_>, request: c_int, arg: c_int) -> SysResult<i64> {
fd: BorrowedFd<'_>,
request: c_int,
arg: c_int,
) -> SysResult<c_long> {
let call = Syscall::PerfEventIoctl { fd, request, arg }; let call = Syscall::PerfEventIoctl { fd, request, arg };
#[cfg(not(test))] #[cfg(not(test))]
return syscall(call); return syscall(call);

@ -1330,7 +1330,7 @@ impl<T> core::convert::From<T> for aya::maps::Map
pub fn aya::maps::Map::from(t: T) -> T pub fn aya::maps::Map::from(t: T) -> T
pub enum aya::maps::MapError pub enum aya::maps::MapError
pub aya::maps::MapError::CreateError pub aya::maps::MapError::CreateError
pub aya::maps::MapError::CreateError::code: core::ffi::c_long pub aya::maps::MapError::CreateError::code: i64
pub aya::maps::MapError::CreateError::io_error: std::io::error::Error pub aya::maps::MapError::CreateError::io_error: std::io::error::Error
pub aya::maps::MapError::CreateError::name: alloc::string::String pub aya::maps::MapError::CreateError::name: alloc::string::String
pub aya::maps::MapError::ElementNotFound pub aya::maps::MapError::ElementNotFound

Loading…
Cancel
Save