diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 0c9d1d51..cff5fe99 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -13,7 +13,7 @@ use aya_obj::{ relocation::BpfRelocationError, BpfSectionKind, Features, }; -use log::debug; +use log::{debug, warn}; use thiserror::Error; use crate::{ @@ -129,6 +129,7 @@ pub struct BpfLoader<'a> { max_entries: HashMap<&'a str, u32>, extensions: HashSet<&'a str>, verifier_log_level: VerifierLogLevel, + allow_unsupported_maps: bool, } bitflags! { @@ -162,6 +163,7 @@ impl<'a> BpfLoader<'a> { max_entries: HashMap::new(), extensions: HashSet::new(), verifier_log_level: VerifierLogLevel::default(), + allow_unsupported_maps: false, } } @@ -187,6 +189,30 @@ impl<'a> BpfLoader<'a> { self } + /// Allows programs containing unsupported maps to be loaded. + /// + /// By default programs containing unsupported maps will fail to load. This + /// method can be used to configure the loader so that unsupported maps will + /// be loaded, but won't be accessible from userspace. Can be useful when + /// using unsupported maps that are only accessed from eBPF code and don't + /// require any userspace interaction. + /// + /// # Example + /// + /// ```no_run + /// use aya::BpfLoader; + /// + /// let bpf = BpfLoader::new() + /// .allow_unsupported_maps() + /// .load_file("file.o")?; + /// # Ok::<(), aya::BpfError>(()) + /// ``` + /// + pub fn allow_unsupported_maps(&mut self) -> &mut BpfLoader<'a> { + self.allow_unsupported_maps = true; + self + } + /// Sets the base directory path for pinned maps. /// /// Pinned maps will be loaded from `path/MAP_NAME`. @@ -616,12 +642,21 @@ impl<'a> BpfLoader<'a> { (name, program) }) .collect(); - let maps: Result, BpfError> = maps.drain().map(parse_map).collect(); + let maps = maps + .drain() + .map(parse_map) + .collect::, BpfError>>()?; + + if !self.allow_unsupported_maps { + maps.iter().try_for_each(|(_, x)| match x { + Map::Unsupported(map) => Err(BpfError::MapError(MapError::Unsupported { + map_type: map.obj.map_type(), + })), + _ => Ok(()), + })?; + }; - Ok(Bpf { - maps: maps?, - programs, - }) + Ok(Bpf { maps, programs }) } } @@ -633,25 +668,26 @@ fn parse_map(data: (String, MapData)) -> Result<(String, Map), BpfError> { map_type: e.map_type, })?; let map = match map_type { - BPF_MAP_TYPE_ARRAY => Ok(Map::Array(map)), - BPF_MAP_TYPE_PERCPU_ARRAY => Ok(Map::PerCpuArray(map)), - BPF_MAP_TYPE_PROG_ARRAY => Ok(Map::ProgramArray(map)), - BPF_MAP_TYPE_HASH => Ok(Map::HashMap(map)), - BPF_MAP_TYPE_LRU_HASH => Ok(Map::LruHashMap(map)), - BPF_MAP_TYPE_PERCPU_HASH => Ok(Map::PerCpuHashMap(map)), - BPF_MAP_TYPE_LRU_PERCPU_HASH => Ok(Map::PerCpuLruHashMap(map)), - BPF_MAP_TYPE_PERF_EVENT_ARRAY => Ok(Map::PerfEventArray(map)), - BPF_MAP_TYPE_SOCKHASH => Ok(Map::SockHash(map)), - BPF_MAP_TYPE_SOCKMAP => Ok(Map::SockMap(map)), - BPF_MAP_TYPE_BLOOM_FILTER => Ok(Map::BloomFilter(map)), - BPF_MAP_TYPE_LPM_TRIE => Ok(Map::LpmTrie(map)), - BPF_MAP_TYPE_STACK => Ok(Map::Stack(map)), - BPF_MAP_TYPE_STACK_TRACE => Ok(Map::StackTraceMap(map)), - BPF_MAP_TYPE_QUEUE => Ok(Map::Queue(map)), - m => Err(BpfError::MapError(MapError::InvalidMapType { - map_type: m as u32, - })), - }?; + BPF_MAP_TYPE_ARRAY => Map::Array(map), + BPF_MAP_TYPE_PERCPU_ARRAY => Map::PerCpuArray(map), + BPF_MAP_TYPE_PROG_ARRAY => Map::ProgramArray(map), + BPF_MAP_TYPE_HASH => Map::HashMap(map), + BPF_MAP_TYPE_LRU_HASH => Map::LruHashMap(map), + BPF_MAP_TYPE_PERCPU_HASH => Map::PerCpuHashMap(map), + BPF_MAP_TYPE_LRU_PERCPU_HASH => Map::PerCpuLruHashMap(map), + BPF_MAP_TYPE_PERF_EVENT_ARRAY => Map::PerfEventArray(map), + BPF_MAP_TYPE_SOCKHASH => Map::SockHash(map), + BPF_MAP_TYPE_SOCKMAP => Map::SockMap(map), + BPF_MAP_TYPE_BLOOM_FILTER => Map::BloomFilter(map), + BPF_MAP_TYPE_LPM_TRIE => Map::LpmTrie(map), + BPF_MAP_TYPE_STACK => Map::Stack(map), + BPF_MAP_TYPE_STACK_TRACE => Map::StackTraceMap(map), + BPF_MAP_TYPE_QUEUE => Map::Queue(map), + m => { + warn!("The map {name} is of type {:#?} which is currently unsupported in Aya, use `allow_unsupported_maps()` to load it anyways", m); + Map::Unsupported(map) + } + }; Ok((name, map)) } diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 24ac992c..dbb94e35 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -183,6 +183,13 @@ pub enum MapError { #[source] error: PinError, }, + + /// Unsupported Map type + #[error("Unsupported map type found {map_type}")] + Unsupported { + /// The map type + map_type: u32, + }, } /// A map file descriptor. @@ -262,6 +269,8 @@ pub enum Map { StackTraceMap(MapData), /// A [`Queue`] map Queue(MapData), + /// An unsupported map type + Unsupported(MapData), } impl Map { @@ -283,6 +292,7 @@ impl Map { Map::Stack(map) => map.obj.map_type(), Map::StackTraceMap(map) => map.obj.map_type(), Map::Queue(map) => map.obj.map_type(), + Map::Unsupported(map) => map.obj.map_type(), } } }