From 74f5acf419ba3395117a0fb67e893d44fdbe8d34 Mon Sep 17 00:00:00 2001 From: martinsoees Date: Thu, 13 Jun 2024 06:30:30 -0400 Subject: [PATCH 01/18] Ignore relocation of maps that should be ignored. This makes it possible to have bytecode with unsupported map types such as BPF_MAP_TYPE_RINGBUF on a target kernel that doesn't have that map type --- aya-obj/src/btf/btf.rs | 14 ++++++++++++++ aya-obj/src/obj.rs | 1 + aya-obj/src/relocation.rs | 32 +++++++++++++++++++++++++++++++- aya/src/bpf.rs | 34 +++++++++++++++++++++++++--------- 4 files changed, 71 insertions(+), 10 deletions(-) diff --git a/aya-obj/src/btf/btf.rs b/aya-obj/src/btf/btf.rs index ef7217ad4..52b04daae 100644 --- a/aya-obj/src/btf/btf.rs +++ b/aya-obj/src/btf/btf.rs @@ -416,6 +416,20 @@ impl Btf { self.string_at(ty.name_offset()).ok().map(String::from) } + /// Returns a type id matching the type name + pub fn id_by_type_name(&self, name: &str) -> Result { + for (type_id, ty) in self.types().enumerate() { + if self.type_name(ty)? == name { + return Ok(type_id as u32); + } + continue; + } + + Err(BtfError::UnknownBtfTypeName { + type_name: name.to_owned(), + }) + } + /// Returns a type id matching the type name and [BtfKind] pub fn id_by_type_name_kind(&self, name: &str, kind: BtfKind) -> Result { for (type_id, ty) in self.types().enumerate() { diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index f6f4fc8b5..50cb9feda 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -8,6 +8,7 @@ use alloc::{ vec::Vec, }; use core::{ffi::CStr, mem, ptr, slice::from_raw_parts_mut, str::FromStr}; +use std::println; use log::debug; use object::{ diff --git a/aya-obj/src/relocation.rs b/aya-obj/src/relocation.rs index b05648ba4..46639bab1 100644 --- a/aya-obj/src/relocation.rs +++ b/aya-obj/src/relocation.rs @@ -2,6 +2,7 @@ use alloc::{borrow::ToOwned, collections::BTreeMap, string::String}; use core::mem; +use std::println; use log::debug; use object::{SectionIndex, SymbolKind}; @@ -108,9 +109,20 @@ impl Object { &mut self, maps: I, text_sections: &HashSet, + ignored_maps: &HashMap, ) -> Result<(), EbpfRelocationError> { let mut maps_by_section = HashMap::new(); let mut maps_by_symbol = HashMap::new(); + let mut ignored_by_section = HashSet::new(); + let mut ignored_by_symbol = HashSet::new(); + + for (name, map) in ignored_maps { + ignored_by_section.insert(map.section_index()); + if let Some(index) = map.symbol_index() { + ignored_by_symbol.insert(index); + } + } + for (name, fd, map) in maps { maps_by_section.insert(map.section_index(), (name, fd, map)); if let Some(index) = map.symbol_index() { @@ -127,6 +139,8 @@ impl Object { &maps_by_symbol, &self.symbol_table, text_sections, + &ignored_by_section, + &ignored_by_symbol, ) .map_err(|error| EbpfRelocationError { function: function.name.clone(), @@ -176,6 +190,7 @@ impl Object { } } +#[allow(clippy::too_many_arguments)] fn relocate_maps<'a, I: Iterator>( fun: &mut Function, relocations: I, @@ -183,6 +198,8 @@ fn relocate_maps<'a, I: Iterator>( maps_by_symbol: &HashMap, symbol_table: &HashMap, text_sections: &HashSet, + ignored_by_section: &HashSet, + ignored_by_symbol: &HashSet, ) -> Result<(), RelocationError> { let section_offset = fun.section_offset; let instructions = &mut fun.instructions; @@ -212,6 +229,7 @@ fn relocate_maps<'a, I: Iterator>( index: rel.symbol_index, })?; + let Some(section_index) = sym.section_index else { // this is not a map relocation continue; @@ -222,7 +240,9 @@ fn relocate_maps<'a, I: Iterator>( continue; } - let (_name, fd, map) = if let Some(m) = maps_by_symbol.get(&rel.symbol_index) { + let (_name, fd, map) = if ignored_by_symbol.contains(&rel.symbol_index) { + continue + } else if let Some(m) = maps_by_symbol.get(&rel.symbol_index) { let map = &m.2; debug!( "relocating map by symbol index {:?}, kind {:?} at insn {ins_index} in section {}", @@ -232,6 +252,8 @@ fn relocate_maps<'a, I: Iterator>( ); debug_assert_eq!(map.symbol_index().unwrap(), rel.symbol_index); m + } else if ignored_by_section.contains(§ion_index) { + continue } else { let Some(m) = maps_by_section.get(§ion_index) else { debug!("failed relocating map by section index {}", section_index); @@ -580,6 +602,8 @@ mod test { &maps_by_symbol, &symbol_table, &HashSet::new(), + &HashSet::new(), + &HashSet::new(), ) .unwrap(); @@ -636,6 +660,8 @@ mod test { &maps_by_symbol, &symbol_table, &HashSet::new(), + &HashSet::new(), + &HashSet::new(), ) .unwrap(); @@ -675,6 +701,8 @@ mod test { &maps_by_symbol, &symbol_table, &HashSet::new(), + &HashSet::new(), + &HashSet::new(), ) .unwrap(); @@ -731,6 +759,8 @@ mod test { &maps_by_symbol, &symbol_table, &HashSet::new(), + &HashSet::new(), + &HashSet::new(), ) .unwrap(); diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 42a9a4899..977fff961 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -3,7 +3,7 @@ use std::{ collections::{HashMap, HashSet}, fs, io, os::{ - fd::{AsFd as _, AsRawFd as _, OwnedFd}, + fd::{AsFd as _, AsRawFd as _, FromRawFd, OwnedFd}, raw::c_int, }, path::{Path, PathBuf}, @@ -21,10 +21,10 @@ use thiserror::Error; use crate::{ generated::{ - bpf_map_type, bpf_map_type::*, AYA_PERF_EVENT_IOC_DISABLE, AYA_PERF_EVENT_IOC_ENABLE, + bpf_map_type::{self, *}, AYA_PERF_EVENT_IOC_DISABLE, AYA_PERF_EVENT_IOC_ENABLE, AYA_PERF_EVENT_IOC_SET_BPF, }, - maps::{Map, MapData, MapError}, + maps::{Map, MapData, MapError, MapFd}, obj::{ btf::{Btf, BtfError}, Object, ParseError, ProgramSection, @@ -137,6 +137,7 @@ pub struct EbpfLoader<'a> { extensions: HashSet<&'a str>, verifier_log_level: VerifierLogLevel, allow_unsupported_maps: bool, + deactivate_maps: HashSet, } /// Builder style API for advanced loading of eBPF programs. @@ -175,6 +176,7 @@ impl<'a> EbpfLoader<'a> { extensions: HashSet::new(), verifier_log_level: VerifierLogLevel::default(), allow_unsupported_maps: false, + deactivate_maps: HashSet::new(), } } @@ -224,6 +226,12 @@ impl<'a> EbpfLoader<'a> { self } + /// Documentaaaaaaaaaaaaation + pub fn deactivate_maps(&mut self, set: HashSet) -> &mut Self { + self.deactivate_maps = set; + self + } + /// Sets the base directory path for pinned maps. /// /// Pinned maps will be loaded from `path/MAP_NAME`. @@ -394,9 +402,9 @@ impl<'a> EbpfLoader<'a> { extensions, verifier_log_level, allow_unsupported_maps, + deactivate_maps, } = self; let mut obj = Object::parse(data)?; - obj.patch_map_data(globals.clone())?; let btf_fd = if let Some(features) = &FEATURES.btf() { if let Some(btf) = obj.fixup_and_sanitize_btf(features)? { @@ -459,12 +467,20 @@ impl<'a> EbpfLoader<'a> { obj.relocate_btf(btf)?; } let mut maps = HashMap::new(); + let mut ignored_maps = HashMap::new(); + for (name, mut obj) in obj.maps.drain() { if let (false, EbpfSectionKind::Bss | EbpfSectionKind::Data | EbpfSectionKind::Rodata) = (FEATURES.bpf_global_data(), obj.section_kind()) { continue; } + + if deactivate_maps.contains(&obj.map_type().try_into().map_err(|_| EbpfError::MapError(MapError::InvalidMapType { map_type: obj.map_type() }))?) { + ignored_maps.insert(name, obj); + continue; + } + let num_cpus = || -> Result { Ok(possible_cpus() .map_err(|error| EbpfError::FileError { @@ -498,17 +514,16 @@ impl<'a> EbpfLoader<'a> { PinningType::ByName => { // pin maps in /sys/fs/bpf by default to align with libbpf // behavior https://github.com/libbpf/libbpf/blob/v1.2.2/src/libbpf.c#L2161. - let path = map_pin_path - .as_deref() - .unwrap_or_else(|| Path::new("/sys/fs/bpf")); + let path: &Path = map_pin_path + .as_deref() + .unwrap_or_else(|| Path::new("/sys/fs/bpf")); - MapData::create_pinned_by_name(path, obj, &name, btf_fd)? + MapData::create_pinned_by_name(path, obj, &name, btf_fd)? } }; map.finalize()?; maps.insert(name, map); } - let text_sections = obj .functions .keys() @@ -519,6 +534,7 @@ impl<'a> EbpfLoader<'a> { maps.iter() .map(|(s, data)| (s.as_str(), data.fd().as_fd().as_raw_fd(), data.obj())), &text_sections, + &ignored_maps, )?; obj.relocate_calls(&text_sections)?; obj.sanitize_functions(&FEATURES); From 3525560c4a98cb1c8f9ced749988e7bd030fc735 Mon Sep 17 00:00:00 2001 From: martinsoees Date: Thu, 13 Jun 2024 06:50:47 -0400 Subject: [PATCH 02/18] Added documentation to --- aya/src/bpf.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 977fff961..7ded6663c 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -226,7 +226,27 @@ impl<'a> EbpfLoader<'a> { self } - /// Documentaaaaaaaaaaaaation + /// Allows programs containing unsupported maps for the current kernel to be loaded + /// by skipping map creation and relocation before loading. + /// + /// This is useful when you have a single program containing e.g. a `RingBuf` + /// and a `PerfEventArray` and you decide which one to use before loading the bytecode. + /// Can be used with `.set_global()` to signal if the map is supported. + /// + /// # Example + /// + /// ```no_run + /// use aya::EbpfLoader; + /// use aya_obj::btf::Btf::bpf_map_type; + /// + /// let mut set = HashSet::new(); + /// set.insert(bpf_map_type::BPF_MAP_TYPE_RINGBUF); + /// let ebpf = EbpfLoader::new() + /// .disable_maps(set) + /// .load_file("file.o")?; + /// # Ok::<(), aya::EbpfError>(()) + /// ``` + /// pub fn deactivate_maps(&mut self, set: HashSet) -> &mut Self { self.deactivate_maps = set; self From 5276a91846665766e775887976ba353b9fa6463e Mon Sep 17 00:00:00 2001 From: martinsoees Date: Thu, 13 Jun 2024 08:14:40 -0400 Subject: [PATCH 03/18] Remove println import, added code comments and re-added patch_map_data (removed by mistake) --- aya-obj/src/btf/btf.rs | 14 -------------- aya-obj/src/obj.rs | 1 - aya-obj/src/relocation.rs | 3 +-- aya/src/bpf.rs | 13 ++++++++----- 4 files changed, 9 insertions(+), 22 deletions(-) diff --git a/aya-obj/src/btf/btf.rs b/aya-obj/src/btf/btf.rs index 52b04daae..ef7217ad4 100644 --- a/aya-obj/src/btf/btf.rs +++ b/aya-obj/src/btf/btf.rs @@ -416,20 +416,6 @@ impl Btf { self.string_at(ty.name_offset()).ok().map(String::from) } - /// Returns a type id matching the type name - pub fn id_by_type_name(&self, name: &str) -> Result { - for (type_id, ty) in self.types().enumerate() { - if self.type_name(ty)? == name { - return Ok(type_id as u32); - } - continue; - } - - Err(BtfError::UnknownBtfTypeName { - type_name: name.to_owned(), - }) - } - /// Returns a type id matching the type name and [BtfKind] pub fn id_by_type_name_kind(&self, name: &str, kind: BtfKind) -> Result { for (type_id, ty) in self.types().enumerate() { diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index 50cb9feda..f6f4fc8b5 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -8,7 +8,6 @@ use alloc::{ vec::Vec, }; use core::{ffi::CStr, mem, ptr, slice::from_raw_parts_mut, str::FromStr}; -use std::println; use log::debug; use object::{ diff --git a/aya-obj/src/relocation.rs b/aya-obj/src/relocation.rs index 46639bab1..92d279c43 100644 --- a/aya-obj/src/relocation.rs +++ b/aya-obj/src/relocation.rs @@ -2,7 +2,6 @@ use alloc::{borrow::ToOwned, collections::BTreeMap, string::String}; use core::mem; -use std::println; use log::debug; use object::{SectionIndex, SymbolKind}; @@ -116,7 +115,7 @@ impl Object { let mut ignored_by_section = HashSet::new(); let mut ignored_by_symbol = HashSet::new(); - for (name, map) in ignored_maps { + for map in ignored_maps.values() { ignored_by_section.insert(map.section_index()); if let Some(index) = map.symbol_index() { ignored_by_symbol.insert(index); diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 7ded6663c..75e47f245 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -3,7 +3,7 @@ use std::{ collections::{HashMap, HashSet}, fs, io, os::{ - fd::{AsFd as _, AsRawFd as _, FromRawFd, OwnedFd}, + fd::{AsFd as _, AsRawFd as _, OwnedFd}, raw::c_int, }, path::{Path, PathBuf}, @@ -24,7 +24,7 @@ use crate::{ bpf_map_type::{self, *}, AYA_PERF_EVENT_IOC_DISABLE, AYA_PERF_EVENT_IOC_ENABLE, AYA_PERF_EVENT_IOC_SET_BPF, }, - maps::{Map, MapData, MapError, MapFd}, + maps::{Map, MapData, MapError}, obj::{ btf::{Btf, BtfError}, Object, ParseError, ProgramSection, @@ -237,7 +237,7 @@ impl<'a> EbpfLoader<'a> { /// /// ```no_run /// use aya::EbpfLoader; - /// use aya_obj::btf::Btf::bpf_map_type; + /// use aya_obj::generated::bpf_map_type; /// /// let mut set = HashSet::new(); /// set.insert(bpf_map_type::BPF_MAP_TYPE_RINGBUF); @@ -425,6 +425,7 @@ impl<'a> EbpfLoader<'a> { deactivate_maps, } = self; let mut obj = Object::parse(data)?; + obj.patch_map_data(globals.clone())?; let btf_fd = if let Some(features) = &FEATURES.btf() { if let Some(btf) = obj.fixup_and_sanitize_btf(features)? { @@ -495,9 +496,12 @@ impl<'a> EbpfLoader<'a> { { continue; } + let map_type: bpf_map_type = obj.map_type().try_into().map_err(MapError::from)?; - if deactivate_maps.contains(&obj.map_type().try_into().map_err(|_| EbpfError::MapError(MapError::InvalidMapType { map_type: obj.map_type() }))?) { + if deactivate_maps.contains(&map_type) { ignored_maps.insert(name, obj); + // ignore map creation. The map is saved in `ignored_maps` and filtered out + // in `relocate_maps()` later on continue; } @@ -509,7 +513,6 @@ impl<'a> EbpfLoader<'a> { })? .len() as u32) }; - let map_type: bpf_map_type = obj.map_type().try_into().map_err(MapError::from)?; if let Some(max_entries) = max_entries_override( map_type, max_entries.get(name.as_str()).copied(), From c725b9d69e9db663191171b344068ecc151db764 Mon Sep 17 00:00:00 2001 From: martinsoees Date: Thu, 13 Jun 2024 08:27:19 -0400 Subject: [PATCH 04/18] All tests are passing now --- aya-obj/src/lib.rs | 3 ++- aya/src/bpf.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/aya-obj/src/lib.rs b/aya-obj/src/lib.rs index ea0e56702..d0e276013 100644 --- a/aya-obj/src/lib.rs +++ b/aya-obj/src/lib.rs @@ -39,10 +39,11 @@ //! // Relocate the programs //! #[cfg(feature = "std")] //! let text_sections = std::collections::HashSet::new(); +//! let deactivate_maps = std::collections::HashMap::new(); //! #[cfg(not(feature = "std"))] //! let text_sections = hashbrown::HashSet::new(); //! object.relocate_calls(&text_sections).unwrap(); -//! object.relocate_maps(std::iter::empty(), &text_sections).unwrap(); +//! object.relocate_maps(std::iter::empty(), &text_sections, &deactivate_maps).unwrap(); //! //! // Run with rbpf //! let function = object.functions.get(&object.programs["prog_name"].function_key()).unwrap(); diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 75e47f245..1c5db58da 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -238,11 +238,12 @@ impl<'a> EbpfLoader<'a> { /// ```no_run /// use aya::EbpfLoader; /// use aya_obj::generated::bpf_map_type; + /// use std::collections::HashSet; /// /// let mut set = HashSet::new(); /// set.insert(bpf_map_type::BPF_MAP_TYPE_RINGBUF); /// let ebpf = EbpfLoader::new() - /// .disable_maps(set) + /// .deactivate_maps(set) /// .load_file("file.o")?; /// # Ok::<(), aya::EbpfError>(()) /// ``` From aad4ad4fd3e5c0e0b4aa313c760fbeabc8b6c92f Mon Sep 17 00:00:00 2001 From: martinsoees Date: Tue, 18 Jun 2024 06:11:02 -0400 Subject: [PATCH 05/18] Changed name to 'ignore_map_by_type' and created a similar function that does the same by name. Fixed renaming and added the new 3rd argument to relocate_maps() for rbpf test case --- aya-obj/src/lib.rs | 4 +- aya/src/bpf.rs | 50 ++++++++++++++++++++----- test/integration-test/src/tests/rbpf.rs | 2 + 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/aya-obj/src/lib.rs b/aya-obj/src/lib.rs index d0e276013..480d4f331 100644 --- a/aya-obj/src/lib.rs +++ b/aya-obj/src/lib.rs @@ -39,11 +39,11 @@ //! // Relocate the programs //! #[cfg(feature = "std")] //! let text_sections = std::collections::HashSet::new(); -//! let deactivate_maps = std::collections::HashMap::new(); +//! let ignore_maps = std::collections::HashMap::new(); //! #[cfg(not(feature = "std"))] //! let text_sections = hashbrown::HashSet::new(); //! object.relocate_calls(&text_sections).unwrap(); -//! object.relocate_maps(std::iter::empty(), &text_sections, &deactivate_maps).unwrap(); +//! object.relocate_maps(std::iter::empty(), &text_sections, &ignore_maps).unwrap(); //! //! // Run with rbpf //! let function = object.functions.get(&object.programs["prog_name"].function_key()).unwrap(); diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 1c5db58da..2b8b7017c 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -137,7 +137,8 @@ pub struct EbpfLoader<'a> { extensions: HashSet<&'a str>, verifier_log_level: VerifierLogLevel, allow_unsupported_maps: bool, - deactivate_maps: HashSet, + ignore_maps_by_type: HashSet, + ignore_maps_by_name: &'a [&'a str], } /// Builder style API for advanced loading of eBPF programs. @@ -176,7 +177,8 @@ impl<'a> EbpfLoader<'a> { extensions: HashSet::new(), verifier_log_level: VerifierLogLevel::default(), allow_unsupported_maps: false, - deactivate_maps: HashSet::new(), + ignore_maps_by_type: HashSet::new(), + ignore_maps_by_name: &[], } } @@ -229,9 +231,10 @@ impl<'a> EbpfLoader<'a> { /// Allows programs containing unsupported maps for the current kernel to be loaded /// by skipping map creation and relocation before loading. /// - /// This is useful when you have a single program containing e.g. a `RingBuf` + /// This is useful when you have a single ebpf program containing e.g. a `RingBuf` /// and a `PerfEventArray` and you decide which one to use before loading the bytecode. - /// Can be used with `.set_global()` to signal if the map is supported. + /// + /// Must be used with `.set_global()` to signal if the map is supported in the ebpf program. /// /// # Example /// @@ -240,16 +243,44 @@ impl<'a> EbpfLoader<'a> { /// use aya_obj::generated::bpf_map_type; /// use std::collections::HashSet; /// + /// let ringbuf_supported = 0; /// let mut set = HashSet::new(); /// set.insert(bpf_map_type::BPF_MAP_TYPE_RINGBUF); /// let ebpf = EbpfLoader::new() - /// .deactivate_maps(set) + /// .ignore_maps_by_type(set) + /// .set_global("RINGBUF_SUPPORTED", &ringbuf_supported, true) + /// .load_file("file.o")?; + /// # Ok::<(), aya::EbpfError>(()) + /// ``` + /// + pub fn ignore_maps_by_type(&mut self, set: HashSet) -> &mut Self { + self.ignore_maps_by_type = set; + self + } + + /// Allows programs containing unsupported maps for the current kernel to be loaded + /// by skipping map creation and relocation before loading. + /// + /// This is useful when you have a single ebpf program containing e.g. a `RingBuf` + /// and a `PerfEventArray` and you decide which one to use before loading the bytecode. + /// + /// Must be used with `.set_global()` to signal if the map is supported in the ebpf program. + /// + /// # Example + /// + /// ```no_run + /// use aya::EbpfLoader; + /// + /// let ringbuf_supported = 0; + /// let ebpf = EbpfLoader::new() + /// .ignore_maps_by_name(&["RINGBUF"]) + /// .set_global("RINGBUF_SUPPORTED", &ringbuf_supported, true) /// .load_file("file.o")?; /// # Ok::<(), aya::EbpfError>(()) /// ``` /// - pub fn deactivate_maps(&mut self, set: HashSet) -> &mut Self { - self.deactivate_maps = set; + pub fn ignore_maps_by_name(&mut self, name: &'a [&'a str]) -> &mut Self { + self.ignore_maps_by_name = name; self } @@ -423,7 +454,8 @@ impl<'a> EbpfLoader<'a> { extensions, verifier_log_level, allow_unsupported_maps, - deactivate_maps, + ignore_maps_by_type, + ignore_maps_by_name, } = self; let mut obj = Object::parse(data)?; obj.patch_map_data(globals.clone())?; @@ -499,7 +531,7 @@ impl<'a> EbpfLoader<'a> { } let map_type: bpf_map_type = obj.map_type().try_into().map_err(MapError::from)?; - if deactivate_maps.contains(&map_type) { + if ignore_maps_by_type.contains(&map_type) || ignore_maps_by_name.contains(&name.as_str()) { ignored_maps.insert(name, obj); // ignore map creation. The map is saved in `ignored_maps` and filtered out // in `relocate_maps()` later on diff --git a/test/integration-test/src/tests/rbpf.rs b/test/integration-test/src/tests/rbpf.rs index 900d1462b..b59c3dacc 100644 --- a/test/integration-test/src/tests/rbpf.rs +++ b/test/integration-test/src/tests/rbpf.rs @@ -81,11 +81,13 @@ fn use_map_with_rbpf() { .iter() .map(|((section_index, _), _)| *section_index) .collect(); + let ignored_maps = HashMap::new(); object .relocate_maps( maps.iter() .map(|(s, (fd, map))| (s.as_ref() as &str, *fd, map)), &text_sections, + &ignored_maps, ) .expect("Relocation failed"); // Actually there is no local function call involved. From b49c3001f19b396e1522fd147782f92ecca961c6 Mon Sep 17 00:00:00 2001 From: martinsoees Date: Wed, 19 Jun 2024 07:01:08 -0400 Subject: [PATCH 06/18] Added integration tests for ignoring maps by type and by name --- test/integration-ebpf/Cargo.toml | 4 ++ test/integration-ebpf/src/ignore_map.rs | 32 +++++++++ test/integration-test/src/lib.rs | 1 + test/integration-test/src/tests/rbpf.rs | 4 +- .../integration-test/src/tests/relocations.rs | 72 ++++++++++++++++++- 5 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 test/integration-ebpf/src/ignore_map.rs diff --git a/test/integration-ebpf/Cargo.toml b/test/integration-ebpf/Cargo.toml index b4146daae..ec9004025 100644 --- a/test/integration-ebpf/Cargo.toml +++ b/test/integration-ebpf/Cargo.toml @@ -59,3 +59,7 @@ path = "src/xdp_sec.rs" [[bin]] name = "ring_buf" path = "src/ring_buf.rs" + +[[bin]] +name = "ignore_map" +path = "src/ignore_map.rs" \ No newline at end of file diff --git a/test/integration-ebpf/src/ignore_map.rs b/test/integration-ebpf/src/ignore_map.rs new file mode 100644 index 000000000..4255d1c94 --- /dev/null +++ b/test/integration-ebpf/src/ignore_map.rs @@ -0,0 +1,32 @@ +#![no_std] +#![no_main] + +use aya_ebpf::{ + macros::{map, uprobe}, + maps::{PerfEventArray, RingBuf}, + programs::ProbeContext, +}; + +#[no_mangle] +pub static RINGBUF_SUPPORTED: i32 = 0; + +#[map] +static mut RINGBUF: RingBuf = RingBuf::with_byte_size(0, 0); + +#[map] +static mut PERFBUF: PerfEventArray = PerfEventArray::with_max_entries(1, 0); + +#[uprobe] +pub fn test_ignored_map_relocation(ctx: ProbeContext) { + if unsafe { core::ptr::read_volatile(&RINGBUF_SUPPORTED) == 1 } { + let _ = unsafe { RINGBUF.output(&1, 0).map_err(|_| 1u32) }; + } else { + unsafe { PERFBUF.output(&ctx, &1, 0) }; + } +} + +#[cfg(not(test))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/test/integration-test/src/lib.rs b/test/integration-test/src/lib.rs index d47080336..a66afed19 100644 --- a/test/integration-test/src/lib.rs +++ b/test/integration-test/src/lib.rs @@ -22,6 +22,7 @@ pub const BPF_PROBE_READ: &[u8] = pub const REDIRECT: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/redirect")); pub const XDP_SEC: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/xdp_sec")); pub const RING_BUF: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/ring_buf")); +pub const IGNORE_MAP: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/ignore_map")); #[cfg(test)] mod tests; diff --git a/test/integration-test/src/tests/rbpf.rs b/test/integration-test/src/tests/rbpf.rs index b59c3dacc..8a90697df 100644 --- a/test/integration-test/src/tests/rbpf.rs +++ b/test/integration-test/src/tests/rbpf.rs @@ -81,13 +81,13 @@ fn use_map_with_rbpf() { .iter() .map(|((section_index, _), _)| *section_index) .collect(); - let ignored_maps = HashMap::new(); + let disable_maps = HashMap::new(); object .relocate_maps( maps.iter() .map(|(s, (fd, map))| (s.as_ref() as &str, *fd, map)), &text_sections, - &ignored_maps, + &disable_maps, ) .expect("Relocation failed"); // Actually there is no local function call involved. diff --git a/test/integration-test/src/tests/relocations.rs b/test/integration-test/src/tests/relocations.rs index eb43466a6..734cc5bae 100644 --- a/test/integration-test/src/tests/relocations.rs +++ b/test/integration-test/src/tests/relocations.rs @@ -1,6 +1,42 @@ -use aya::{programs::UProbe, util::KernelVersion, Ebpf}; +use std::collections::HashSet; + +use aya::{programs::UProbe, util::KernelVersion, Ebpf, EbpfLoader}; +use aya_obj::generated::bpf_map_type; use test_log::test; +enum DisableMapRelocation<'a> { + ByType(bpf_map_type), + ByName(&'a str), +} + +#[test] +fn test_ignored_map_relocation_by_type() { + let mut ebpf = relocation_load_and_attach("test_ignored_map_relocation", crate::IGNORE_MAP, DisableMapRelocation::ByType(bpf_map_type::BPF_MAP_TYPE_RINGBUF)); + + let perf = ebpf + .take_map("PERFBUF"); + + let ring = ebpf + .take_map("RINGBUF"); + + assert!(perf.is_some()); + assert!(ring.is_none()); +} + +#[test] +fn test_ignored_map_relocation_by_name() { + let mut ebpf = relocation_load_and_attach("test_ignored_map_relocation", crate::IGNORE_MAP, DisableMapRelocation::ByName("RINGBUF")); + + let perf = ebpf + .take_map("PERFBUF"); + + let ring = ebpf + .take_map("RINGBUF"); + + assert!(perf.is_some()); + assert!(ring.is_none()); +} + #[test] fn relocations() { let bpf = load_and_attach("test_64_32_call_relocs", crate::RELOCATIONS); @@ -33,6 +69,40 @@ fn text_64_64_reloc() { assert_eq!(m.get(&1, 0).unwrap(), 3); } +fn relocation_load_and_attach(name: &str, bytes: &[u8], disable_type: DisableMapRelocation) -> Ebpf { + let mut ebpf = match disable_type { + DisableMapRelocation::ByType(bmt) => { + let mut set = HashSet::new(); + set.insert(bmt); + EbpfLoader::new() + .ignore_maps_by_type(set) + .set_global("RINGBUF_SUPPORTED", &0, true) + .load(bytes) + .unwrap() + } + DisableMapRelocation::ByName(name) => { + EbpfLoader::new() + .ignore_maps_by_name(&[name]) + .set_global("RINGBUF_SUPPORTED", &0, true) + .load(bytes) + .unwrap() + } + }; + + let prog: &mut UProbe = ebpf.program_mut(name).unwrap().try_into().unwrap(); + prog.load().unwrap(); + + prog.attach( + Some("trigger_relocations_program"), + 0, + "/proc/self/exe", + None, + ) + .unwrap(); + + ebpf +} + fn load_and_attach(name: &str, bytes: &[u8]) -> Ebpf { let mut bpf = Ebpf::load(bytes).unwrap(); From 0e3556647932c1b1f6104e67397a6ddeab95e8d5 Mon Sep 17 00:00:00 2001 From: martinsoees Date: Wed, 19 Jun 2024 08:38:55 -0400 Subject: [PATCH 07/18] indentation --- aya/src/bpf.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 2b8b7017c..addc7d685 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -571,10 +571,10 @@ impl<'a> EbpfLoader<'a> { // pin maps in /sys/fs/bpf by default to align with libbpf // behavior https://github.com/libbpf/libbpf/blob/v1.2.2/src/libbpf.c#L2161. let path: &Path = map_pin_path - .as_deref() - .unwrap_or_else(|| Path::new("/sys/fs/bpf")); + .as_deref() + .unwrap_or_else(|| Path::new("/sys/fs/bpf")); - MapData::create_pinned_by_name(path, obj, &name, btf_fd)? + MapData::create_pinned_by_name(path, obj, &name, btf_fd)? } }; map.finalize()?; From ad2dc1b7f060d9d33f5632ce5c18525cbcb5e35a Mon Sep 17 00:00:00 2001 From: martinsoees Date: Thu, 20 Jun 2024 04:42:50 -0400 Subject: [PATCH 08/18] Fixed doc test --- aya-obj/src/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/aya-obj/src/lib.rs b/aya-obj/src/lib.rs index 480d4f331..99919c07c 100644 --- a/aya-obj/src/lib.rs +++ b/aya-obj/src/lib.rs @@ -31,17 +31,18 @@ //! This example loads a simple eBPF program and runs it with [rbpf]. //! //! ```no_run -//! use aya_obj::{generated::bpf_insn, Object}; -//! +//! use aya_obj::{generated::bpf_insn, Object, Map}; +//! //! // Parse the object file //! let bytes = std::fs::read("program.o").unwrap(); //! let mut object = Object::parse(&bytes).unwrap(); //! // Relocate the programs //! #[cfg(feature = "std")] //! let text_sections = std::collections::HashSet::new(); -//! let ignore_maps = std::collections::HashMap::new(); +//! let ignore_maps: std::collections::HashMap = std::collections::HashMap::new(); //! #[cfg(not(feature = "std"))] //! let text_sections = hashbrown::HashSet::new(); +//! let ignore_maps = hashbrown::HashMap::new(); //! object.relocate_calls(&text_sections).unwrap(); //! object.relocate_maps(std::iter::empty(), &text_sections, &ignore_maps).unwrap(); //! From c3084fd6a712c9c9e59eb10c259da64bca271781 Mon Sep 17 00:00:00 2001 From: martinsoees Date: Thu, 20 Jun 2024 04:53:58 -0400 Subject: [PATCH 09/18] removed newline at end of file --- test/integration-ebpf/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration-ebpf/Cargo.toml b/test/integration-ebpf/Cargo.toml index ec9004025..c988fa675 100644 --- a/test/integration-ebpf/Cargo.toml +++ b/test/integration-ebpf/Cargo.toml @@ -62,4 +62,4 @@ path = "src/ring_buf.rs" [[bin]] name = "ignore_map" -path = "src/ignore_map.rs" \ No newline at end of file +path = "src/ignore_map.rs" From b05ab1599dfcb3a5b9eb3ddf0033ebe31dcc7c5c Mon Sep 17 00:00:00 2001 From: martinsoees Date: Thu, 20 Jun 2024 05:49:56 -0400 Subject: [PATCH 10/18] Applied cargo fmt to fix formatting --- aya-obj/src/lib.rs | 2 +- aya-obj/src/relocation.rs | 5 +-- aya/src/bpf.rs | 32 +++++++------- .../integration-test/src/tests/relocations.rs | 42 +++++++++++-------- 4 files changed, 44 insertions(+), 37 deletions(-) diff --git a/aya-obj/src/lib.rs b/aya-obj/src/lib.rs index 99919c07c..04fa44410 100644 --- a/aya-obj/src/lib.rs +++ b/aya-obj/src/lib.rs @@ -32,7 +32,7 @@ //! //! ```no_run //! use aya_obj::{generated::bpf_insn, Object, Map}; -//! +//! //! // Parse the object file //! let bytes = std::fs::read("program.o").unwrap(); //! let mut object = Object::parse(&bytes).unwrap(); diff --git a/aya-obj/src/relocation.rs b/aya-obj/src/relocation.rs index 92d279c43..bbf7f1d3a 100644 --- a/aya-obj/src/relocation.rs +++ b/aya-obj/src/relocation.rs @@ -228,7 +228,6 @@ fn relocate_maps<'a, I: Iterator>( index: rel.symbol_index, })?; - let Some(section_index) = sym.section_index else { // this is not a map relocation continue; @@ -240,7 +239,7 @@ fn relocate_maps<'a, I: Iterator>( } let (_name, fd, map) = if ignored_by_symbol.contains(&rel.symbol_index) { - continue + continue; } else if let Some(m) = maps_by_symbol.get(&rel.symbol_index) { let map = &m.2; debug!( @@ -252,7 +251,7 @@ fn relocate_maps<'a, I: Iterator>( debug_assert_eq!(map.symbol_index().unwrap(), rel.symbol_index); m } else if ignored_by_section.contains(§ion_index) { - continue + continue; } else { let Some(m) = maps_by_section.get(§ion_index) else { debug!("failed relocating map by section index {}", section_index); diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index addc7d685..8c6803128 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -21,8 +21,8 @@ use thiserror::Error; use crate::{ generated::{ - bpf_map_type::{self, *}, AYA_PERF_EVENT_IOC_DISABLE, AYA_PERF_EVENT_IOC_ENABLE, - AYA_PERF_EVENT_IOC_SET_BPF, + bpf_map_type::{self, *}, + AYA_PERF_EVENT_IOC_DISABLE, AYA_PERF_EVENT_IOC_ENABLE, AYA_PERF_EVENT_IOC_SET_BPF, }, maps::{Map, MapData, MapError}, obj::{ @@ -230,19 +230,19 @@ impl<'a> EbpfLoader<'a> { /// Allows programs containing unsupported maps for the current kernel to be loaded /// by skipping map creation and relocation before loading. - /// + /// /// This is useful when you have a single ebpf program containing e.g. a `RingBuf` /// and a `PerfEventArray` and you decide which one to use before loading the bytecode. - /// + /// /// Must be used with `.set_global()` to signal if the map is supported in the ebpf program. - /// + /// /// # Example - /// + /// /// ```no_run /// use aya::EbpfLoader; /// use aya_obj::generated::bpf_map_type; /// use std::collections::HashSet; - /// + /// /// let ringbuf_supported = 0; /// let mut set = HashSet::new(); /// set.insert(bpf_map_type::BPF_MAP_TYPE_RINGBUF); @@ -252,7 +252,7 @@ impl<'a> EbpfLoader<'a> { /// .load_file("file.o")?; /// # Ok::<(), aya::EbpfError>(()) /// ``` - /// + /// pub fn ignore_maps_by_type(&mut self, set: HashSet) -> &mut Self { self.ignore_maps_by_type = set; self @@ -260,17 +260,17 @@ impl<'a> EbpfLoader<'a> { /// Allows programs containing unsupported maps for the current kernel to be loaded /// by skipping map creation and relocation before loading. - /// + /// /// This is useful when you have a single ebpf program containing e.g. a `RingBuf` /// and a `PerfEventArray` and you decide which one to use before loading the bytecode. - /// + /// /// Must be used with `.set_global()` to signal if the map is supported in the ebpf program. - /// + /// /// # Example - /// + /// /// ```no_run /// use aya::EbpfLoader; - /// + /// /// let ringbuf_supported = 0; /// let ebpf = EbpfLoader::new() /// .ignore_maps_by_name(&["RINGBUF"]) @@ -278,7 +278,7 @@ impl<'a> EbpfLoader<'a> { /// .load_file("file.o")?; /// # Ok::<(), aya::EbpfError>(()) /// ``` - /// + /// pub fn ignore_maps_by_name(&mut self, name: &'a [&'a str]) -> &mut Self { self.ignore_maps_by_name = name; self @@ -531,7 +531,9 @@ impl<'a> EbpfLoader<'a> { } let map_type: bpf_map_type = obj.map_type().try_into().map_err(MapError::from)?; - if ignore_maps_by_type.contains(&map_type) || ignore_maps_by_name.contains(&name.as_str()) { + if ignore_maps_by_type.contains(&map_type) + || ignore_maps_by_name.contains(&name.as_str()) + { ignored_maps.insert(name, obj); // ignore map creation. The map is saved in `ignored_maps` and filtered out // in `relocate_maps()` later on diff --git a/test/integration-test/src/tests/relocations.rs b/test/integration-test/src/tests/relocations.rs index 734cc5bae..98adf0449 100644 --- a/test/integration-test/src/tests/relocations.rs +++ b/test/integration-test/src/tests/relocations.rs @@ -11,13 +11,15 @@ enum DisableMapRelocation<'a> { #[test] fn test_ignored_map_relocation_by_type() { - let mut ebpf = relocation_load_and_attach("test_ignored_map_relocation", crate::IGNORE_MAP, DisableMapRelocation::ByType(bpf_map_type::BPF_MAP_TYPE_RINGBUF)); + let mut ebpf = relocation_load_and_attach( + "test_ignored_map_relocation", + crate::IGNORE_MAP, + DisableMapRelocation::ByType(bpf_map_type::BPF_MAP_TYPE_RINGBUF), + ); - let perf = ebpf - .take_map("PERFBUF"); + let perf = ebpf.take_map("PERFBUF"); - let ring = ebpf - .take_map("RINGBUF"); + let ring = ebpf.take_map("RINGBUF"); assert!(perf.is_some()); assert!(ring.is_none()); @@ -25,13 +27,15 @@ fn test_ignored_map_relocation_by_type() { #[test] fn test_ignored_map_relocation_by_name() { - let mut ebpf = relocation_load_and_attach("test_ignored_map_relocation", crate::IGNORE_MAP, DisableMapRelocation::ByName("RINGBUF")); + let mut ebpf = relocation_load_and_attach( + "test_ignored_map_relocation", + crate::IGNORE_MAP, + DisableMapRelocation::ByName("RINGBUF"), + ); - let perf = ebpf - .take_map("PERFBUF"); + let perf = ebpf.take_map("PERFBUF"); - let ring = ebpf - .take_map("RINGBUF"); + let ring = ebpf.take_map("RINGBUF"); assert!(perf.is_some()); assert!(ring.is_none()); @@ -69,7 +73,11 @@ fn text_64_64_reloc() { assert_eq!(m.get(&1, 0).unwrap(), 3); } -fn relocation_load_and_attach(name: &str, bytes: &[u8], disable_type: DisableMapRelocation) -> Ebpf { +fn relocation_load_and_attach( + name: &str, + bytes: &[u8], + disable_type: DisableMapRelocation, +) -> Ebpf { let mut ebpf = match disable_type { DisableMapRelocation::ByType(bmt) => { let mut set = HashSet::new(); @@ -80,13 +88,11 @@ fn relocation_load_and_attach(name: &str, bytes: &[u8], disable_type: DisableMap .load(bytes) .unwrap() } - DisableMapRelocation::ByName(name) => { - EbpfLoader::new() - .ignore_maps_by_name(&[name]) - .set_global("RINGBUF_SUPPORTED", &0, true) - .load(bytes) - .unwrap() - } + DisableMapRelocation::ByName(name) => EbpfLoader::new() + .ignore_maps_by_name(&[name]) + .set_global("RINGBUF_SUPPORTED", &0, true) + .load(bytes) + .unwrap(), }; let prog: &mut UProbe = ebpf.program_mut(name).unwrap().try_into().unwrap(); From d9cd8de7fcee646cd92610062976d91b1a48f9f0 Mon Sep 17 00:00:00 2001 From: martinsoees Date: Thu, 20 Jun 2024 06:06:12 -0400 Subject: [PATCH 11/18] Properly cfg gate std and non-std --- aya-obj/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aya-obj/src/lib.rs b/aya-obj/src/lib.rs index 04fa44410..36a22ec9c 100644 --- a/aya-obj/src/lib.rs +++ b/aya-obj/src/lib.rs @@ -39,9 +39,11 @@ //! // Relocate the programs //! #[cfg(feature = "std")] //! let text_sections = std::collections::HashSet::new(); -//! let ignore_maps: std::collections::HashMap = std::collections::HashMap::new(); +//! #[cfg(feature = "std")] +//! let ignore_maps = std::collections::HashMap::new(); //! #[cfg(not(feature = "std"))] //! let text_sections = hashbrown::HashSet::new(); +//! #[cfg(not(feature = "std"))] //! let ignore_maps = hashbrown::HashMap::new(); //! object.relocate_calls(&text_sections).unwrap(); //! object.relocate_maps(std::iter::empty(), &text_sections, &ignore_maps).unwrap(); From 7b9f1d26d162dd9eca263ecc935f2dde07240018 Mon Sep 17 00:00:00 2001 From: martinsoees Date: Fri, 12 Jul 2024 02:59:00 -0400 Subject: [PATCH 12/18] Review comments - Removed 'ignore_map_by_type' since 'ignore_map_by_name' makes more sense --- aya/src/bpf.rs | 39 ++------------------------------------- 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 8c6803128..3e93aaf8c 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -137,7 +137,6 @@ pub struct EbpfLoader<'a> { extensions: HashSet<&'a str>, verifier_log_level: VerifierLogLevel, allow_unsupported_maps: bool, - ignore_maps_by_type: HashSet, ignore_maps_by_name: &'a [&'a str], } @@ -177,7 +176,6 @@ impl<'a> EbpfLoader<'a> { extensions: HashSet::new(), verifier_log_level: VerifierLogLevel::default(), allow_unsupported_maps: false, - ignore_maps_by_type: HashSet::new(), ignore_maps_by_name: &[], } } @@ -234,37 +232,7 @@ impl<'a> EbpfLoader<'a> { /// This is useful when you have a single ebpf program containing e.g. a `RingBuf` /// and a `PerfEventArray` and you decide which one to use before loading the bytecode. /// - /// Must be used with `.set_global()` to signal if the map is supported in the ebpf program. - /// - /// # Example - /// - /// ```no_run - /// use aya::EbpfLoader; - /// use aya_obj::generated::bpf_map_type; - /// use std::collections::HashSet; - /// - /// let ringbuf_supported = 0; - /// let mut set = HashSet::new(); - /// set.insert(bpf_map_type::BPF_MAP_TYPE_RINGBUF); - /// let ebpf = EbpfLoader::new() - /// .ignore_maps_by_type(set) - /// .set_global("RINGBUF_SUPPORTED", &ringbuf_supported, true) - /// .load_file("file.o")?; - /// # Ok::<(), aya::EbpfError>(()) - /// ``` - /// - pub fn ignore_maps_by_type(&mut self, set: HashSet) -> &mut Self { - self.ignore_maps_by_type = set; - self - } - - /// Allows programs containing unsupported maps for the current kernel to be loaded - /// by skipping map creation and relocation before loading. - /// - /// This is useful when you have a single ebpf program containing e.g. a `RingBuf` - /// and a `PerfEventArray` and you decide which one to use before loading the bytecode. - /// - /// Must be used with `.set_global()` to signal if the map is supported in the ebpf program. + /// Must be used with [.set_global()] to signal if the map is supported in the ebpf program. /// /// # Example /// @@ -454,7 +422,6 @@ impl<'a> EbpfLoader<'a> { extensions, verifier_log_level, allow_unsupported_maps, - ignore_maps_by_type, ignore_maps_by_name, } = self; let mut obj = Object::parse(data)?; @@ -531,9 +498,7 @@ impl<'a> EbpfLoader<'a> { } let map_type: bpf_map_type = obj.map_type().try_into().map_err(MapError::from)?; - if ignore_maps_by_type.contains(&map_type) - || ignore_maps_by_name.contains(&name.as_str()) - { + if ignore_maps_by_name.contains(&name.as_str()) { ignored_maps.insert(name, obj); // ignore map creation. The map is saved in `ignored_maps` and filtered out // in `relocate_maps()` later on From 2e0bc82078f16ebe453a8efc344c2b27f6710d3e Mon Sep 17 00:00:00 2001 From: martinsoees Date: Fri, 12 Jul 2024 03:00:12 -0400 Subject: [PATCH 13/18] Review comments - Removed 'ignore_map_by_type' since 'ignore_map_by_name' makes more sense --- aya/src/bpf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 3e93aaf8c..27e9eebaf 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -496,7 +496,6 @@ impl<'a> EbpfLoader<'a> { { continue; } - let map_type: bpf_map_type = obj.map_type().try_into().map_err(MapError::from)?; if ignore_maps_by_name.contains(&name.as_str()) { ignored_maps.insert(name, obj); @@ -513,6 +512,7 @@ impl<'a> EbpfLoader<'a> { })? .len() as u32) }; + let map_type: bpf_map_type = obj.map_type().try_into().map_err(MapError::from)?; if let Some(max_entries) = max_entries_override( map_type, max_entries.get(name.as_str()).copied(), From 71ec04eb250c71bfa28f79c7b2a321ae40ab7e90 Mon Sep 17 00:00:00 2001 From: martinsoees Date: Fri, 12 Jul 2024 03:06:59 -0400 Subject: [PATCH 14/18] Proper rustdoc reference to Ebpfloader::set_global --- aya/src/bpf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 27e9eebaf..b86909356 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -232,7 +232,7 @@ impl<'a> EbpfLoader<'a> { /// This is useful when you have a single ebpf program containing e.g. a `RingBuf` /// and a `PerfEventArray` and you decide which one to use before loading the bytecode. /// - /// Must be used with [.set_global()] to signal if the map is supported in the ebpf program. + /// Must be used with [`EbpfLoader::set_global`] to signal if the map is supported in the ebpf program. /// /// # Example /// From 0b0d4c7e97026848e7627f39ea40b8ab80e41271 Mon Sep 17 00:00:00 2001 From: martinsoees Date: Fri, 12 Jul 2024 03:26:19 -0400 Subject: [PATCH 15/18] Map import unused in usage example --- aya-obj/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aya-obj/src/lib.rs b/aya-obj/src/lib.rs index 36a22ec9c..460d64240 100644 --- a/aya-obj/src/lib.rs +++ b/aya-obj/src/lib.rs @@ -31,7 +31,7 @@ //! This example loads a simple eBPF program and runs it with [rbpf]. //! //! ```no_run -//! use aya_obj::{generated::bpf_insn, Object, Map}; +//! use aya_obj::{generated::bpf_insn, Object}; //! //! // Parse the object file //! let bytes = std::fs::read("program.o").unwrap(); From 787d08b0317567a625173f4ff954695efe6c1a7a Mon Sep 17 00:00:00 2001 From: martinsoees Date: Fri, 12 Jul 2024 03:31:46 -0400 Subject: [PATCH 16/18] remove unintended explicit type declaration in code unrelated to this PR --- aya/src/bpf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index b86909356..6ec4c5c37 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -537,7 +537,7 @@ impl<'a> EbpfLoader<'a> { PinningType::ByName => { // pin maps in /sys/fs/bpf by default to align with libbpf // behavior https://github.com/libbpf/libbpf/blob/v1.2.2/src/libbpf.c#L2161. - let path: &Path = map_pin_path + let path = map_pin_path .as_deref() .unwrap_or_else(|| Path::new("/sys/fs/bpf")); From 492feb2147da669487cfde5c3ad5633137f84245 Mon Sep 17 00:00:00 2001 From: martinsoees Date: Fri, 12 Jul 2024 03:43:23 -0400 Subject: [PATCH 17/18] Remove relocation test by type The 'ignore_map_by_type' function has been removed. Also renamed test function and simplified the relocation builder since 'by_name' is the only option now --- .../integration-test/src/tests/relocations.rs | 51 +++---------------- 1 file changed, 8 insertions(+), 43 deletions(-) diff --git a/test/integration-test/src/tests/relocations.rs b/test/integration-test/src/tests/relocations.rs index 98adf0449..d4c44e3f2 100644 --- a/test/integration-test/src/tests/relocations.rs +++ b/test/integration-test/src/tests/relocations.rs @@ -1,36 +1,12 @@ -use std::collections::HashSet; - use aya::{programs::UProbe, util::KernelVersion, Ebpf, EbpfLoader}; -use aya_obj::generated::bpf_map_type; use test_log::test; -enum DisableMapRelocation<'a> { - ByType(bpf_map_type), - ByName(&'a str), -} - -#[test] -fn test_ignored_map_relocation_by_type() { - let mut ebpf = relocation_load_and_attach( - "test_ignored_map_relocation", - crate::IGNORE_MAP, - DisableMapRelocation::ByType(bpf_map_type::BPF_MAP_TYPE_RINGBUF), - ); - - let perf = ebpf.take_map("PERFBUF"); - - let ring = ebpf.take_map("RINGBUF"); - - assert!(perf.is_some()); - assert!(ring.is_none()); -} - #[test] -fn test_ignored_map_relocation_by_name() { +fn ignored_map_relocation_by_name() { let mut ebpf = relocation_load_and_attach( "test_ignored_map_relocation", crate::IGNORE_MAP, - DisableMapRelocation::ByName("RINGBUF"), + "RINGBUF", ); let perf = ebpf.take_map("PERFBUF"); @@ -76,24 +52,13 @@ fn text_64_64_reloc() { fn relocation_load_and_attach( name: &str, bytes: &[u8], - disable_type: DisableMapRelocation, + disable_map_name: &str, ) -> Ebpf { - let mut ebpf = match disable_type { - DisableMapRelocation::ByType(bmt) => { - let mut set = HashSet::new(); - set.insert(bmt); - EbpfLoader::new() - .ignore_maps_by_type(set) - .set_global("RINGBUF_SUPPORTED", &0, true) - .load(bytes) - .unwrap() - } - DisableMapRelocation::ByName(name) => EbpfLoader::new() - .ignore_maps_by_name(&[name]) - .set_global("RINGBUF_SUPPORTED", &0, true) - .load(bytes) - .unwrap(), - }; + let mut ebpf = EbpfLoader::new() + .ignore_maps_by_name(&[disable_map_name]) + .set_global("RINGBUF_SUPPORTED", &0, true) + .load(bytes) + .unwrap(); let prog: &mut UProbe = ebpf.program_mut(name).unwrap().try_into().unwrap(); prog.load().unwrap(); From d7e5f31b68e71e66b2280f1b4d471a13e6c3bf2c Mon Sep 17 00:00:00 2001 From: martinsoees Date: Fri, 12 Jul 2024 03:53:34 -0400 Subject: [PATCH 18/18] cargo fmt --- test/integration-test/src/tests/relocations.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/test/integration-test/src/tests/relocations.rs b/test/integration-test/src/tests/relocations.rs index d4c44e3f2..2c0326711 100644 --- a/test/integration-test/src/tests/relocations.rs +++ b/test/integration-test/src/tests/relocations.rs @@ -3,11 +3,8 @@ use test_log::test; #[test] fn ignored_map_relocation_by_name() { - let mut ebpf = relocation_load_and_attach( - "test_ignored_map_relocation", - crate::IGNORE_MAP, - "RINGBUF", - ); + let mut ebpf = + relocation_load_and_attach("test_ignored_map_relocation", crate::IGNORE_MAP, "RINGBUF"); let perf = ebpf.take_map("PERFBUF"); @@ -49,11 +46,7 @@ fn text_64_64_reloc() { assert_eq!(m.get(&1, 0).unwrap(), 3); } -fn relocation_load_and_attach( - name: &str, - bytes: &[u8], - disable_map_name: &str, -) -> Ebpf { +fn relocation_load_and_attach(name: &str, bytes: &[u8], disable_map_name: &str) -> Ebpf { let mut ebpf = EbpfLoader::new() .ignore_maps_by_name(&[disable_map_name]) .set_global("RINGBUF_SUPPORTED", &0, true)