diff --git a/aya/src/features.rs b/aya/src/features.rs index 3c6f8b85..e457af4d 100644 --- a/aya/src/features.rs +++ b/aya/src/features.rs @@ -1,176 +1,182 @@ -//! A collection of ebpf feature helpers that can determine kernel capabilities. -//! -//! Basing kernel capabilities on kernel version is not sufficient since some -//! distros will backport ebpf functionality to older kernels. -//! +// //! A collection of ebpf feature helpers that can determine kernel capabilities. +// //! +// //! Basing kernel capabilities on kernel version is not sufficient since some +// //! distros will backport ebpf functionality to older kernels. +// //! -use std::mem::size_of; +// use std::mem::size_of; -use aya_obj::{generated::bpf_map_type, maps::LegacyMap, EbpfSectionKind, Map}; -use thiserror::Error; +// use aya_obj::{generated::bpf_map_type, maps::LegacyMap, EbpfSectionKind, Map}; +// use thiserror::Error; -use crate::maps::{MapData, MapError}; +// use crate::maps::{MapData, MapError}; -/// An error ocurred working with a pinned BPF object. -#[derive(Error, Debug)] -pub enum FeatureError { - /// An error ocurred making a syscall. - #[error(transparent)] - MapError(#[from] MapError), -} - -/// Result type used for the feature helpers -pub type Result = std::result::Result; - -fn probe_map_create(map_type: bpf_map_type) -> Result { - - let def = Map::Legacy(LegacyMap { - def: aya_obj::maps::bpf_map_def { - map_type: map_type as u32, - key_size: size_of::() as u32, - value_size: size_of::() as u32, - max_entries: 1, - map_flags: 0, - id: 0, - pinning: aya_obj::maps::PinningType::None, - }, - section_index: 0, - section_kind: EbpfSectionKind::Undefined, - symbol_index: None, - data: vec![], - }); - - let map = MapData::create(def, "", None); - - match map { - Ok(_) => Ok(true), - Err(e) => match e { - MapError::CreateError { name: _, code: _, ref io_error } => match io_error.kind() { - std::io::ErrorKind::InvalidInput => { - // InvalidInput is the return kind for unsupported map - Ok(false) - } - _ => Err(FeatureError::MapError(e)) - } - _ => { - Err(FeatureError::MapError(e)) - } - } - } -} +// /// An error ocurred working with a pinned BPF object. +// #[derive(Error, Debug)] +// pub enum FeatureError { +// /// An error ocurred making a syscall. +// #[error(transparent)] +// MapError(#[from] MapError), +// } -/// Returns `true` if `map_type` is supported. -/// -/// # Example -/// -/// ```no_run -/// use aya::features::is_map_type_supported; -/// -/// if is_map_type_supported(bpf_map_type::BPF_MAP_TYPE_RINGBUF)? { -/// println!("Ringbuf is supported!"); -/// } -/// ``` -pub fn is_map_type_supported(map_type: bpf_map_type) -> Result { - probe_map_create(map_type) -} +use crate::sys::is_ringbuf_supported as ringbuf_supported; -/// Returns `true` if the kernel supports `Ringbuf` (`BPF_MAP_TYPE_RINGBUF`). -/// -/// # Example -/// -/// ```no_run -/// use aya::features::is_map_type_ringbuf_supported; -/// -/// if is_map_type_ringbuf_supported()? { -/// println!("Ringbuf is supported!"); -/// } -/// ``` -pub fn is_map_type_ringbuf_supported() -> Result { - probe_map_create(bpf_map_type::BPF_MAP_TYPE_RINGBUF) +pub fn is_ringbuf_supported() -> bool { + ringbuf_supported() } -#[cfg(test)] -mod tests { - use std::os::fd::IntoRawFd; - - use aya_obj::generated::bpf_cmd; - - use crate::sys::{override_syscall, Syscall}; - - use super::*; - - #[test] - fn test_probe_map_create_success() { - override_syscall(|syscall| { - match syscall { - Syscall::Ebpf{cmd, attr} => { - assert_eq!(cmd, bpf_cmd::BPF_MAP_CREATE); - - let u = unsafe { &mut attr.__bindgen_anon_1 }; - - assert_eq!(u.map_type, bpf_map_type::BPF_MAP_TYPE_RINGBUF as u32); - assert_eq!(u.key_size, size_of::() as u32); - assert_eq!(u.value_size, size_of::() as u32); - } - _ => { - panic!(); - } - } - - let fd = std::fs::File::open("/dev/null").unwrap().into_raw_fd(); - Ok(fd as i64) - }); - - let supported = probe_map_create(bpf_map_type::BPF_MAP_TYPE_RINGBUF).unwrap(); - assert!(supported); - } - - #[test] - fn test_probe_map_create_failed() { - override_syscall(|syscall| { - match syscall { - Syscall::Ebpf{cmd, attr} => { - assert_eq!(cmd, bpf_cmd::BPF_MAP_CREATE); - - let u = unsafe { &mut attr.__bindgen_anon_1 }; - - assert_eq!(u.map_type, bpf_map_type::BPF_MAP_TYPE_RINGBUF as u32); - assert_eq!(u.key_size, size_of::() as u32); - assert_eq!(u.value_size, size_of::() as u32); - } - _ => { - panic!(); - } - } - - Err((-1, std::io::Error::from_raw_os_error(libc::EINVAL))) - }); - - let supported = probe_map_create(bpf_map_type::BPF_MAP_TYPE_RINGBUF).unwrap(); - assert!(!supported); - } - - #[test] - fn test_probe_map_create_unknown_error() { - override_syscall(|syscall| { - match syscall { - Syscall::Ebpf{cmd, attr} => { - assert_eq!(cmd, bpf_cmd::BPF_MAP_CREATE); - - let u = unsafe { &mut attr.__bindgen_anon_1 }; - - assert_eq!(u.map_type, bpf_map_type::BPF_MAP_TYPE_RINGBUF as u32); - assert_eq!(u.key_size, size_of::() as u32); - assert_eq!(u.value_size, size_of::() as u32); - } - _ => { - panic!(); - } - } - - Err((-1, std::io::Error::from_raw_os_error(libc::EPERM))) - }); - - assert!(probe_map_create(bpf_map_type::BPF_MAP_TYPE_RINGBUF).is_err()); - } -} \ No newline at end of file +// /// Result type used for the feature helpers +// pub type Result = std::result::Result; + +// fn probe_map_create(map_type: bpf_map_type) -> Result { + +// let def = Map::Legacy(LegacyMap { +// def: aya_obj::maps::bpf_map_def { +// map_type: map_type as u32, +// key_size: size_of::() as u32, +// value_size: size_of::() as u32, +// max_entries: 1, +// map_flags: 0, +// id: 0, +// pinning: aya_obj::maps::PinningType::None, +// }, +// section_index: 0, +// section_kind: EbpfSectionKind::Undefined, +// symbol_index: None, +// data: vec![], +// }); + +// let map = MapData::create(def, "", None); + +// match map { +// Ok(_) => Ok(true), +// Err(e) => match e { +// MapError::CreateError { name: _, code: _, ref io_error } => match io_error.kind() { +// std::io::ErrorKind::InvalidInput => { +// // InvalidInput is the return kind for unsupported map +// Ok(false) +// } +// _ => Err(FeatureError::MapError(e)) +// } +// _ => { +// Err(FeatureError::MapError(e)) +// } +// } +// } +// } + +// /// Returns `true` if `map_type` is supported. +// /// +// /// # Example +// /// +// /// ```no_run +// /// use aya::features::is_map_type_supported; +// /// +// /// if is_map_type_supported(bpf_map_type::BPF_MAP_TYPE_RINGBUF)? { +// /// println!("Ringbuf is supported!"); +// /// } +// /// ``` +// pub fn is_map_type_supported(map_type: bpf_map_type) -> Result { +// probe_map_create(map_type) +// } + +// /// Returns `true` if the kernel supports `Ringbuf` (`BPF_MAP_TYPE_RINGBUF`). +// /// +// /// # Example +// /// +// /// ```no_run +// /// use aya::features::is_map_type_ringbuf_supported; +// /// +// /// if is_map_type_ringbuf_supported()? { +// /// println!("Ringbuf is supported!"); +// /// } +// /// ``` +// pub fn is_map_type_ringbuf_supported() -> Result { +// probe_map_create(bpf_map_type::BPF_MAP_TYPE_RINGBUF) +// } + +// #[cfg(test)] +// mod tests { +// use std::os::fd::IntoRawFd; + +// use aya_obj::generated::bpf_cmd; + +// use crate::sys::{override_syscall, Syscall}; + +// use super::*; + +// #[test] +// fn test_probe_map_create_success() { +// override_syscall(|syscall| { +// match syscall { +// Syscall::Ebpf{cmd, attr} => { +// assert_eq!(cmd, bpf_cmd::BPF_MAP_CREATE); + +// let u = unsafe { &mut attr.__bindgen_anon_1 }; + +// assert_eq!(u.map_type, bpf_map_type::BPF_MAP_TYPE_RINGBUF as u32); +// assert_eq!(u.key_size, size_of::() as u32); +// assert_eq!(u.value_size, size_of::() as u32); +// } +// _ => { +// panic!(); +// } +// } + +// let fd = std::fs::File::open("/dev/null").unwrap().into_raw_fd(); +// Ok(fd as i64) +// }); + +// let supported = probe_map_create(bpf_map_type::BPF_MAP_TYPE_RINGBUF).unwrap(); +// assert!(supported); +// } + +// #[test] +// fn test_probe_map_create_failed() { +// override_syscall(|syscall| { +// match syscall { +// Syscall::Ebpf{cmd, attr} => { +// assert_eq!(cmd, bpf_cmd::BPF_MAP_CREATE); + +// let u = unsafe { &mut attr.__bindgen_anon_1 }; + +// assert_eq!(u.map_type, bpf_map_type::BPF_MAP_TYPE_RINGBUF as u32); +// assert_eq!(u.key_size, size_of::() as u32); +// assert_eq!(u.value_size, size_of::() as u32); +// } +// _ => { +// panic!(); +// } +// } + +// Err((-1, std::io::Error::from_raw_os_error(libc::EINVAL))) +// }); + +// let supported = probe_map_create(bpf_map_type::BPF_MAP_TYPE_RINGBUF).unwrap(); +// assert!(!supported); +// } + +// #[test] +// fn test_probe_map_create_unknown_error() { +// override_syscall(|syscall| { +// match syscall { +// Syscall::Ebpf{cmd, attr} => { +// assert_eq!(cmd, bpf_cmd::BPF_MAP_CREATE); + +// let u = unsafe { &mut attr.__bindgen_anon_1 }; + +// assert_eq!(u.map_type, bpf_map_type::BPF_MAP_TYPE_RINGBUF as u32); +// assert_eq!(u.key_size, size_of::() as u32); +// assert_eq!(u.value_size, size_of::() as u32); +// } +// _ => { +// panic!(); +// } +// } + +// Err((-1, std::io::Error::from_raw_os_error(libc::EPERM))) +// }); + +// assert!(probe_map_create(bpf_map_type::BPF_MAP_TYPE_RINGBUF).is_err()); +// } +// } \ No newline at end of file diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index 1ae1dc95..9949e94a 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -990,6 +990,36 @@ pub(crate) fn is_btf_type_tag_supported() -> bool { bpf_load_btf(btf_bytes.as_slice(), &mut [], Default::default()).is_ok() } +pub(crate) fn is_map_type_supported(map_type: bpf_map_type) -> bool { + map_create(map_type) +} + +pub(crate) fn is_ringbuf_supported() -> bool { + map_create(bpf_map_type::BPF_MAP_TYPE_RINGBUF) +} + +fn map_create(map_type: bpf_map_type ) -> bool { + let def = obj::Map::Legacy(LegacyMap { + def: aya_obj::maps::bpf_map_def { + map_type: map_type as u32, + key_size: std::mem::size_of::() as u32, + value_size: std::mem::size_of::() as u32, + max_entries: 1, + map_flags: 0, + id: 0, + pinning: aya_obj::maps::PinningType::None, + }, + section_index: 0, + section_kind: EbpfSectionKind::Undefined, + symbol_index: None, + data: vec![], + }); + + let map = MapData::create(def, "", None); + + map.is_ok() +} + fn bpf_prog_load(attr: &mut bpf_attr) -> SysResult { // SAFETY: BPF_PROG_LOAD returns a new file descriptor. unsafe { fd_sys_bpf(bpf_cmd::BPF_PROG_LOAD, attr) } @@ -1091,11 +1121,64 @@ pub(crate) fn retry_with_verifier_logs( #[cfg(test)] mod tests { + use std::os::fd::IntoRawFd; + use libc::{EBADF, EINVAL}; use super::*; use crate::sys::override_syscall; + #[test] + fn test_probe_map_create_success() { + override_syscall(|syscall| { + match syscall { + Syscall::Ebpf{cmd, attr} => { + assert_eq!(cmd, bpf_cmd::BPF_MAP_CREATE); + + let u = unsafe { &mut attr.__bindgen_anon_1 }; + + assert_eq!(u.map_type, bpf_map_type::BPF_MAP_TYPE_RINGBUF as u32); + assert_eq!(u.key_size, std::mem::size_of::() as u32); + assert_eq!(u.value_size, std::mem::size_of::() as u32); + } + _ => { + panic!(); + } + } + + let fd = std::fs::File::open("/dev/null").unwrap().into_raw_fd(); + Ok(fd as i64) + }); + + let supported = map_create(bpf_map_type::BPF_MAP_TYPE_RINGBUF); + assert!(supported); + } + + #[test] + fn test_probe_map_create_failed() { + override_syscall(|syscall| { + match syscall { + Syscall::Ebpf{cmd, attr} => { + assert_eq!(cmd, bpf_cmd::BPF_MAP_CREATE); + + let u = unsafe { &mut attr.__bindgen_anon_1 }; + + assert_eq!(u.map_type, bpf_map_type::BPF_MAP_TYPE_RINGBUF as u32); + assert_eq!(u.key_size, std::mem::size_of::() as u32); + assert_eq!(u.value_size, std::mem::size_of::() as u32); + } + _ => { + panic!(); + } + } + + Err((-1, std::io::Error::from_raw_os_error(libc::EINVAL))) + }); + + let supported = map_create(bpf_map_type::BPF_MAP_TYPE_RINGBUF); + assert!(!supported); + } + #[test] fn test_perf_link_supported() { override_syscall(|call| match call {