ソースを参照

Add Unsupported Map type

Just because aya doesn't support working with some map
types doesn't mean we should't allow them to be loaded.

Add a new `Unsupported` map type to facilitate this,

Next add a user configurable option `allow_unsupported_maps()`
which can be called against the `bpfLoader`.  Additionally
add a nice warning log message when a program is being loaded
by Aya and contains an unsupported map type.

Signed-off-by: Andrew Stoycos <astoycos@redhat.com>
Andrew Stoycos 2 年 前
コミット
b5719c5
2 ファイル変更68 行追加25 行削除
  1. 65 25
      aya/src/bpf.rs
  2. 3 0
      aya/src/maps/mod.rs

+ 65 - 25
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::{
@@ -123,6 +123,7 @@ pub struct BpfLoader<'a> {
     max_entries: HashMap<&'a str, u32>,
     extensions: HashSet<&'a str>,
     verifier_log_level: VerifierLogLevel,
+    allow_unsupported_maps: bool,
 }
 
 bitflags! {
@@ -156,6 +157,7 @@ impl<'a> BpfLoader<'a> {
             max_entries: HashMap::new(),
             extensions: HashSet::new(),
             verifier_log_level: VerifierLogLevel::default(),
+            allow_unsupported_maps: false,
         }
     }
 
@@ -181,6 +183,29 @@ impl<'a> BpfLoader<'a> {
         self
     }
 
+    /// Allows bytecode containing maps unsupported by Aya to be loaded.
+    ///
+    /// By default, programs containing maps unsupported by Aya will not be loaded.
+    /// This function changes the default behavior, allowing programs to be loaded.
+    /// This should only be used in cases where you do not require access to eBPF
+    /// maps from this crate.
+    ///
+    /// # 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`.
@@ -599,12 +624,22 @@ impl<'a> BpfLoader<'a> {
                 (name, program)
             })
             .collect();
-        let maps: Result<HashMap<String, Map>, BpfError> = maps.drain().map(parse_map).collect();
+        let maps = maps
+            .drain()
+            .map(parse_map)
+            .collect::<Result<HashMap<String, Map>, BpfError>>()?;
+
+        if !self.allow_unsupported_maps
+            && maps
+                .iter()
+                .filter(|(_, x)| matches!(x, Map::Unsupported(_)))
+                .count()
+                != 0
+        {
+            return Err(BpfError::UnsupportedMap);
+        }
 
-        Ok(Bpf {
-            maps: maps?,
-            programs,
-        })
+        Ok(Bpf { maps, programs })
     }
 }
 
@@ -616,25 +651,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))
 }
@@ -895,6 +931,10 @@ pub enum BpfError {
     #[error("program error: {0}")]
     /// A program error
     ProgramError(#[from] ProgramError),
+
+    /// Unsupported Map type
+    #[error("Unsupported map types found")]
+    UnsupportedMap,
 }
 
 fn load_btf(raw_btf: Vec<u8>) -> Result<RawFd, BtfError> {

+ 3 - 0
aya/src/maps/mod.rs

@@ -261,6 +261,8 @@ pub enum Map {
     StackTraceMap(MapData),
     /// A [`Queue`] map
     Queue(MapData),
+    /// An unsupported map type
+    Unsupported(MapData),
 }
 
 impl Map {
@@ -282,6 +284,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(),
         }
     }
 }