diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index b513f09b..175798cd 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -48,7 +48,7 @@ unsafe_impl_pod!(i8, u8, i16, u16, i32, u32, i64, u64); #[allow(non_camel_case_types)] #[repr(C)] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Default)] pub(crate) struct bpf_map_def { // minimum features required by old BPF programs pub(crate) map_type: u32, @@ -57,34 +57,8 @@ pub(crate) struct bpf_map_def { pub(crate) max_entries: u32, pub(crate) map_flags: u32, // optional features - pub(crate) inner_map_fd: u32, // id - pub(crate) numa_node: u32, // pinning - pub(crate) map_name: [u8; BPF_OBJ_NAME_LEN], - pub(crate) map_ifindex: u32, - pub(crate) btf_id: u32, - pub(crate) btf_key_type_id: u32, - pub(crate) btf_value_type_id: u32, - pub(crate) btf_vmlinux_value_type_id: u32, -} - -impl Default for bpf_map_def { - fn default() -> Self { - Self { - map_type: 0, - key_size: 0, - value_size: 0, - max_entries: 0, - map_flags: 0, - inner_map_fd: 0, - numa_node: 0, - map_name: [0u8; BPF_OBJ_NAME_LEN], - map_ifindex: 0, - btf_id: 0, - btf_key_type_id: 0, - btf_value_type_id: 0, - btf_vmlinux_value_type_id: 0 - } - } + pub(crate) id: u32, // id + pub(crate) pinning: u32, // pinning } /// The main entry point into the library, used to work with eBPF programs and maps. diff --git a/aya/src/obj/mod.rs b/aya/src/obj/mod.rs index 2579dca7..5e548a3a 100644 --- a/aya/src/obj/mod.rs +++ b/aya/src/obj/mod.rs @@ -509,33 +509,24 @@ fn parse_map(section: &Section, name: &str) -> Result { } fn parse_map_def(name: &str, data: &[u8]) -> Result { - if mem::size_of::() < data.len() { + if data.len() > mem::size_of::() { return Err(ParseError::InvalidMapDefinition { name: name.to_owned(), }); } - let mut map_def = bpf_map_def{ - ..Default::default() - }; - - unsafe { - // std::ptr::copy is const, we can't use it because data.len() isn't known at - // compile time, this is only safe because we've asserted that data.len() - // must be <= mem::size_of::(), if you change that check, then - // you must change this copy - let mut p = data.as_ptr(); - let mut q = &mut map_def as *mut bpf_map_def as *mut u8; - for _ in 0..=data.len() { - *q = *p; - q = q.add(1); - p = p.add(1); + if data.len() < mem::size_of::() { + let mut map_def = bpf_map_def { ..Default::default() }; + unsafe { + ptr::copy(data.as_ptr() as *const bpf_map_def, &mut map_def as *mut bpf_map_def, 1); + // id and pinning will be garbage data + map_def.id = 0; + map_def.pinning = 0; } + Ok(map_def) + } else { + Ok(unsafe { ptr::read_unaligned(data.as_ptr() as *const bpf_map_def) }) } - - Ok(map_def) - - //Ok(unsafe { ptr::read_unaligned(data.as_ptr() as *const bpf_map_def) }) } fn copy_instructions(data: &[u8]) -> Result, ParseError> { @@ -703,6 +694,19 @@ mod tests { ), Ok(map_def) )); + + assert!(matches!( + parse_map_def( + "foo", + &[0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 0u8, 5u8] + ), + Ok(map_def) + )); + let map = parse_map_def( + "foo", + &[0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 0u8, 5u8] + ).unwrap(); + assert!(map.id == 0 && map.pinning == 0) } #[test]