From 8a9cbf179f62b68def7d30612cdffb576d062baa Mon Sep 17 00:00:00 2001 From: Andrew Stoycos Date: Tue, 6 Sep 2022 12:49:12 -0400 Subject: [PATCH] Add `from_pinned` and `from_fd` methods Add `from_pinned` to allow loading BPF maps from pinned points in the bpffs and `from_fd` to allow loading BPF maps from RawFds aquired via some other means eg a unix socket. These functions return an aya::Map which has not been used previously but will be the future abstraction once all bpf maps are represented as an enum. Signed-off-by: Andrew Stoycos --- aya/src/bpf.rs | 8 +-- aya/src/maps/array/array.rs | 6 +- aya/src/maps/array/per_cpu_array.rs | 6 +- aya/src/maps/array/program_array.rs | 6 +- aya/src/maps/bloom_filter.rs | 16 ++--- aya/src/maps/hash_map/hash_map.rs | 9 ++- aya/src/maps/hash_map/mod.rs | 6 +- aya/src/maps/hash_map/per_cpu_hash_map.rs | 6 +- aya/src/maps/lpm_trie.rs | 15 ++--- aya/src/maps/mod.rs | 76 ++++++++++++++++++----- aya/src/maps/queue.rs | 12 ++-- aya/src/maps/sock/sock_hash.rs | 3 +- aya/src/maps/sock/sock_map.rs | 6 +- aya/src/maps/stack.rs | 6 +- aya/src/maps/stack_trace.rs | 4 +- aya/src/obj/mod.rs | 41 +++++++++++- aya/src/programs/extension.rs | 4 +- aya/src/sys/bpf.rs | 23 +++++-- 18 files changed, 161 insertions(+), 92 deletions(-) diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index bd9ce595..3bd01c8b 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -443,7 +443,7 @@ impl<'a> BpfLoader<'a> { Err(_) => { let fd = map.create(&name)?; map.pin(&name, path).map_err(|error| MapError::PinError { - name: name.to_string(), + name: Some(name.to_string()), error, })?; fd @@ -454,16 +454,14 @@ impl<'a> BpfLoader<'a> { }; if !map.obj.data().is_empty() && map.obj.kind() != MapKind::Bss { bpf_map_update_elem_ptr(fd, &0 as *const _, map.obj.data_mut().as_mut_ptr(), 0) - .map_err(|(code, io_error)| MapError::SyscallError { + .map_err(|(_, io_error)| MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), - code, io_error, })?; } if map.obj.kind() == MapKind::Rodata { - bpf_map_freeze(fd).map_err(|(code, io_error)| MapError::SyscallError { + bpf_map_freeze(fd).map_err(|(_, io_error)| MapError::SyscallError { call: "bpf_map_freeze".to_owned(), - code, io_error, })?; } diff --git a/aya/src/maps/array/array.rs b/aya/src/maps/array/array.rs index 4e4aafd2..b1bef3e9 100644 --- a/aya/src/maps/array/array.rs +++ b/aya/src/maps/array/array.rs @@ -80,10 +80,9 @@ impl, V: Pod> Array { self.check_bounds(*index)?; let fd = self.inner.fd_or_err()?; - let value = bpf_map_lookup_elem(fd, index, flags).map_err(|(code, io_error)| { + let value = bpf_map_lookup_elem(fd, index, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_lookup_elem".to_owned(), - code, io_error, } })?; @@ -116,10 +115,9 @@ impl + DerefMut, V: Pod> Array { pub fn set(&mut self, index: u32, value: V, flags: u64) -> Result<(), MapError> { let fd = self.inner.fd_or_err()?; self.check_bounds(index)?; - bpf_map_update_elem(fd, Some(&index), &value, flags).map_err(|(code, io_error)| { + bpf_map_update_elem(fd, Some(&index), &value, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), - code, io_error, } })?; diff --git a/aya/src/maps/array/per_cpu_array.rs b/aya/src/maps/array/per_cpu_array.rs index f501aeda..99a3e7ed 100644 --- a/aya/src/maps/array/per_cpu_array.rs +++ b/aya/src/maps/array/per_cpu_array.rs @@ -99,10 +99,9 @@ impl, V: Pod> PerCpuArray { self.check_bounds(*index)?; let fd = self.inner.fd_or_err()?; - let value = bpf_map_lookup_elem_per_cpu(fd, index, flags).map_err(|(code, io_error)| { + let value = bpf_map_lookup_elem_per_cpu(fd, index, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_lookup_elem".to_owned(), - code, io_error, } })?; @@ -135,10 +134,9 @@ impl + DerefMut, V: Pod> PerCpuArray pub fn set(&mut self, index: u32, values: PerCpuValues, flags: u64) -> Result<(), MapError> { let fd = self.inner.fd_or_err()?; self.check_bounds(index)?; - bpf_map_update_elem_per_cpu(fd, &index, &values, flags).map_err(|(code, io_error)| { + bpf_map_update_elem_per_cpu(fd, &index, &values, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), - code, io_error, } })?; diff --git a/aya/src/maps/array/program_array.rs b/aya/src/maps/array/program_array.rs index a16dc607..5d02e026 100644 --- a/aya/src/maps/array/program_array.rs +++ b/aya/src/maps/array/program_array.rs @@ -103,10 +103,9 @@ impl + DerefMut> ProgramArray { self.check_bounds(index)?; let prog_fd = program.as_raw_fd(); - bpf_map_update_elem(fd, Some(&index), &prog_fd, flags).map_err(|(code, io_error)| { + bpf_map_update_elem(fd, Some(&index), &prog_fd, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), - code, io_error, } })?; @@ -122,9 +121,8 @@ impl + DerefMut> ProgramArray { self.check_bounds(*index)?; bpf_map_delete_elem(fd, index) .map(|_| ()) - .map_err(|(code, io_error)| MapError::SyscallError { + .map_err(|(_, io_error)| MapError::SyscallError { call: "bpf_map_delete_elem".to_owned(), - code, io_error, }) } diff --git a/aya/src/maps/bloom_filter.rs b/aya/src/maps/bloom_filter.rs index b0901df5..47ba0207 100644 --- a/aya/src/maps/bloom_filter.rs +++ b/aya/src/maps/bloom_filter.rs @@ -68,9 +68,8 @@ impl, V: Pod> BloomFilter { let fd = self.inner.deref().fd_or_err()?; bpf_map_lookup_elem_ptr::(fd, None, &mut value, flags) - .map_err(|(code, io_error)| MapError::SyscallError { + .map_err(|(_, io_error)| MapError::SyscallError { call: "bpf_map_lookup_elem".to_owned(), - code, io_error, })? .ok_or(MapError::ElementNotFound)?; @@ -80,12 +79,9 @@ impl, V: Pod> BloomFilter { /// Inserts a value into the map. pub fn insert(&self, value: V, flags: u64) -> Result<(), MapError> { let fd = self.inner.deref().fd_or_err()?; - bpf_map_push_elem(fd, &value, flags).map_err(|(code, io_error)| { - MapError::SyscallError { - call: "bpf_map_push_elem".to_owned(), - code, - io_error, - } + bpf_map_push_elem(fd, &value, flags).map_err(|(_, io_error)| MapError::SyscallError { + call: "bpf_map_push_elem".to_owned(), + io_error, })?; Ok(()) } @@ -254,7 +250,7 @@ mod tests { assert!(matches!( bloom_filter.insert(1, 0), - Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_push_elem" && io_error.raw_os_error() == Some(EFAULT) + Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_push_elem" && io_error.raw_os_error() == Some(EFAULT) )); } @@ -292,7 +288,7 @@ mod tests { assert!(matches!( bloom_filter.contains(&1, 0), - Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT) + Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT) )); } diff --git a/aya/src/maps/hash_map/hash_map.rs b/aya/src/maps/hash_map/hash_map.rs index 5b99b0d8..33bd6cc8 100644 --- a/aya/src/maps/hash_map/hash_map.rs +++ b/aya/src/maps/hash_map/hash_map.rs @@ -61,10 +61,9 @@ impl, K: Pod, V: Pod> HashMap { /// Returns a copy of the value associated with the key. pub fn get(&self, key: &K, flags: u64) -> Result { let fd = self.inner.deref().fd_or_err()?; - let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(code, io_error)| { + let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_lookup_elem".to_owned(), - code, io_error, } })?; @@ -313,7 +312,7 @@ mod tests { assert!(matches!( hm.insert(1, 42, 0), - Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_update_elem" && io_error.raw_os_error() == Some(EFAULT) + Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_update_elem" && io_error.raw_os_error() == Some(EFAULT) )); } @@ -352,7 +351,7 @@ mod tests { assert!(matches!( hm.remove(&1), - Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_delete_elem" && io_error.raw_os_error() == Some(EFAULT) + Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_delete_elem" && io_error.raw_os_error() == Some(EFAULT) )); } @@ -390,7 +389,7 @@ mod tests { assert!(matches!( hm.get(&1, 0), - Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT) + Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT) )); } diff --git a/aya/src/maps/hash_map/mod.rs b/aya/src/maps/hash_map/mod.rs index e878e2d4..60d0ec8a 100644 --- a/aya/src/maps/hash_map/mod.rs +++ b/aya/src/maps/hash_map/mod.rs @@ -29,10 +29,9 @@ pub(crate) fn check_kv_size(map: &Map) -> Result<(), MapError> { pub(crate) fn insert(map: &mut Map, key: K, value: V, flags: u64) -> Result<(), MapError> { let fd = map.fd_or_err()?; - bpf_map_update_elem(fd, Some(&key), &value, flags).map_err(|(code, io_error)| { + bpf_map_update_elem(fd, Some(&key), &value, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), - code, io_error, } })?; @@ -44,9 +43,8 @@ pub(crate) fn remove(map: &mut Map, key: &K) -> Result<(), MapError> { let fd = map.fd_or_err()?; bpf_map_delete_elem(fd, key) .map(|_| ()) - .map_err(|(code, io_error)| MapError::SyscallError { + .map_err(|(_, io_error)| MapError::SyscallError { call: "bpf_map_delete_elem".to_owned(), - code, io_error, }) } diff --git a/aya/src/maps/hash_map/per_cpu_hash_map.rs b/aya/src/maps/hash_map/per_cpu_hash_map.rs index 3399254a..dded8477 100644 --- a/aya/src/maps/hash_map/per_cpu_hash_map.rs +++ b/aya/src/maps/hash_map/per_cpu_hash_map.rs @@ -73,10 +73,9 @@ impl, K: Pod, V: Pod> PerCpuHashMap { /// Returns a slice of values - one for each CPU - associated with the key. pub fn get(&self, key: &K, flags: u64) -> Result, MapError> { let fd = self.inner.deref().fd_or_err()?; - let values = bpf_map_lookup_elem_per_cpu(fd, key, flags).map_err(|(code, io_error)| { + let values = bpf_map_lookup_elem_per_cpu(fd, key, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_lookup_elem".to_owned(), - code, io_error, } })?; @@ -127,10 +126,9 @@ impl, K: Pod, V: Pod> PerCpuHashMap { /// ``` pub fn insert(&mut self, key: K, values: PerCpuValues, flags: u64) -> Result<(), MapError> { let fd = self.inner.fd_or_err()?; - bpf_map_update_elem_per_cpu(fd, &key, &values, flags).map_err(|(code, io_error)| { + bpf_map_update_elem_per_cpu(fd, &key, &values, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), - code, io_error, } })?; diff --git a/aya/src/maps/lpm_trie.rs b/aya/src/maps/lpm_trie.rs index 405da462..98c217d7 100644 --- a/aya/src/maps/lpm_trie.rs +++ b/aya/src/maps/lpm_trie.rs @@ -129,10 +129,9 @@ impl, K: Pod, V: Pod> LpmTrie { /// Returns a copy of the value associated with the longest prefix matching key in the LpmTrie. pub fn get(&self, key: &Key, flags: u64) -> Result { let fd = self.inner.deref().fd_or_err()?; - let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(code, io_error)| { + let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_lookup_elem".to_owned(), - code, io_error, } })?; @@ -142,10 +141,9 @@ impl, K: Pod, V: Pod> LpmTrie { /// Inserts a key value pair into the map. pub fn insert(&self, key: &Key, value: V, flags: u64) -> Result<(), MapError> { let fd = self.inner.deref().fd_or_err()?; - bpf_map_update_elem(fd, Some(key), &value, flags).map_err(|(code, io_error)| { + bpf_map_update_elem(fd, Some(key), &value, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), - code, io_error, } })?; @@ -160,9 +158,8 @@ impl, K: Pod, V: Pod> LpmTrie { let fd = self.inner.deref().fd_or_err()?; bpf_map_delete_elem(fd, key) .map(|_| ()) - .map_err(|(code, io_error)| MapError::SyscallError { + .map_err(|(_, io_error)| MapError::SyscallError { call: "bpf_map_delete_elem".to_owned(), - code, io_error, }) } @@ -360,7 +357,7 @@ mod tests { let key = Key::new(16, u32::from(ipaddr).to_be()); assert!(matches!( trie.insert(&key, 1, 0), - Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_update_elem" && io_error.raw_os_error() == Some(EFAULT) + Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_update_elem" && io_error.raw_os_error() == Some(EFAULT) )); } @@ -402,7 +399,7 @@ mod tests { let key = Key::new(16, u32::from(ipaddr).to_be()); assert!(matches!( trie.remove(&key), - Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_delete_elem" && io_error.raw_os_error() == Some(EFAULT) + Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_delete_elem" && io_error.raw_os_error() == Some(EFAULT) )); } @@ -443,7 +440,7 @@ mod tests { assert!(matches!( trie.get(&key, 0), - Err(MapError::SyscallError { call, code: -1, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT) + Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT) )); } diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index aa45e55e..af7f489b 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -50,7 +50,10 @@ use crate::{ generated::bpf_map_type, obj, pin::PinError, - sys::{bpf_create_map, bpf_get_object, bpf_map_get_next_key, bpf_pin_object, kernel_version}, + sys::{ + bpf_create_map, bpf_get_object, bpf_map_get_info_by_fd, bpf_map_get_next_key, + bpf_pin_object, kernel_version, + }, util::nr_cpus, Pod, }; @@ -163,13 +166,10 @@ pub enum MapError { ProgramNotLoaded, /// Syscall failed - #[error("the `{call}` syscall failed with code {code}")] + #[error("the `{call}` syscall failed")] SyscallError { /// Syscall Name call: String, - /// Error code - code: libc::c_long, - #[source] /// Original io::Error io_error: io::Error, }, @@ -189,10 +189,10 @@ pub enum MapError { }, /// Could not pin map by name - #[error("map `{name}` requested pinning by name. pinning failed")] + #[error("map `{name:?}` requested pinning by name. pinning failed")] PinError { /// The map name - name: String, + name: Option, /// The reason for the failure #[source] error: PinError, @@ -292,18 +292,65 @@ impl Map { } let map_path = path.as_ref().join(name); let path_string = CString::new(map_path.to_str().unwrap()).unwrap(); - let fd = - bpf_get_object(&path_string).map_err(|(code, io_error)| MapError::SyscallError { - call: "BPF_OBJ_GET".to_string(), - code, - io_error, - })? as RawFd; + let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| MapError::SyscallError { + call: "BPF_OBJ_GET".to_string(), + io_error, + })? as RawFd; self.fd = Some(fd); Ok(fd) } + /// Loads a map from a pinned path in bpffs. + pub fn from_pinned>(path: P) -> Result { + let path_string = + CString::new(path.as_ref().to_string_lossy().into_owned()).map_err(|e| { + MapError::PinError { + name: None, + error: PinError::InvalidPinPath { + error: e.to_string(), + }, + } + })?; + + let fd = bpf_get_object(&path_string).map_err(|(_, io_error)| MapError::SyscallError { + call: "BPF_OBJ_GET".to_owned(), + io_error, + })? as RawFd; + + let info = bpf_map_get_info_by_fd(fd).map_err(|io_error| MapError::SyscallError { + call: "BPF_MAP_GET_INFO_BY_FD".to_owned(), + io_error, + })?; + + Ok(Map { + obj: obj::parse_map_info(info, crate::PinningType::ByName), + fd: Some(fd), + btf_fd: None, + pinned: true, + }) + } + + /// Loads a map from a [`RawFd`]. + /// + /// If loading from a BPF Filesystem (bpffs) you should use [`Map::from_pinned`]. + /// This API is intended for cases where you have received a valid BPF FD from some other means. + /// For example, you received an FD over Unix Domain Socket. + pub fn from_fd(fd: RawFd) -> Result { + let info = bpf_map_get_info_by_fd(fd).map_err(|io_error| MapError::SyscallError { + call: "BPF_OBJ_GET".to_owned(), + io_error, + })?; + + Ok(Map { + obj: obj::parse_map_info(info, crate::PinningType::None), + fd: Some(fd), + btf_fd: None, + pinned: false, + }) + } + /// Returns the [`bpf_map_type`] of this map pub fn map_type(&self) -> Result { bpf_map_type::try_from(self.obj.map_type()) @@ -402,11 +449,10 @@ impl Iterator for MapKeys<'_, K> { self.key = None; None } - Err((code, io_error)) => { + Err((_, io_error)) => { self.err = true; Some(Err(MapError::SyscallError { call: "bpf_map_get_next_key".to_owned(), - code, io_error, })) } diff --git a/aya/src/maps/queue.rs b/aya/src/maps/queue.rs index 20cb606d..f53abe57 100644 --- a/aya/src/maps/queue.rs +++ b/aya/src/maps/queue.rs @@ -81,9 +81,8 @@ impl + DerefMut, V: Pod> Queue { let fd = self.inner.fd_or_err()?; let value = bpf_map_lookup_and_delete_elem::(fd, None, flags).map_err( - |(code, io_error)| MapError::SyscallError { + |(_, io_error)| MapError::SyscallError { call: "bpf_map_lookup_and_delete_elem".to_owned(), - code, io_error, }, )?; @@ -97,12 +96,9 @@ impl + DerefMut, V: Pod> Queue { /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails. pub fn push(&mut self, value: V, flags: u64) -> Result<(), MapError> { let fd = self.inner.fd_or_err()?; - bpf_map_push_elem(fd, &value, flags).map_err(|(code, io_error)| { - MapError::SyscallError { - call: "bpf_map_push_elem".to_owned(), - code, - io_error, - } + bpf_map_push_elem(fd, &value, flags).map_err(|(_, io_error)| MapError::SyscallError { + call: "bpf_map_push_elem".to_owned(), + io_error, })?; Ok(()) } diff --git a/aya/src/maps/sock/sock_hash.rs b/aya/src/maps/sock/sock_hash.rs index 948213b5..a4016ead 100644 --- a/aya/src/maps/sock/sock_hash.rs +++ b/aya/src/maps/sock/sock_hash.rs @@ -87,10 +87,9 @@ impl, K: Pod> SockHash { /// Returns the fd of the socket stored at the given key. pub fn get(&self, key: &K, flags: u64) -> Result { let fd = self.inner.deref().fd_or_err()?; - let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(code, io_error)| { + let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_lookup_elem".to_owned(), - code, io_error, } })?; diff --git a/aya/src/maps/sock/sock_map.rs b/aya/src/maps/sock/sock_map.rs index 9941b09e..1abbf16a 100644 --- a/aya/src/maps/sock/sock_map.rs +++ b/aya/src/maps/sock/sock_map.rs @@ -89,9 +89,8 @@ impl + DerefMut> SockMap { let fd = self.inner.fd_or_err()?; self.check_bounds(index)?; bpf_map_update_elem(fd, Some(&index), &socket.as_raw_fd(), flags).map_err( - |(code, io_error)| MapError::SyscallError { + |(_, io_error)| MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), - code, io_error, }, )?; @@ -104,9 +103,8 @@ impl + DerefMut> SockMap { self.check_bounds(*index)?; bpf_map_delete_elem(fd, index) .map(|_| ()) - .map_err(|(code, io_error)| MapError::SyscallError { + .map_err(|(_, io_error)| MapError::SyscallError { call: "bpf_map_delete_elem".to_owned(), - code, io_error, }) } diff --git a/aya/src/maps/stack.rs b/aya/src/maps/stack.rs index 26fe828d..60d85758 100644 --- a/aya/src/maps/stack.rs +++ b/aya/src/maps/stack.rs @@ -81,9 +81,8 @@ impl + DerefMut, V: Pod> Stack { let fd = self.inner.fd_or_err()?; let value = bpf_map_lookup_and_delete_elem::(fd, None, flags).map_err( - |(code, io_error)| MapError::SyscallError { + |(_, io_error)| MapError::SyscallError { call: "bpf_map_lookup_and_delete_elem".to_owned(), - code, io_error, }, )?; @@ -97,10 +96,9 @@ impl + DerefMut, V: Pod> Stack { /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails. pub fn push(&mut self, value: V, flags: u64) -> Result<(), MapError> { let fd = self.inner.fd_or_err()?; - bpf_map_update_elem(fd, None::<&u32>, &value, flags).map_err(|(code, io_error)| { + bpf_map_update_elem(fd, None::<&u32>, &value, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), - code, io_error, } })?; diff --git a/aya/src/maps/stack_trace.rs b/aya/src/maps/stack_trace.rs index e67584d6..0d73353f 100644 --- a/aya/src/maps/stack_trace.rs +++ b/aya/src/maps/stack_trace.rs @@ -86,7 +86,6 @@ impl> StackTraceMap { sysctl::("kernel/perf_event_max_stack").map_err(|io_error| { MapError::SyscallError { call: "sysctl".to_owned(), - code: -1, io_error, } })?; @@ -113,9 +112,8 @@ impl> StackTraceMap { let mut frames = vec![0; self.max_stack_depth]; bpf_map_lookup_elem_ptr(fd, Some(stack_id), frames.as_mut_ptr(), flags) - .map_err(|(code, io_error)| MapError::SyscallError { + .map_err(|(_, io_error)| MapError::SyscallError { call: "bpf_map_lookup_elem".to_owned(), - code, io_error, })? .ok_or(MapError::KeyNotFound)?; diff --git a/aya/src/obj/mod.rs b/aya/src/obj/mod.rs index 2d0b39c2..dca36b70 100644 --- a/aya/src/obj/mod.rs +++ b/aya/src/obj/mod.rs @@ -19,7 +19,7 @@ use relocation::*; use crate::{ bpf_map_def, - generated::{bpf_insn, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_F_RDONLY_PROG}, + generated::{bpf_insn, bpf_map_info, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_F_RDONLY_PROG}, obj::btf::{Btf, BtfError, BtfExt, BtfType}, programs::{CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType}, BpfError, BtfMapDef, PinningType, @@ -1305,6 +1305,45 @@ fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, BtfMapDe Ok((map_name.to_string(), map_def)) } +pub(crate) fn parse_map_info(info: bpf_map_info, pinned: PinningType) -> Map { + if info.btf_key_type_id != 0 { + Map::Btf(BtfMap { + def: BtfMapDef { + map_type: info.type_, + key_size: info.key_size, + value_size: info.value_size, + max_entries: info.max_entries, + map_flags: info.map_flags, + pinning: pinned, + btf_key_type_id: info.btf_key_type_id, + btf_value_type_id: info.btf_value_type_id, + }, + section_index: 0, + symbol_index: 0, + data: Vec::new(), + // We should never be loading the .bss or .data or .rodata FDs + kind: MapKind::Other, + }) + } else { + Map::Legacy(LegacyMap { + def: bpf_map_def { + map_type: info.type_, + key_size: info.key_size, + value_size: info.value_size, + max_entries: info.max_entries, + map_flags: info.map_flags, + pinning: pinned, + id: info.id, + }, + section_index: 0, + symbol_index: 0, + data: Vec::new(), + // We should never be loading the .bss or .data or .rodata FDs + kind: MapKind::Other, + }) + } +} + pub(crate) fn copy_instructions(data: &[u8]) -> Result, ParseError> { if data.len() % mem::size_of::() > 0 { return Err(ParseError::InvalidProgramCode); diff --git a/aya/src/programs/extension.rs b/aya/src/programs/extension.rs index f5b5f9db..75296244 100644 --- a/aya/src/programs/extension.rs +++ b/aya/src/programs/extension.rs @@ -175,7 +175,7 @@ fn get_btf_info(prog_fd: i32, func_name: &str) -> Result<(RawFd, u32), ProgramEr let btf_info = sys::btf_obj_get_info_by_fd(btf_fd, &mut buf).map_err(|io_error| { ProgramError::SyscallError { - call: "btf_obj_get_info_by_fd".to_owned(), + call: "bpf_prog_get_info_by_fd".to_owned(), io_error, } })?; @@ -185,7 +185,7 @@ fn get_btf_info(prog_fd: i32, func_name: &str) -> Result<(RawFd, u32), ProgramEr } } Err(io_error) => Err(ProgramError::SyscallError { - call: "btf_obj_get_info_by_fd".to_owned(), + call: "bpf_prog_get_info_by_fd".to_owned(), io_error, }), }?; diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index 1e0010ea..f408a49b 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -11,8 +11,8 @@ use libc::{c_char, c_long, close, ENOENT, ENOSPC}; use crate::{ generated::{ - bpf_attach_type, bpf_attr, bpf_btf_info, bpf_cmd, bpf_insn, bpf_link_info, bpf_prog_info, - bpf_prog_type, BPF_F_REPLACE, + bpf_attach_type, bpf_attr, bpf_btf_info, bpf_cmd, bpf_insn, bpf_link_info, bpf_map_info, + bpf_prog_info, bpf_prog_type, BPF_F_REPLACE, }, maps::PerCpuValues, obj::{ @@ -439,14 +439,29 @@ pub(crate) fn bpf_prog_get_fd_by_id(prog_id: u32) -> Result { pub(crate) fn bpf_prog_get_info_by_fd(prog_fd: RawFd) -> Result { let mut attr = unsafe { mem::zeroed::() }; // info gets entirely populated by the kernel - let info = unsafe { MaybeUninit::zeroed().assume_init() }; + let info = MaybeUninit::zeroed(); attr.info.bpf_fd = prog_fd as u32; attr.info.info = &info as *const _ as u64; attr.info.info_len = mem::size_of::() as u32; match sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &attr) { - Ok(_) => Ok(info), + Ok(_) => Ok(unsafe { info.assume_init() }), + Err((_, err)) => Err(err), + } +} + +pub(crate) fn bpf_map_get_info_by_fd(prog_fd: RawFd) -> Result { + let mut attr = unsafe { mem::zeroed::() }; + // info gets entirely populated by the kernel + let info = MaybeUninit::zeroed(); + + attr.info.bpf_fd = prog_fd as u32; + attr.info.info = info.as_ptr() as *const _ as u64; + attr.info.info_len = mem::size_of::() as u32; + + match sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &attr) { + Ok(_) => Ok(unsafe { info.assume_init() }), Err((_, err)) => Err(err), } }