Merge pull request #662 from nrxus/use-owned-fd-for-btf

Use `OwnedFd` for BTF's file descriptor
pull/699/head
Tamir Duberstein 1 year ago committed by GitHub
commit 13e83b24ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -9,6 +9,7 @@ repository = "https://github.com/aya-rs/aya"
readme = "README.md" readme = "README.md"
documentation = "https://docs.rs/aya" documentation = "https://docs.rs/aya"
edition = "2021" edition = "2021"
rust-version = "1.66"
[dependencies] [dependencies]
async-io = { workspace = true, optional = true } async-io = { workspace = true, optional = true }

@ -3,8 +3,12 @@ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
ffi::CString, ffi::CString,
fs, io, fs, io,
os::{raw::c_int, unix::io::RawFd}, os::{
fd::{OwnedFd, RawFd},
raw::c_int,
},
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::Arc,
}; };
use aya_obj::{ use aya_obj::{
@ -390,7 +394,7 @@ impl<'a> BpfLoader<'a> {
let btf_fd = if let Some(features) = &FEATURES.btf() { let btf_fd = if let Some(features) = &FEATURES.btf() {
if let Some(btf) = obj.fixup_and_sanitize_btf(features)? { if let Some(btf) = obj.fixup_and_sanitize_btf(features)? {
match load_btf(btf.to_bytes(), *verifier_log_level) { match load_btf(btf.to_bytes(), *verifier_log_level) {
Ok(btf_fd) => Some(btf_fd), Ok(btf_fd) => Some(Arc::new(btf_fd)),
// Only report an error here if the BTF is truely needed, otherwise proceed without. // Only report an error here if the BTF is truely needed, otherwise proceed without.
Err(err) => { Err(err) => {
for program in obj.programs.values() { for program in obj.programs.values() {
@ -473,7 +477,7 @@ impl<'a> BpfLoader<'a> {
obj, obj,
fd: None, fd: None,
pinned: false, pinned: false,
btf_fd, btf_fd: btf_fd.as_ref().map(Arc::clone),
}; };
let fd = match map.obj.pinning() { let fd = match map.obj.pinning() {
PinningType::ByName => { PinningType::ByName => {
@ -543,6 +547,7 @@ impl<'a> BpfLoader<'a> {
let section = prog_obj.section.clone(); let section = prog_obj.section.clone();
let obj = (prog_obj, function_obj); let obj = (prog_obj, function_obj);
let btf_fd = btf_fd.as_ref().map(Arc::clone);
let program = if extensions.contains(name.as_str()) { let program = if extensions.contains(name.as_str()) {
Program::Extension(Extension { Program::Extension(Extension {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
@ -993,17 +998,14 @@ pub enum BpfError {
ProgramError(#[from] ProgramError), ProgramError(#[from] ProgramError),
} }
fn load_btf(raw_btf: Vec<u8>, verifier_log_level: VerifierLogLevel) -> Result<RawFd, BtfError> { fn load_btf(raw_btf: Vec<u8>, verifier_log_level: VerifierLogLevel) -> Result<OwnedFd, BtfError> {
let (ret, verifier_log) = retry_with_verifier_logs(10, |logger| { let (ret, verifier_log) = retry_with_verifier_logs(10, |logger| {
bpf_load_btf(raw_btf.as_slice(), logger, verifier_log_level) bpf_load_btf(raw_btf.as_slice(), logger, verifier_log_level)
}); });
match ret { ret.map_err(|(_, io_error)| BtfError::LoadError {
Ok(fd) => Ok(fd as RawFd), io_error,
Err((_, io_error)) => Err(BtfError::LoadError { verifier_log,
io_error, })
verifier_log,
}),
}
} }
/// Global data that can be exported to eBPF programs before they are loaded. /// Global data that can be exported to eBPF programs before they are loaded.

@ -90,7 +90,7 @@ mod tests {
}; };
use assert_matches::assert_matches; use assert_matches::assert_matches;
use libc::{EFAULT, ENOENT}; use libc::{EFAULT, ENOENT};
use std::io; use std::{ffi::c_long, io};
fn new_obj_map() -> obj::Map { fn new_obj_map() -> obj::Map {
obj::Map::Legacy(LegacyMap { obj::Map::Legacy(LegacyMap {
@ -108,7 +108,7 @@ mod tests {
}) })
} }
fn sys_error(value: i32) -> SysResult { fn sys_error(value: i32) -> SysResult<c_long> {
Err((-1, io::Error::from_raw_os_error(value))) Err((-1, io::Error::from_raw_os_error(value)))
} }

@ -105,7 +105,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::io; use std::{ffi::c_long, io};
use assert_matches::assert_matches; use assert_matches::assert_matches;
use libc::{EFAULT, ENOENT}; use libc::{EFAULT, ENOENT};
@ -139,7 +139,7 @@ mod tests {
}) })
} }
fn sys_error(value: i32) -> SysResult { fn sys_error(value: i32) -> SysResult<c_long> {
Err((-1, io::Error::from_raw_os_error(value))) Err((-1, io::Error::from_raw_os_error(value)))
} }
@ -451,7 +451,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 { fn get_next_key(attr: &bpf_attr) -> SysResult<c_long> {
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),
@ -463,7 +463,7 @@ mod tests {
Ok(1) Ok(1)
} }
fn lookup_elem(attr: &bpf_attr) -> SysResult { fn lookup_elem(attr: &bpf_attr) -> SysResult<c_long> {
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),

@ -209,7 +209,7 @@ mod tests {
}; };
use assert_matches::assert_matches; use assert_matches::assert_matches;
use libc::{EFAULT, ENOENT}; use libc::{EFAULT, ENOENT};
use std::{io, mem, net::Ipv4Addr}; use std::{ffi::c_long, io, mem, net::Ipv4Addr};
fn new_obj_map() -> obj::Map { fn new_obj_map() -> obj::Map {
obj::Map::Legacy(LegacyMap { obj::Map::Legacy(LegacyMap {
@ -227,7 +227,7 @@ mod tests {
}) })
} }
fn sys_error(value: i32) -> SysResult { fn sys_error(value: i32) -> SysResult<c_long> {
Err((-1, io::Error::from_raw_os_error(value))) Err((-1, io::Error::from_raw_os_error(value)))
} }

@ -42,9 +42,10 @@ use std::{
marker::PhantomData, marker::PhantomData,
mem, mem,
ops::Deref, ops::Deref,
os::fd::{AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd, OwnedFd, RawFd},
path::Path, path::Path,
ptr, ptr,
sync::Arc,
}; };
use crate::util::KernelVersion; use crate::util::KernelVersion;
@ -486,7 +487,7 @@ pub(crate) fn check_v_size<V>(map: &MapData) -> Result<(), MapError> {
pub struct MapData { pub struct MapData {
pub(crate) obj: obj::Map, pub(crate) obj: obj::Map,
pub(crate) fd: Option<RawFd>, pub(crate) fd: Option<RawFd>,
pub(crate) btf_fd: Option<RawFd>, pub(crate) btf_fd: Option<Arc<OwnedFd>>,
/// Indicates if this map has been pinned to bpffs /// Indicates if this map has been pinned to bpffs
pub pinned: bool, pub pinned: bool,
} }
@ -504,19 +505,23 @@ impl MapData {
let kernel_version = KernelVersion::current().unwrap(); let kernel_version = KernelVersion::current().unwrap();
#[cfg(test)] #[cfg(test)]
let kernel_version = KernelVersion::new(0xff, 0xff, 0xff); let kernel_version = KernelVersion::new(0xff, 0xff, 0xff);
let fd = bpf_create_map(&c_name, &self.obj, self.btf_fd, kernel_version).map_err( let fd = bpf_create_map(
|(code, io_error)| { &c_name,
if kernel_version < KernelVersion::new(5, 11, 0) { &self.obj,
maybe_warn_rlimit(); self.btf_fd.as_ref().map(|f| f.as_fd()),
} kernel_version,
)
.map_err(|(code, io_error)| {
if kernel_version < KernelVersion::new(5, 11, 0) {
maybe_warn_rlimit();
}
MapError::CreateError { MapError::CreateError {
name: name.into(), name: name.into(),
code, code,
io_error, io_error,
} }
}, })? as RawFd;
)? as RawFd;
self.fd = Some(fd); self.fd = Some(fd);
@ -639,7 +644,7 @@ impl Clone for MapData {
MapData { MapData {
obj: self.obj.clone(), obj: self.obj.clone(),
fd: self.fd.map(|fd| unsafe { libc::dup(fd) }), fd: self.fd.map(|fd| unsafe { libc::dup(fd) }),
btf_fd: self.btf_fd, btf_fd: self.btf_fd.as_ref().map(Arc::clone),
pinned: self.pinned, pinned: self.pinned,
} }
} }

@ -1,7 +1,7 @@
use std::{ use std::{
ffi::c_void, ffi::c_void,
io, mem, io, mem,
os::unix::io::{AsRawFd, RawFd}, os::fd::{AsRawFd, RawFd},
ptr, slice, ptr, slice,
sync::atomic::{self, AtomicPtr, Ordering}, sync::atomic::{self, AtomicPtr, Ordering},
}; };

@ -4,7 +4,7 @@
use std::{ use std::{
borrow::{Borrow, BorrowMut}, borrow::{Borrow, BorrowMut},
ops::Deref, ops::Deref,
os::unix::io::{AsRawFd, RawFd}, os::fd::{AsRawFd, RawFd},
sync::Arc, sync::Arc,
}; };
@ -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. /// 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 /// 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: /// To receive events you need to:
/// * call [`PerfEventArray::open`] /// * 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 /// 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 /// 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 /// 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 /// amounts of data, in order not to lose events you might want to process each

@ -5,7 +5,7 @@ mod sock_map;
pub use sock_hash::SockHash; pub use sock_hash::SockHash;
pub use sock_map::SockMap; pub use sock_map::SockMap;
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::fd::{AsRawFd, RawFd};
/// A socket map file descriptor. /// A socket map file descriptor.
#[derive(Copy, Clone)] #[derive(Copy, Clone)]

@ -1,7 +1,7 @@
use std::{ use std::{
borrow::{Borrow, BorrowMut}, borrow::{Borrow, BorrowMut},
marker::PhantomData, marker::PhantomData,
os::unix::io::{AsRawFd, RawFd}, os::fd::{AsRawFd, RawFd},
}; };
use crate::{ use crate::{
@ -42,7 +42,7 @@ use crate::{
/// # let mut bpf = aya::Bpf::load(&[])?; /// # let mut bpf = aya::Bpf::load(&[])?;
/// use std::io::Write; /// use std::io::Write;
/// use std::net::TcpStream; /// use std::net::TcpStream;
/// use std::os::unix::io::AsRawFd; /// use std::os::fd::AsRawFd;
/// use aya::maps::SockHash; /// use aya::maps::SockHash;
/// use aya::programs::SkMsg; /// use aya::programs::SkMsg;
/// ///

@ -354,7 +354,7 @@ pub enum LinkError {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use assert_matches::assert_matches; use assert_matches::assert_matches;
use std::{cell::RefCell, fs::File, mem, os::unix::io::AsRawFd, rc::Rc}; use std::{cell::RefCell, fs::File, mem, os::fd::AsRawFd, rc::Rc};
use tempfile::tempdir; use tempfile::tempdir;
use crate::{programs::ProgramError, sys::override_syscall}; use crate::{programs::ProgramError, sys::override_syscall};

@ -69,8 +69,9 @@ use libc::ENOSPC;
use std::{ use std::{
ffi::CString, ffi::CString,
io, io,
os::fd::{AsRawFd, IntoRawFd as _, RawFd}, os::fd::{AsFd, AsRawFd, IntoRawFd as _, OwnedFd, RawFd},
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::Arc,
}; };
use thiserror::Error; use thiserror::Error;
@ -413,7 +414,7 @@ pub(crate) struct ProgramData<T: Link> {
pub(crate) attach_btf_obj_fd: Option<u32>, pub(crate) attach_btf_obj_fd: Option<u32>,
pub(crate) attach_btf_id: Option<u32>, pub(crate) attach_btf_id: Option<u32>,
pub(crate) attach_prog_fd: Option<RawFd>, pub(crate) attach_prog_fd: Option<RawFd>,
pub(crate) btf_fd: Option<RawFd>, pub(crate) btf_fd: Option<Arc<OwnedFd>>,
pub(crate) verifier_log_level: VerifierLogLevel, pub(crate) verifier_log_level: VerifierLogLevel,
pub(crate) path: Option<PathBuf>, pub(crate) path: Option<PathBuf>,
pub(crate) flags: u32, pub(crate) flags: u32,
@ -423,7 +424,7 @@ impl<T: Link> ProgramData<T> {
pub(crate) fn new( pub(crate) fn new(
name: Option<String>, name: Option<String>,
obj: (obj::Program, obj::Function), obj: (obj::Program, obj::Function),
btf_fd: Option<RawFd>, btf_fd: Option<Arc<OwnedFd>>,
verifier_log_level: VerifierLogLevel, verifier_log_level: VerifierLogLevel,
) -> ProgramData<T> { ) -> ProgramData<T> {
ProgramData { ProgramData {
@ -613,7 +614,7 @@ fn load_program<T: Link>(
license, license,
kernel_version: target_kernel_version, kernel_version: target_kernel_version,
expected_attach_type: *expected_attach_type, expected_attach_type: *expected_attach_type,
prog_btf_fd: *btf_fd, prog_btf_fd: btf_fd.as_ref().map(|f| f.as_fd()),
attach_btf_obj_fd: *attach_btf_obj_fd, attach_btf_obj_fd: *attach_btf_obj_fd,
attach_btf_id: *attach_btf_id, attach_btf_id: *attach_btf_id,
attach_prog_fd: *attach_prog_fd, attach_prog_fd: *attach_prog_fd,

@ -1,6 +1,6 @@
//! Perf attach links. //! Perf attach links.
use libc::close; use libc::close;
use std::os::unix::io::RawFd; use std::os::fd::RawFd;
use crate::{ use crate::{
generated::bpf_attach_type::BPF_PERF_EVENT, generated::bpf_attach_type::BPF_PERF_EVENT,

@ -1,6 +1,6 @@
//! Skmsg programs. //! Skmsg programs.
use std::os::unix::io::AsRawFd; use std::os::fd::AsRawFd;
use crate::{ use crate::{
generated::{bpf_attach_type::BPF_SK_MSG_VERDICT, bpf_prog_type::BPF_PROG_TYPE_SK_MSG}, generated::{bpf_attach_type::BPF_SK_MSG_VERDICT, bpf_prog_type::BPF_PROG_TYPE_SK_MSG},
@ -39,7 +39,7 @@ use crate::{
/// # let mut bpf = aya::Bpf::load(&[])?; /// # let mut bpf = aya::Bpf::load(&[])?;
/// use std::io::Write; /// use std::io::Write;
/// use std::net::TcpStream; /// use std::net::TcpStream;
/// use std::os::unix::io::AsRawFd; /// use std::os::fd::AsRawFd;
/// use aya::maps::SockHash; /// use aya::maps::SockHash;
/// use aya::programs::SkMsg; /// use aya::programs::SkMsg;
/// ///

@ -1,6 +1,6 @@
//! Skskb programs. //! Skskb programs.
use std::{os::unix::io::AsRawFd, path::Path}; use std::{os::fd::AsRawFd, path::Path};
use crate::{ use crate::{
generated::{ generated::{

@ -1,5 +1,5 @@
//! Socket option programs. //! Socket option programs.
use std::os::unix::io::AsRawFd; use std::os::fd::AsRawFd;
use crate::{ use crate::{
generated::{bpf_attach_type::BPF_CGROUP_SOCK_OPS, bpf_prog_type::BPF_PROG_TYPE_SOCK_OPS}, generated::{bpf_attach_type::BPF_CGROUP_SOCK_OPS, bpf_prog_type::BPF_PROG_TYPE_SOCK_OPS},

@ -48,7 +48,7 @@ pub enum SocketFilterError {
/// # } /// # }
/// # let mut bpf = aya::Bpf::load(&[])?; /// # let mut bpf = aya::Bpf::load(&[])?;
/// use std::net::TcpStream; /// use std::net::TcpStream;
/// use std::os::unix::io::AsRawFd; /// use std::os::fd::AsRawFd;
/// use aya::programs::SocketFilter; /// use aya::programs::SocketFilter;
/// ///
/// let mut client = TcpStream::connect("127.0.0.1:1234")?; /// let mut client = TcpStream::connect("127.0.0.1:1234")?;

@ -1,5 +1,5 @@
//! Common functions shared between multiple eBPF program types. //! 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::RawFd, path::Path};
use crate::{ use crate::{
programs::{FdLink, Link, ProgramData, ProgramError}, programs::{FdLink, Link, ProgramData, ProgramError},

@ -3,7 +3,7 @@
use crate::util::KernelVersion; use crate::util::KernelVersion;
use bitflags; use bitflags;
use libc::if_nametoindex; 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, mem, os::fd::RawFd};
use thiserror::Error; use thiserror::Error;
use crate::{ use crate::{

@ -3,7 +3,7 @@ use std::{
ffi::{CStr, CString}, ffi::{CStr, CString},
io, io,
mem::{self, MaybeUninit}, mem::{self, MaybeUninit},
os::fd::{FromRawFd as _, OwnedFd, RawFd}, os::fd::{AsRawFd, BorrowedFd, FromRawFd as _, OwnedFd, RawFd},
slice, slice,
}; };
@ -35,9 +35,9 @@ use crate::{
pub(crate) fn bpf_create_map( pub(crate) fn bpf_create_map(
name: &CStr, name: &CStr,
def: &obj::Map, def: &obj::Map,
btf_fd: Option<RawFd>, btf_fd: Option<BorrowedFd<'_>>,
kernel_version: KernelVersion, kernel_version: KernelVersion,
) -> SysResult { ) -> SysResult<c_long> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_1 }; let u = unsafe { &mut attr.__bindgen_anon_1 };
@ -75,7 +75,7 @@ pub(crate) fn bpf_create_map(
_ => { _ => {
u.btf_key_type_id = m.def.btf_key_type_id; u.btf_key_type_id = m.def.btf_key_type_id;
u.btf_value_type_id = m.def.btf_value_type_id; u.btf_value_type_id = m.def.btf_value_type_id;
u.btf_fd = btf_fd.unwrap_or_default() as u32; u.btf_fd = btf_fd.map(|fd| fd.as_raw_fd()).unwrap_or_default() as u32;
} }
} }
} }
@ -93,7 +93,7 @@ pub(crate) fn bpf_create_map(
sys_bpf(bpf_cmd::BPF_MAP_CREATE, &attr) sys_bpf(bpf_cmd::BPF_MAP_CREATE, &attr)
} }
pub(crate) fn bpf_pin_object(fd: RawFd, path: &CStr) -> SysResult { pub(crate) fn bpf_pin_object(fd: RawFd, path: &CStr) -> SysResult<c_long> {
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 u32; u.bpf_fd = fd as u32;
@ -101,7 +101,7 @@ pub(crate) fn bpf_pin_object(fd: RawFd, path: &CStr) -> SysResult {
sys_bpf(bpf_cmd::BPF_OBJ_PIN, &attr) 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) -> SysResult<c_long> {
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.pathname = path.as_ptr() as u64; u.pathname = path.as_ptr() as u64;
@ -115,7 +115,7 @@ pub(crate) struct BpfLoadProgramAttrs<'a> {
pub(crate) license: &'a CStr, pub(crate) license: &'a CStr,
pub(crate) kernel_version: u32, pub(crate) kernel_version: u32,
pub(crate) expected_attach_type: Option<bpf_attach_type>, pub(crate) expected_attach_type: Option<bpf_attach_type>,
pub(crate) prog_btf_fd: Option<RawFd>, pub(crate) prog_btf_fd: Option<BorrowedFd<'a>>,
pub(crate) attach_btf_obj_fd: Option<u32>, pub(crate) attach_btf_obj_fd: Option<u32>,
pub(crate) attach_btf_id: Option<u32>, pub(crate) attach_btf_id: Option<u32>,
pub(crate) attach_prog_fd: Option<RawFd>, pub(crate) attach_prog_fd: Option<RawFd>,
@ -130,7 +130,7 @@ pub(crate) fn bpf_load_program(
aya_attr: &BpfLoadProgramAttrs, aya_attr: &BpfLoadProgramAttrs,
log_buf: &mut [u8], log_buf: &mut [u8],
verifier_log_level: VerifierLogLevel, verifier_log_level: VerifierLogLevel,
) -> SysResult { ) -> SysResult<c_long> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_3 }; let u = unsafe { &mut attr.__bindgen_anon_3 };
@ -161,7 +161,7 @@ pub(crate) fn bpf_load_program(
let func_info_buf = aya_attr.func_info.func_info_bytes(); let func_info_buf = aya_attr.func_info.func_info_bytes();
if let Some(btf_fd) = aya_attr.prog_btf_fd { if let Some(btf_fd) = aya_attr.prog_btf_fd {
u.prog_btf_fd = btf_fd as u32; u.prog_btf_fd = btf_fd.as_raw_fd() as u32;
if aya_attr.line_info_rec_size > 0 { if aya_attr.line_info_rec_size > 0 {
u.line_info = line_info_buf.as_ptr() as *const _ as u64; u.line_info = line_info_buf.as_ptr() as *const _ as u64;
u.line_info_cnt = aya_attr.line_info.len() as u32; u.line_info_cnt = aya_attr.line_info.len() as u32;
@ -272,7 +272,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 { ) -> SysResult<c_long> {
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 };
@ -286,7 +286,7 @@ pub(crate) fn bpf_map_update_elem<K: Pod, V: Pod>(
sys_bpf(bpf_cmd::BPF_MAP_UPDATE_ELEM, &attr) sys_bpf(bpf_cmd::BPF_MAP_UPDATE_ELEM, &attr)
} }
pub(crate) fn bpf_map_push_elem<V: Pod>(fd: RawFd, value: &V, flags: u64) -> SysResult { pub(crate) fn bpf_map_push_elem<V: Pod>(fd: RawFd, value: &V, flags: u64) -> SysResult<c_long> {
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 };
@ -302,7 +302,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 { ) -> SysResult<c_long> {
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 };
@ -319,12 +319,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 { ) -> SysResult<c_long> {
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: RawFd, key: &K) -> SysResult { pub(crate) fn bpf_map_delete_elem<K: Pod>(fd: RawFd, key: &K) -> SysResult<c_long> {
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 };
@ -356,7 +356,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: RawFd) -> SysResult { pub(crate) fn bpf_map_freeze(fd: RawFd) -> SysResult<c_long> {
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 u32; u.map_fd = fd as u32;
@ -370,7 +370,7 @@ pub(crate) fn bpf_link_create(
attach_type: bpf_attach_type, attach_type: bpf_attach_type,
btf_id: Option<u32>, btf_id: Option<u32>,
flags: u32, flags: u32,
) -> SysResult { ) -> SysResult<c_long> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.link_create.__bindgen_anon_1.prog_fd = prog_fd as u32; attr.link_create.__bindgen_anon_1.prog_fd = prog_fd as u32;
@ -390,7 +390,7 @@ pub(crate) fn bpf_link_update(
new_prog_fd: RawFd, new_prog_fd: RawFd,
old_prog_fd: Option<RawFd>, old_prog_fd: Option<RawFd>,
flags: u32, flags: u32,
) -> SysResult { ) -> SysResult<c_long> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.link_update.link_fd = link_fd as u32; attr.link_update.link_fd = link_fd as u32;
@ -409,7 +409,7 @@ pub(crate) fn bpf_prog_attach(
prog_fd: RawFd, prog_fd: RawFd,
target_fd: RawFd, target_fd: RawFd,
attach_type: bpf_attach_type, attach_type: bpf_attach_type,
) -> SysResult { ) -> SysResult<c_long> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.__bindgen_anon_5.attach_bpf_fd = prog_fd as u32; attr.__bindgen_anon_5.attach_bpf_fd = prog_fd as u32;
@ -423,7 +423,7 @@ pub(crate) fn bpf_prog_detach(
prog_fd: RawFd, prog_fd: RawFd,
map_fd: RawFd, map_fd: RawFd,
attach_type: bpf_attach_type, attach_type: bpf_attach_type,
) -> SysResult { ) -> SysResult<c_long> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.__bindgen_anon_5.attach_bpf_fd = prog_fd as u32; attr.__bindgen_anon_5.attach_bpf_fd = prog_fd as u32;
@ -440,7 +440,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 { ) -> SysResult<c_long> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.query.target_fd = target_fd as u32; attr.query.target_fd = target_fd as u32;
@ -464,21 +464,8 @@ pub(crate) fn bpf_prog_get_fd_by_id(prog_id: u32) -> Result<OwnedFd, io::Error>
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.__bindgen_anon_6.__bindgen_anon_1.prog_id = prog_id; attr.__bindgen_anon_6.__bindgen_anon_1.prog_id = prog_id;
// SAFETY: BPF_PROG_GET_FD_BY_ID returns a new file descriptor.
match sys_bpf(bpf_cmd::BPF_PROG_GET_FD_BY_ID, &attr) { unsafe { fd_sys_bpf(bpf_cmd::BPF_PROG_GET_FD_BY_ID, &attr).map_err(|(_, e)| e) }
Ok(v) => {
let v = v.try_into().map_err(|_err| {
// _err is std::num::TryFromIntError or std::convert::Infallible depending on
// target, so we can't ascribe.
io::Error::new(
io::ErrorKind::InvalidData,
format!("bpf_prog_get_fd_by_id: invalid fd returned: {}", v),
)
})?;
Ok(unsafe { OwnedFd::from_raw_fd(v) })
}
Err((_, err)) => Err(err),
}
} }
pub(crate) fn bpf_prog_get_info_by_fd(prog_fd: RawFd) -> Result<bpf_prog_info, io::Error> { pub(crate) fn bpf_prog_get_info_by_fd(prog_fd: RawFd) -> Result<bpf_prog_info, io::Error> {
@ -545,7 +532,7 @@ pub(crate) fn btf_obj_get_info_by_fd(
} }
} }
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) -> SysResult<c_long> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.raw_tracepoint.name = match name { attr.raw_tracepoint.name = match name {
@ -561,7 +548,7 @@ pub(crate) fn bpf_load_btf(
raw_btf: &[u8], raw_btf: &[u8],
log_buf: &mut [u8], log_buf: &mut [u8],
verifier_log_level: VerifierLogLevel, verifier_log_level: VerifierLogLevel,
) -> SysResult { ) -> SysResult<OwnedFd> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_7 }; let u = unsafe { &mut attr.__bindgen_anon_7 };
u.btf = raw_btf.as_ptr() as *const _ as u64; u.btf = raw_btf.as_ptr() as *const _ as u64;
@ -571,7 +558,23 @@ pub(crate) fn bpf_load_btf(
u.btf_log_buf = log_buf.as_mut_ptr() as u64; u.btf_log_buf = log_buf.as_mut_ptr() as u64;
u.btf_log_size = log_buf.len() as u32; u.btf_log_size = log_buf.len() as u32;
} }
sys_bpf(bpf_cmd::BPF_BTF_LOAD, &attr) // SAFETY: `BPF_BTF_LOAD` returns a newly created fd.
unsafe { fd_sys_bpf(bpf_cmd::BPF_BTF_LOAD, &attr) }
}
// SAFETY: only use for bpf_cmd that return a new file descriptor on success.
unsafe fn fd_sys_bpf(cmd: bpf_cmd, attr: &bpf_attr) -> SysResult<OwnedFd> {
let fd = sys_bpf(cmd, attr)?;
let fd = fd.try_into().map_err(|_| {
(
fd,
io::Error::new(
io::ErrorKind::InvalidData,
format!("{cmd:?}: invalid fd returned: {fd}"),
),
)
})?;
Ok(OwnedFd::from_raw_fd(fd))
} }
pub(crate) fn bpf_btf_get_fd_by_id(id: u32) -> Result<RawFd, io::Error> { pub(crate) fn bpf_btf_get_fd_by_id(id: u32) -> Result<RawFd, io::Error> {
@ -987,7 +990,7 @@ pub(crate) fn is_btf_type_tag_supported() -> bool {
} }
} }
pub fn sys_bpf(cmd: bpf_cmd, attr: &bpf_attr) -> SysResult { pub fn sys_bpf(cmd: bpf_cmd, attr: &bpf_attr) -> SysResult<c_long> {
syscall(Syscall::Bpf { cmd, attr }) syscall(Syscall::Bpf { cmd, attr })
} }
@ -1002,10 +1005,10 @@ pub(crate) fn bpf_prog_get_next_id(id: u32) -> Result<Option<u32>, (c_long, io::
} }
} }
pub(crate) fn retry_with_verifier_logs( pub(crate) fn retry_with_verifier_logs<T>(
max_retries: usize, max_retries: usize,
f: impl Fn(&mut [u8]) -> SysResult, f: impl Fn(&mut [u8]) -> SysResult<T>,
) -> (SysResult, String) { ) -> (SysResult<T>, String) {
const MIN_LOG_BUF_SIZE: usize = 1024 * 10; const MIN_LOG_BUF_SIZE: usize = 1024 * 10;
const MAX_LOG_BUF_SIZE: usize = (std::u32::MAX >> 8) as usize; const MAX_LOG_BUF_SIZE: usize = (std::u32::MAX >> 8) as usize;

@ -1,10 +1,10 @@
use std::{cell::RefCell, io, ptr}; use std::{cell::RefCell, ffi::c_long, io, ptr};
use libc::c_void; use libc::c_void;
use super::{SysResult, Syscall}; use super::{SysResult, Syscall};
type SyscallFn = unsafe fn(Syscall) -> SysResult; type SyscallFn = unsafe fn(Syscall) -> SysResult<c_long>;
#[cfg(test)] #[cfg(test)]
thread_local! { thread_local! {
@ -13,11 +13,11 @@ thread_local! {
} }
#[cfg(test)] #[cfg(test)]
unsafe fn test_syscall(_call: Syscall) -> SysResult { unsafe fn test_syscall(_call: Syscall) -> SysResult<c_long> {
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) { pub(crate) fn override_syscall(call: unsafe fn(Syscall) -> SysResult<c_long>) {
TEST_SYSCALL.with(|test_impl| *test_impl.borrow_mut() = call); TEST_SYSCALL.with(|test_impl| *test_impl.borrow_mut() = call);
} }

@ -17,7 +17,7 @@ pub(crate) use perf_event::*;
use crate::generated::{bpf_attr, bpf_cmd, perf_event_attr}; use crate::generated::{bpf_attr, bpf_cmd, perf_event_attr};
pub(crate) type SysResult = Result<c_long, (c_long, io::Error)>; pub(crate) type SysResult<T> = Result<T, (c_long, io::Error)>;
pub(crate) enum Syscall<'a> { pub(crate) enum Syscall<'a> {
Bpf { Bpf {
@ -38,7 +38,7 @@ pub(crate) enum Syscall<'a> {
}, },
} }
fn syscall(call: Syscall) -> SysResult { fn syscall(call: Syscall) -> SysResult<c_long> {
#[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) });

@ -1,4 +1,4 @@
use std::{collections::HashMap, ffi::CStr, io, mem, os::unix::io::RawFd, ptr, slice}; use std::{collections::HashMap, ffi::CStr, io, mem, os::fd::RawFd, ptr, slice};
use thiserror::Error; use thiserror::Error;
use libc::{ use libc::{

@ -1,4 +1,7 @@
use std::{ffi::CString, mem}; use std::{
ffi::{c_long, CString},
mem,
};
use libc::{c_int, pid_t}; use libc::{c_int, pid_t};
@ -22,7 +25,7 @@ pub(crate) fn perf_event_open(
sample_frequency: Option<u64>, sample_frequency: Option<u64>,
wakeup: bool, wakeup: bool,
flags: u32, flags: u32,
) -> SysResult { ) -> SysResult<c_long> {
let mut attr = unsafe { mem::zeroed::<perf_event_attr>() }; let mut attr = unsafe { mem::zeroed::<perf_event_attr>() };
attr.config = config; attr.config = config;
@ -48,7 +51,7 @@ pub(crate) fn perf_event_open(
}) })
} }
pub(crate) fn perf_event_open_bpf(cpu: c_int) -> SysResult { pub(crate) fn perf_event_open_bpf(cpu: c_int) -> SysResult<c_long> {
perf_event_open( perf_event_open(
PERF_TYPE_SOFTWARE as u32, PERF_TYPE_SOFTWARE as u32,
PERF_COUNT_SW_BPF_OUTPUT as u64, PERF_COUNT_SW_BPF_OUTPUT as u64,
@ -67,7 +70,7 @@ pub(crate) fn perf_event_open_probe(
name: &str, name: &str,
offset: u64, offset: u64,
pid: Option<pid_t>, pid: Option<pid_t>,
) -> SysResult { ) -> SysResult<c_long> {
let mut attr = unsafe { mem::zeroed::<perf_event_attr>() }; let mut attr = unsafe { mem::zeroed::<perf_event_attr>() };
if let Some(ret_bit) = ret_bit { if let Some(ret_bit) = ret_bit {
@ -93,7 +96,7 @@ pub(crate) fn perf_event_open_probe(
}) })
} }
pub(crate) fn perf_event_open_trace_point(id: u32, pid: Option<pid_t>) -> SysResult { pub(crate) fn perf_event_open_trace_point(id: u32, pid: Option<pid_t>) -> SysResult<c_long> {
let mut attr = unsafe { mem::zeroed::<perf_event_attr>() }; let mut attr = unsafe { mem::zeroed::<perf_event_attr>() };
attr.size = mem::size_of::<perf_event_attr>() as u32; attr.size = mem::size_of::<perf_event_attr>() as u32;
@ -112,7 +115,7 @@ pub(crate) fn perf_event_open_trace_point(id: u32, pid: Option<pid_t>) -> SysRes
}) })
} }
pub(crate) fn perf_event_ioctl(fd: c_int, request: c_int, arg: c_int) -> SysResult { pub(crate) fn perf_event_ioctl(fd: c_int, 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);

Loading…
Cancel
Save