From 5c908f5266c2bf8329f297d7d9c05a556899ecb2 Mon Sep 17 00:00:00 2001 From: aorhant Date: Wed, 26 Feb 2025 18:54:13 +0100 Subject: [PATCH] aya: Fix PerCpuHashMap NotFound PerCpuHashMap was never returning MapError::KeyNotFound because bpf_map_lookup_elem_per_cpu was replacing Ok(None) with Ok(Some(zeroed_value)). Update bpf_map_lookup_elem_per_cpu to map the Option value. --- aya/src/maps/hash_map/per_cpu_hash_map.rs | 25 ++++++++++++++++++++++- aya/src/sys/bpf.rs | 2 +- 2 files changed, 25 insertions(+), 2 deletions(-) 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 d9194668..3d402a8b 100644 --- a/aya/src/maps/hash_map/per_cpu_hash_map.rs +++ b/aya/src/maps/hash_map/per_cpu_hash_map.rs @@ -151,12 +151,23 @@ impl, K: Pod, V: Pod> IterableMap> #[cfg(test)] mod tests { + use std::{ffi::c_long, io}; + + use assert_matches::assert_matches; use aya_obj::generated::bpf_map_type::{ BPF_MAP_TYPE_LRU_PERCPU_HASH, BPF_MAP_TYPE_PERCPU_HASH, }; + use libc::ENOENT; use super::*; - use crate::maps::{test_utils, Map}; + use crate::{ + maps::{test_utils, Map}, + sys::{override_syscall, SysResult}, + }; + + fn sys_error(value: i32) -> SysResult { + Err((-1, io::Error::from_raw_os_error(value))) + } #[test] fn test_try_from_ok() { @@ -174,4 +185,16 @@ mod tests { let map = Map::PerCpuLruHashMap(map_data()); assert!(PerCpuHashMap::<_, u32, u32>::try_from(&map).is_ok()) } + #[test] + #[cfg_attr(miri, ignore = "`open` not available when isolation is enabled")] + fn test_get_not_found() { + let map_data = + || test_utils::new_map(test_utils::new_obj_map::(BPF_MAP_TYPE_LRU_PERCPU_HASH)); + let map = Map::PerCpuHashMap(map_data()); + let map = PerCpuHashMap::<_, u32, u32>::try_from(&map).unwrap(); + + override_syscall(|_| sys_error(ENOENT)); + + assert_matches!(map.get(&1, 0), Err(MapError::KeyNotFound)); + } } diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index 791959f1..51ca7a97 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -249,7 +249,7 @@ pub(crate) fn bpf_map_lookup_elem_per_cpu( ) -> SysResult>> { let mut mem = PerCpuValues::::alloc_kernel_mem().map_err(|io_error| (-1, io_error))?; match bpf_map_lookup_elem_ptr(fd, Some(key), mem.as_mut_ptr(), flags) { - Ok(_) => Ok(Some(unsafe { PerCpuValues::from_kernel_mem(mem) })), + Ok(v) => Ok(v.map(|()| unsafe { PerCpuValues::from_kernel_mem(mem) })), Err((_, io_error)) if io_error.raw_os_error() == Some(ENOENT) => Ok(None), Err(e) => Err(e), }