diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index 3c2aa495..ab6773f9 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -3,7 +3,7 @@ use std::{ collections::{HashMap, HashSet}, ffi::CString, fs, io, - os::{raw::c_int, unix::io::RawFd}, + os::{fd::AsRawFd, raw::c_int, unix::io::RawFd}, path::{Path, PathBuf}, }; @@ -398,7 +398,7 @@ impl<'a> BpfLoader<'a> { pinned: false, btf_fd, }; - let fd = match map.obj.pinning() { + match map.obj.pinning() { PinningType::ByName => { let path = match &self.map_pin_path { Some(p) => p, @@ -406,31 +406,38 @@ impl<'a> BpfLoader<'a> { }; // try to open map in case it's already pinned match map.open_pinned(&name, path) { - Ok(fd) => { + Ok(_) => { map.pinned = true; - fd as RawFd } Err(_) => { - let fd = map.create(&name)?; + map.create(&name)?; map.pin(&name, path).map_err(|error| MapError::PinError { name: Some(name.to_string()), error, })?; - fd } } } PinningType::None => map.create(&name)?, }; + // OK: we just loaded the map + let fd = map.fd.as_ref().unwrap(); if !map.obj.data().is_empty() && map.obj.section_kind() != BpfSectionKind::Bss { - bpf_map_update_elem_ptr(fd, &0 as *const _, map.obj.data_mut().as_mut_ptr(), 0) - .map_err(|(_, io_error)| MapError::SyscallError { - call: "bpf_map_update_elem".to_owned(), - io_error, - })?; + // TODO (AM) + bpf_map_update_elem_ptr( + fd.as_raw_fd(), + &0 as *const _, + map.obj.data_mut().as_mut_ptr(), + 0, + ) + .map_err(|(_, io_error)| MapError::SyscallError { + call: "bpf_map_update_elem".to_owned(), + io_error, + })?; } if map.obj.section_kind() == BpfSectionKind::Rodata { - bpf_map_freeze(fd).map_err(|(_, io_error)| MapError::SyscallError { + // TODO (AM) + bpf_map_freeze(fd.as_raw_fd()).map_err(|(_, io_error)| MapError::SyscallError { call: "bpf_map_freeze".to_owned(), io_error, })?; @@ -446,7 +453,14 @@ impl<'a> BpfLoader<'a> { obj.relocate_maps( maps.iter() - .map(|(s, data)| (s.as_str(), data.fd, &data.obj)), + // TODO (AM) + .map(|(s, data)| { + ( + s.as_str(), + data.fd.as_ref().map(|f| f.as_raw_fd()), + &data.obj, + ) + }), &text_sections, )?; obj.relocate_calls(&text_sections)?; diff --git a/aya/src/maps/array/array.rs b/aya/src/maps/array/array.rs index 71ac1223..07b55cc9 100644 --- a/aya/src/maps/array/array.rs +++ b/aya/src/maps/array/array.rs @@ -1,6 +1,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsRawFd, }; use crate::{ @@ -65,12 +66,14 @@ impl, V: Pod> Array { check_bounds(data, *index)?; let fd = data.fd_or_err()?; - let value = bpf_map_lookup_elem(fd, index, flags).map_err(|(_, io_error)| { - MapError::SyscallError { - call: "bpf_map_lookup_elem".to_owned(), - io_error, - } - })?; + // TODO (AM) + let value = + bpf_map_lookup_elem(fd.as_raw_fd(), index, flags).map_err(|(_, io_error)| { + MapError::SyscallError { + call: "bpf_map_lookup_elem".to_owned(), + io_error, + } + })?; value.ok_or(MapError::KeyNotFound) } @@ -92,12 +95,13 @@ impl, V: Pod> Array { let data = self.inner.borrow_mut(); check_bounds(data, index)?; let fd = data.fd_or_err()?; - bpf_map_update_elem(fd, Some(&index), value.borrow(), flags).map_err(|(_, io_error)| { - MapError::SyscallError { + // TODO (AM) + bpf_map_update_elem(fd.as_raw_fd(), Some(&index), value.borrow(), flags).map_err( + |(_, io_error)| MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), io_error, - } - })?; + }, + )?; Ok(()) } } diff --git a/aya/src/maps/array/per_cpu_array.rs b/aya/src/maps/array/per_cpu_array.rs index e83f59e5..fcfc8090 100644 --- a/aya/src/maps/array/per_cpu_array.rs +++ b/aya/src/maps/array/per_cpu_array.rs @@ -1,6 +1,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsRawFd, }; use crate::{ @@ -84,12 +85,13 @@ impl, V: Pod> PerCpuArray { check_bounds(data, *index)?; let fd = data.fd_or_err()?; - let value = bpf_map_lookup_elem_per_cpu(fd, index, flags).map_err(|(_, io_error)| { - MapError::SyscallError { + // TODO (AM) + let value = bpf_map_lookup_elem_per_cpu(fd.as_raw_fd(), index, flags).map_err( + |(_, io_error)| MapError::SyscallError { call: "bpf_map_lookup_elem".to_owned(), io_error, - } - })?; + }, + )?; value.ok_or(MapError::KeyNotFound) } @@ -112,12 +114,13 @@ impl, V: Pod> PerCpuArray { check_bounds(data, index)?; let fd = data.fd_or_err()?; - bpf_map_update_elem_per_cpu(fd, &index, &values, flags).map_err(|(_, io_error)| { - MapError::SyscallError { + // TODO (AM) + bpf_map_update_elem_per_cpu(fd.as_raw_fd(), &index, &values, flags).map_err( + |(_, io_error)| MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), io_error, - } - })?; + }, + )?; Ok(()) } } diff --git a/aya/src/maps/array/program_array.rs b/aya/src/maps/array/program_array.rs index 8418b1cd..fb19cf26 100644 --- a/aya/src/maps/array/program_array.rs +++ b/aya/src/maps/array/program_array.rs @@ -79,12 +79,13 @@ impl> ProgramArray { let fd = data.fd_or_err()?; let prog_fd = program.as_raw_fd(); - bpf_map_update_elem(fd, Some(&index), &prog_fd, flags).map_err(|(_, io_error)| { - MapError::SyscallError { + // TODO (AM) + bpf_map_update_elem(fd.as_raw_fd(), Some(&index), &prog_fd, flags).map_err( + |(_, io_error)| MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), io_error, - } - })?; + }, + )?; Ok(()) } @@ -97,7 +98,8 @@ impl> ProgramArray { check_bounds(data, *index)?; let fd = self.inner.borrow_mut().fd_or_err()?; - bpf_map_delete_elem(fd, index) + // TODO (AM) + bpf_map_delete_elem(fd.as_raw_fd(), index) .map(|_| ()) .map_err(|(_, io_error)| MapError::SyscallError { call: "bpf_map_delete_elem".to_owned(), diff --git a/aya/src/maps/bloom_filter.rs b/aya/src/maps/bloom_filter.rs index f7f4be02..afc9c5b5 100644 --- a/aya/src/maps/bloom_filter.rs +++ b/aya/src/maps/bloom_filter.rs @@ -1,5 +1,5 @@ //! A Bloom Filter. -use std::{borrow::Borrow, marker::PhantomData}; +use std::{borrow::Borrow, marker::PhantomData, os::fd::AsRawFd}; use crate::{ maps::{check_v_size, MapData, MapError}, @@ -52,7 +52,8 @@ impl, V: Pod> BloomFilter { pub fn contains(&self, mut value: &V, flags: u64) -> Result<(), MapError> { let fd = self.inner.borrow().fd_or_err()?; - bpf_map_lookup_elem_ptr::(fd, None, &mut value, flags) + // TODO (AM) + bpf_map_lookup_elem_ptr::(fd.as_raw_fd(), None, &mut value, flags) .map_err(|(_, io_error)| MapError::SyscallError { call: "bpf_map_lookup_elem".to_owned(), io_error, @@ -64,7 +65,8 @@ impl, V: Pod> BloomFilter { /// Inserts a value into the map. pub fn insert(&self, value: impl Borrow, flags: u64) -> Result<(), MapError> { let fd = self.inner.borrow().fd_or_err()?; - bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| { + // TODO (AM) + bpf_map_push_elem(fd.as_raw_fd(), value.borrow(), flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_push_elem".to_owned(), io_error, @@ -88,7 +90,7 @@ mod tests { sys::{override_syscall, SysResult, Syscall}, }; use libc::{EFAULT, ENOENT}; - use std::io; + use std::{env, fs::File, io, os::fd::OwnedFd}; fn new_obj_map() -> obj::Map { obj::Map::Legacy(LegacyMap { @@ -175,7 +177,7 @@ mod tests { fn test_new_ok() { let mut map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -187,7 +189,7 @@ mod tests { fn test_try_from_ok() { let map_data = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -202,7 +204,7 @@ mod tests { let mut map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -226,7 +228,7 @@ mod tests { let mut map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -240,7 +242,7 @@ mod tests { override_syscall(|_| sys_error(EFAULT)); let map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -263,7 +265,7 @@ mod tests { }); let map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -274,4 +276,11 @@ mod tests { Err(MapError::ElementNotFound) )); } + + fn create_fd() -> OwnedFd { + let dir = env::temp_dir(); + File::create(dir.join("f1")) + .expect("unable to create file in tmpdir") + .into() + } } diff --git a/aya/src/maps/hash_map/hash_map.rs b/aya/src/maps/hash_map/hash_map.rs index 26a4af0f..bfe3dc71 100644 --- a/aya/src/maps/hash_map/hash_map.rs +++ b/aya/src/maps/hash_map/hash_map.rs @@ -1,6 +1,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsRawFd, }; use crate::{ @@ -54,7 +55,8 @@ 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.borrow().fd_or_err()?; - let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| { + // TODO (AM) + let value = bpf_map_lookup_elem(fd.as_raw_fd(), key, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_lookup_elem".to_owned(), io_error, @@ -105,7 +107,7 @@ impl, K: Pod, V: Pod> IterableMap for HashMap #[cfg(test)] mod tests { - use std::io; + use std::{env, fs::File, io, os::fd::OwnedFd}; use libc::{EFAULT, ENOENT}; @@ -230,7 +232,7 @@ mod tests { fn test_new_ok() { let mut map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -242,7 +244,7 @@ mod tests { fn test_try_from_ok() { let map_data = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -267,7 +269,7 @@ mod tests { symbol_index: None, data: Vec::new(), }), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -283,7 +285,7 @@ mod tests { let mut map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -307,7 +309,7 @@ mod tests { let mut map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -328,7 +330,7 @@ mod tests { let mut map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -343,7 +345,7 @@ mod tests { let mut map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -367,7 +369,7 @@ mod tests { let mut map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -381,7 +383,7 @@ mod tests { override_syscall(|_| sys_error(EFAULT)); let map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -404,7 +406,7 @@ mod tests { }); let map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -441,7 +443,7 @@ mod tests { }); let map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -490,7 +492,7 @@ mod tests { let map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -523,7 +525,7 @@ mod tests { }); let map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -558,7 +560,7 @@ mod tests { }); let map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -596,7 +598,7 @@ mod tests { }); let map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -635,7 +637,7 @@ mod tests { }); let map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -680,7 +682,7 @@ mod tests { }); let map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -695,4 +697,11 @@ mod tests { assert!(matches!(iter.next(), Some(Ok((30, 300))))); assert!(matches!(iter.next(), None)); } + + fn create_fd() -> OwnedFd { + let dir = env::temp_dir(); + File::create(dir.join("f1")) + .expect("unable to create file in tmpdir") + .into() + } } diff --git a/aya/src/maps/hash_map/mod.rs b/aya/src/maps/hash_map/mod.rs index f1e1837f..a816ff97 100644 --- a/aya/src/maps/hash_map/mod.rs +++ b/aya/src/maps/hash_map/mod.rs @@ -1,4 +1,6 @@ //! Hash map types. +use std::os::fd::AsRawFd; + use crate::{ maps::MapError, sys::{bpf_map_delete_elem, bpf_map_update_elem}, @@ -21,7 +23,8 @@ pub(crate) fn insert( flags: u64, ) -> Result<(), MapError> { let fd = map.fd_or_err()?; - bpf_map_update_elem(fd, Some(key), value, flags).map_err(|(_, io_error)| { + // TODO (AM) + bpf_map_update_elem(fd.as_raw_fd(), Some(key), value, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), io_error, @@ -33,7 +36,8 @@ pub(crate) fn insert( pub(crate) fn remove(map: &mut MapData, key: &K) -> Result<(), MapError> { let fd = map.fd_or_err()?; - bpf_map_delete_elem(fd, key) + // TODO (AM) + bpf_map_delete_elem(fd.as_raw_fd(), key) .map(|_| ()) .map_err(|(_, io_error)| MapError::SyscallError { call: "bpf_map_delete_elem".to_owned(), 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 aaa48838..34d60689 100644 --- a/aya/src/maps/hash_map/per_cpu_hash_map.rs +++ b/aya/src/maps/hash_map/per_cpu_hash_map.rs @@ -2,6 +2,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsRawFd, }; use crate::{ @@ -64,12 +65,14 @@ 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.borrow().fd_or_err()?; - let values = bpf_map_lookup_elem_per_cpu(fd, key, flags).map_err(|(_, io_error)| { - MapError::SyscallError { - call: "bpf_map_lookup_elem".to_owned(), - io_error, - } - })?; + let values = + // TODO (AM) + bpf_map_lookup_elem_per_cpu(fd.as_raw_fd(), key, flags).map_err(|(_, io_error)| { + MapError::SyscallError { + call: "bpf_map_lookup_elem".to_owned(), + io_error, + } + })?; values.ok_or(MapError::KeyNotFound) } @@ -122,7 +125,8 @@ impl, K: Pod, V: Pod> PerCpuHashMap { flags: u64, ) -> Result<(), MapError> { let fd = self.inner.borrow_mut().fd_or_err()?; - bpf_map_update_elem_per_cpu(fd, key.borrow(), &values, flags).map_err( + // TODO (AM) + bpf_map_update_elem_per_cpu(fd.as_raw_fd(), key.borrow(), &values, flags).map_err( |(_, io_error)| MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), io_error, diff --git a/aya/src/maps/lpm_trie.rs b/aya/src/maps/lpm_trie.rs index 34b86ef0..177fa213 100644 --- a/aya/src/maps/lpm_trie.rs +++ b/aya/src/maps/lpm_trie.rs @@ -2,6 +2,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsRawFd, }; use crate::{ @@ -128,7 +129,8 @@ 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.borrow().fd_or_err()?; - let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| { + // TODO (AM) + let value = bpf_map_lookup_elem(fd.as_raw_fd(), key, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_lookup_elem".to_owned(), io_error, @@ -159,12 +161,13 @@ impl, K: Pod, V: Pod> LpmTrie { flags: u64, ) -> Result<(), MapError> { let fd = self.inner.borrow().fd_or_err()?; - bpf_map_update_elem(fd, Some(key), value.borrow(), flags).map_err(|(_, io_error)| { - MapError::SyscallError { + // TODO (AM) + bpf_map_update_elem(fd.as_raw_fd(), Some(key), value.borrow(), flags).map_err( + |(_, io_error)| MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), io_error, - } - })?; + }, + )?; Ok(()) } @@ -174,7 +177,8 @@ impl, K: Pod, V: Pod> LpmTrie { /// Both the prefix and data must match exactly - this method does not do a longest prefix match. pub fn remove(&mut self, key: &Key) -> Result<(), MapError> { let fd = self.inner.borrow().fd_or_err()?; - bpf_map_delete_elem(fd, key) + // TODO (AM) + bpf_map_delete_elem(fd.as_raw_fd(), key) .map(|_| ()) .map_err(|(_, io_error)| MapError::SyscallError { call: "bpf_map_delete_elem".to_owned(), @@ -207,7 +211,7 @@ mod tests { sys::{override_syscall, SysResult, Syscall}, }; use libc::{EFAULT, ENOENT}; - use std::{io, mem, net::Ipv4Addr}; + use std::{env, fs::File, io, mem, net::Ipv4Addr, os::fd::OwnedFd}; fn new_obj_map() -> obj::Map { obj::Map::Legacy(LegacyMap { @@ -311,7 +315,7 @@ mod tests { fn test_new_ok() { let mut map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -323,7 +327,7 @@ mod tests { fn test_try_from_ok() { let map_data = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -338,7 +342,7 @@ mod tests { let mut map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -363,7 +367,7 @@ mod tests { let mut map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -380,7 +384,7 @@ mod tests { let mut map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -405,7 +409,7 @@ mod tests { let mut map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -420,7 +424,7 @@ mod tests { override_syscall(|_| sys_error(EFAULT)); let map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -445,7 +449,7 @@ mod tests { }); let map = MapData { obj: new_obj_map(), - fd: Some(42), + fd: Some(create_fd()), pinned: false, btf_fd: None, }; @@ -455,4 +459,11 @@ mod tests { assert!(matches!(trie.get(&key, 0), Err(MapError::KeyNotFound))); } + + fn create_fd() -> OwnedFd { + let dir = env::temp_dir(); + File::create(dir.join("f1")) + .expect("unable to create file in tmpdir") + .into() + } } diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 3f20c503..68ad72d2 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -42,7 +42,7 @@ use std::{ marker::PhantomData, mem, ops::Deref, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd}, path::Path, ptr, }; @@ -185,11 +185,17 @@ pub enum MapError { } /// A map file descriptor. -pub struct MapFd(RawFd); +pub struct MapFd<'f>(BorrowedFd<'f>); -impl AsRawFd for MapFd { +impl AsRawFd for MapFd<'_> { fn as_raw_fd(&self) -> RawFd { - self.0 + self.0.as_raw_fd() + } +} + +impl AsFd for MapFd<'_> { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() } } @@ -474,7 +480,7 @@ pub(crate) fn check_v_size(map: &MapData) -> Result<(), MapError> { #[derive(Debug)] pub struct MapData { pub(crate) obj: obj::Map, - pub(crate) fd: Option, + pub(crate) fd: Option, pub(crate) btf_fd: Option, /// Indicates if this map has been pinned to bpffs pub pinned: bool, @@ -482,7 +488,7 @@ pub struct MapData { impl MapData { /// Creates a new map with the provided `name` - pub fn create(&mut self, name: &str) -> Result { + pub fn create(&mut self, name: &str) -> Result<(), MapError> { if self.fd.is_some() { return Err(MapError::AlreadyCreated { name: name.into() }); } @@ -500,18 +506,18 @@ impl MapData { code, io_error, } - })? as RawFd; + })?; self.fd = Some(fd); - Ok(fd) + Ok(()) } pub(crate) fn open_pinned>( &mut self, name: &str, path: P, - ) -> Result { + ) -> Result<(), MapError> { if self.fd.is_some() { return Err(MapError::AlreadyCreated { name: name.into() }); } @@ -520,11 +526,10 @@ impl MapData { 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) + Ok(()) } /// Loads a map from a pinned path in bpffs. @@ -542,13 +547,15 @@ impl MapData { 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, })?; + // TODO (AM) + let info = + bpf_map_get_info_by_fd(fd.as_raw_fd()).map_err(|io_error| MapError::SyscallError { + call: "BPF_MAP_GET_INFO_BY_FD".to_owned(), + io_error, + })?; + Ok(MapData { obj: parse_map_info(info, PinningType::ByName), fd: Some(fd), @@ -562,11 +569,13 @@ impl MapData { /// If loading from a BPF Filesystem (bpffs) you should use [`Map::from_pin`](crate::maps::MapData::from_pin). /// 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, - })?; + pub fn from_fd(fd: OwnedFd) -> Result { + // TODO (AM) + let info = + bpf_map_get_info_by_fd(fd.as_raw_fd()).map_err(|io_error| MapError::SyscallError { + call: "BPF_OBJ_GET".to_owned(), + io_error, + })?; Ok(MapData { obj: parse_map_info(info, PinningType::None), @@ -576,8 +585,11 @@ impl MapData { }) } - pub(crate) fn fd_or_err(&self) -> Result { - self.fd.ok_or(MapError::NotCreated) + pub(crate) fn fd_or_err(&self) -> Result, MapError> { + self.fd + .as_ref() + .map(|f| f.as_fd()) + .ok_or(MapError::NotCreated) } pub(crate) fn pin>(&mut self, name: &str, path: P) -> Result<(), PinError> { @@ -585,7 +597,7 @@ impl MapData { return Err(PinError::AlreadyPinned { name: name.into() }); } let map_path = path.as_ref().join(name); - let fd = self.fd.ok_or(PinError::NoFd { + let fd = self.fd.as_ref().ok_or(PinError::NoFd { name: name.to_string(), })?; let path_string = CString::new(map_path.to_string_lossy().into_owned()).map_err(|e| { @@ -593,9 +605,12 @@ impl MapData { error: e.to_string(), } })?; - bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError { - name: "BPF_OBJ_PIN".to_string(), - io_error, + // TODO (AM): switch to BorrowedFd + bpf_pin_object(fd.as_raw_fd(), &path_string).map_err(|(_, io_error)| { + PinError::SyscallError { + name: "BPF_OBJ_PIN".to_string(), + io_error, + } })?; self.pinned = true; Ok(()) @@ -604,28 +619,32 @@ impl MapData { /// Returns the file descriptor of the map. /// /// Can be converted to [`RawFd`] using [`AsRawFd`]. - pub fn fd(&self) -> Option { - self.fd.map(MapFd) + pub fn fd(&self) -> Option> { + self.fd.as_ref().map(|fd| MapFd(fd.as_fd())) } } -impl Drop for MapData { - fn drop(&mut self) { - // TODO: Replace this with an OwnedFd once that is stabilized. - if let Some(fd) = self.fd.take() { - unsafe { libc::close(fd) }; - } +impl MapData { + /// Attempts to duplicate MapData + /// + /// Fails if if the inner file descriptor could not be cloned + // TODO (AM): should we return MapError? New variant? Maybe make MapError non_exhaustive? + pub fn try_clone(&self) -> io::Result { + let fd = self.fd.as_ref().map(|f| f.try_clone()).transpose()?; + + Ok(MapData { + fd, + obj: self.obj.clone(), + btf_fd: self.btf_fd, + pinned: self.pinned, + }) } } +// TODO (AM): DELETE? impl Clone for MapData { fn clone(&self) -> MapData { - MapData { - obj: self.obj.clone(), - fd: self.fd.map(|fd| unsafe { libc::dup(fd) }), - btf_fd: self.btf_fd, - pinned: self.pinned, - } + self.try_clone().unwrap() } } @@ -671,7 +690,8 @@ impl Iterator for MapKeys<'_, K> { } }; - match bpf_map_get_next_key(fd, self.key.as_ref()) { + // TODO (AM) + match bpf_map_get_next_key(fd.as_raw_fd(), self.key.as_ref()) { Ok(Some(key)) => { self.key = Some(key); Some(Ok(key)) @@ -874,8 +894,8 @@ mod tests { }); let mut map = new_map(); - assert!(matches!(map.create("foo"), Ok(42))); - assert_eq!(map.fd, Some(42)); + map.create("foo").unwrap(); + assert_eq!(map.fd.as_ref().unwrap().as_raw_fd(), 42); assert!(matches!( map.create("foo"), Err(MapError::AlreadyCreated { .. }) @@ -899,6 +919,6 @@ mod tests { assert_eq!(code, -42); assert_eq!(io_error.raw_os_error(), Some(EFAULT)); } - assert_eq!(map.fd, None); + assert!(map.fd.is_none()); } } diff --git a/aya/src/maps/perf/perf_event_array.rs b/aya/src/maps/perf/perf_event_array.rs index c241a37b..17f408f0 100644 --- a/aya/src/maps/perf/perf_event_array.rs +++ b/aya/src/maps/perf/perf_event_array.rs @@ -64,7 +64,7 @@ impl + Borrow> AsRawFd for PerfEventArrayBuffer + Borrow> AsRawFd for PerfEventArrayBuffer + Borrow> PerfEventArray { let map_data: &MapData = self.map.deref().borrow(); let map_fd = map_data.fd_or_err().unwrap(); let buf = PerfBuffer::open(index, self.page_size, page_count.unwrap_or(2))?; - bpf_map_update_elem(map_fd, Some(&index), &buf.as_raw_fd(), 0) + // TODO (AM) + bpf_map_update_elem(map_fd.as_raw_fd(), Some(&index), &buf.as_raw_fd(), 0) .map_err(|(_, io_error)| io_error)?; Ok(PerfEventArrayBuffer { diff --git a/aya/src/maps/queue.rs b/aya/src/maps/queue.rs index c6810546..a5589674 100644 --- a/aya/src/maps/queue.rs +++ b/aya/src/maps/queue.rs @@ -2,6 +2,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsRawFd, }; use crate::{ @@ -64,7 +65,8 @@ impl, V: Pod> Queue { pub fn pop(&mut self, flags: u64) -> Result { let fd = self.inner.borrow().fd_or_err()?; - let value = bpf_map_lookup_and_delete_elem::(fd, None, flags).map_err( + // TODO (AM) + let value = bpf_map_lookup_and_delete_elem::(fd.as_raw_fd(), None, flags).map_err( |(_, io_error)| MapError::SyscallError { call: "bpf_map_lookup_and_delete_elem".to_owned(), io_error, @@ -80,7 +82,8 @@ impl, V: Pod> Queue { /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails. pub fn push(&mut self, value: impl Borrow, flags: u64) -> Result<(), MapError> { let fd = self.inner.borrow().fd_or_err()?; - bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| { + // TODO (AM) + bpf_map_push_elem(fd.as_raw_fd(), value.borrow(), flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_push_elem".to_owned(), io_error, diff --git a/aya/src/maps/sock/sock_hash.rs b/aya/src/maps/sock/sock_hash.rs index 244dcd1c..cbe0ddf8 100644 --- a/aya/src/maps/sock/sock_hash.rs +++ b/aya/src/maps/sock/sock_hash.rs @@ -83,7 +83,8 @@ 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.borrow().fd_or_err()?; - let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| { + // TODO (AM) + let value = bpf_map_lookup_elem(fd.as_raw_fd(), key, flags).map_err(|(_, io_error)| { MapError::SyscallError { call: "bpf_map_lookup_elem".to_owned(), io_error, @@ -109,7 +110,8 @@ impl, K: Pod> SockHash { /// The returned file descriptor can be used to attach programs that work with /// socket maps, like [`SkMsg`](crate::programs::SkMsg) and [`SkSkb`](crate::programs::SkSkb). pub fn fd(&self) -> Result { - Ok(SockMapFd(self.inner.borrow().fd_or_err()?)) + // TODO (AM) + Ok(SockMapFd(self.inner.borrow().fd_or_err()?.as_raw_fd())) } } diff --git a/aya/src/maps/sock/sock_map.rs b/aya/src/maps/sock/sock_map.rs index 732917de..b76fe2af 100644 --- a/aya/src/maps/sock/sock_map.rs +++ b/aya/src/maps/sock/sock_map.rs @@ -17,7 +17,7 @@ use crate::{ /// sockets. /// /// A `SockMap` can also be used to redirect packets to sockets contained by the -/// map using `bpf_redirect_map()`, `bpf_sk_redirect_map()` etc. +/// map using `bpf_redirect_map()`, `bpf_sk_redirect_map()` etc. /// /// # Minimum kernel version /// @@ -65,7 +65,8 @@ impl> SockMap { /// The returned file descriptor can be used to attach programs that work with /// socket maps, like [`SkMsg`](crate::programs::SkMsg) and [`SkSkb`](crate::programs::SkSkb). pub fn fd(&self) -> Result { - Ok(SockMapFd(self.inner.borrow().fd_or_err()?)) + // TODO (AM) + Ok(SockMapFd(self.inner.borrow().fd_or_err()?.as_raw_fd())) } } @@ -75,7 +76,8 @@ impl> SockMap { let data = self.inner.borrow_mut(); let fd = data.fd_or_err()?; check_bounds(data, index)?; - bpf_map_update_elem(fd, Some(&index), &socket.as_raw_fd(), flags).map_err( + // TODO (AM) + bpf_map_update_elem(fd.as_raw_fd(), Some(&index), &socket.as_raw_fd(), flags).map_err( |(_, io_error)| MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), io_error, @@ -89,7 +91,8 @@ impl> SockMap { let data = self.inner.borrow_mut(); let fd = data.fd_or_err()?; check_bounds(data, *index)?; - bpf_map_delete_elem(fd, index) + // TODO (AM) + bpf_map_delete_elem(fd.as_raw_fd(), index) .map(|_| ()) .map_err(|(_, io_error)| MapError::SyscallError { call: "bpf_map_delete_elem".to_owned(), diff --git a/aya/src/maps/stack.rs b/aya/src/maps/stack.rs index db428ddf..124b2d5e 100644 --- a/aya/src/maps/stack.rs +++ b/aya/src/maps/stack.rs @@ -2,6 +2,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsRawFd, }; use crate::{ @@ -64,7 +65,8 @@ impl, V: Pod> Stack { pub fn pop(&mut self, flags: u64) -> Result { let fd = self.inner.borrow().fd_or_err()?; - let value = bpf_map_lookup_and_delete_elem::(fd, None, flags).map_err( + // TODO (AM) + let value = bpf_map_lookup_and_delete_elem::(fd.as_raw_fd(), None, flags).map_err( |(_, io_error)| MapError::SyscallError { call: "bpf_map_lookup_and_delete_elem".to_owned(), io_error, @@ -80,12 +82,13 @@ impl, V: Pod> Stack { /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails. pub fn push(&mut self, value: impl Borrow, flags: u64) -> Result<(), MapError> { let fd = self.inner.borrow().fd_or_err()?; - bpf_map_update_elem(fd, None::<&u32>, value.borrow(), flags).map_err(|(_, io_error)| { - MapError::SyscallError { + // TODO (AM) + bpf_map_update_elem(fd.as_raw_fd(), None::<&u32>, value.borrow(), flags).map_err( + |(_, io_error)| MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), io_error, - } - })?; + }, + )?; Ok(()) } } diff --git a/aya/src/maps/stack_trace.rs b/aya/src/maps/stack_trace.rs index a8cce414..90121336 100644 --- a/aya/src/maps/stack_trace.rs +++ b/aya/src/maps/stack_trace.rs @@ -1,7 +1,9 @@ //! A hash map of kernel or user space stack traces. //! //! See [`StackTraceMap`] for documentation and examples. -use std::{borrow::Borrow, collections::BTreeMap, fs, io, mem, path::Path, str::FromStr}; +use std::{ + borrow::Borrow, collections::BTreeMap, fs, io, mem, os::fd::AsRawFd, path::Path, str::FromStr, +}; use crate::{ maps::{IterableMap, MapData, MapError, MapIter, MapKeys}, @@ -18,7 +20,7 @@ use crate::{ /// # Minimum kernel version /// /// The minimum kernel version required to use this feature is 4.6. -/// +/// /// # Examples /// /// ```no_run @@ -105,7 +107,8 @@ impl> StackTraceMap { let fd = self.inner.borrow().fd_or_err()?; let mut frames = vec![0; self.max_stack_depth]; - bpf_map_lookup_elem_ptr(fd, Some(stack_id), frames.as_mut_ptr(), flags) + // TODO (AM) + bpf_map_lookup_elem_ptr(fd.as_raw_fd(), Some(stack_id), frames.as_mut_ptr(), flags) .map_err(|(_, io_error)| MapError::SyscallError { call: "bpf_map_lookup_elem".to_owned(), io_error, diff --git a/aya/src/programs/cgroup_device.rs b/aya/src/programs/cgroup_device.rs index 9e1d94a9..143b9547 100644 --- a/aya/src/programs/cgroup_device.rs +++ b/aya/src/programs/cgroup_device.rs @@ -1,5 +1,5 @@ //! Cgroup device programs. -use std::os::fd::{AsRawFd, RawFd}; +use std::os::fd::AsRawFd; use crate::{ generated::{bpf_attach_type::BPF_CGROUP_DEVICE, bpf_prog_type::BPF_PROG_TYPE_CGROUP_DEVICE}, @@ -64,28 +64,31 @@ impl CgroupDevice { let k_ver = kernel_version().unwrap(); if k_ver >= (5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE, None, 0).map_err( - |(_, io_error)| ProgramError::SyscallError { - call: "bpf_link_create".to_owned(), - io_error, - }, - )? as RawFd; + // TODO (AM) + let link_fd = + bpf_link_create(prog_fd.as_raw_fd(), cgroup_fd, BPF_CGROUP_DEVICE, None, 0) + .map_err(|(_, io_error)| ProgramError::SyscallError { + call: "bpf_link_create".to_owned(), + io_error, + })?; self.data .links .insert(CgroupDeviceLink::new(CgroupDeviceLinkInner::Fd( FdLink::new(link_fd), ))) } else { - bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE).map_err(|(_, io_error)| { - ProgramError::SyscallError { + // TODO (AM) + bpf_prog_attach(prog_fd.as_raw_fd(), cgroup_fd, BPF_CGROUP_DEVICE).map_err( + |(_, io_error)| ProgramError::SyscallError { call: "bpf_prog_attach".to_owned(), io_error, - } - })?; + }, + )?; self.data .links .insert(CgroupDeviceLink::new(CgroupDeviceLinkInner::ProgAttach( - ProgAttachLink::new(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE), + // TODO (AM) + ProgAttachLink::new(prog_fd.as_raw_fd(), cgroup_fd, BPF_CGROUP_DEVICE), ))) } } diff --git a/aya/src/programs/cgroup_skb.rs b/aya/src/programs/cgroup_skb.rs index 558afadf..77e49307 100644 --- a/aya/src/programs/cgroup_skb.rs +++ b/aya/src/programs/cgroup_skb.rs @@ -1,9 +1,5 @@ //! Cgroup skb programs. -use std::{ - hash::Hash, - os::fd::{AsRawFd, RawFd}, - path::Path, -}; +use std::{hash::Hash, os::fd::AsRawFd, path::Path}; use crate::{ generated::{ @@ -98,29 +94,31 @@ impl CgroupSkb { }; let k_ver = kernel_version().unwrap(); if k_ver >= (5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err( - |(_, io_error)| ProgramError::SyscallError { + // TODO (AM) + let link_fd = bpf_link_create(prog_fd.as_raw_fd(), cgroup_fd, attach_type, None, 0) + .map_err(|(_, io_error)| ProgramError::SyscallError { call: "bpf_link_create".to_owned(), io_error, - }, - )? as RawFd; + })?; self.data .links .insert(CgroupSkbLink::new(CgroupSkbLinkInner::Fd(FdLink::new( link_fd, )))) } else { - bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| { - ProgramError::SyscallError { + // TODO (AM) + bpf_prog_attach(prog_fd.as_raw_fd(), cgroup_fd, attach_type).map_err( + |(_, io_error)| ProgramError::SyscallError { call: "bpf_prog_attach".to_owned(), io_error, - } - })?; + }, + )?; self.data .links .insert(CgroupSkbLink::new(CgroupSkbLinkInner::ProgAttach( - ProgAttachLink::new(prog_fd, cgroup_fd, attach_type), + // TODO (AM) + ProgAttachLink::new(prog_fd.as_raw_fd(), cgroup_fd, attach_type), ))) } } diff --git a/aya/src/programs/cgroup_sock.rs b/aya/src/programs/cgroup_sock.rs index f4a0b59b..16fdb3c9 100644 --- a/aya/src/programs/cgroup_sock.rs +++ b/aya/src/programs/cgroup_sock.rs @@ -1,11 +1,7 @@ //! Cgroup socket programs. pub use aya_obj::programs::CgroupSockAttachType; -use std::{ - hash::Hash, - os::fd::{AsRawFd, RawFd}, - path::Path, -}; +use std::{hash::Hash, os::fd::AsRawFd, path::Path}; use crate::{ generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCK, @@ -73,29 +69,31 @@ impl CgroupSock { let attach_type = self.data.expected_attach_type.unwrap(); let k_ver = kernel_version().unwrap(); if k_ver >= (5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err( - |(_, io_error)| ProgramError::SyscallError { + // TODO (AM) + let link_fd = bpf_link_create(prog_fd.as_raw_fd(), cgroup_fd, attach_type, None, 0) + .map_err(|(_, io_error)| ProgramError::SyscallError { call: "bpf_link_create".to_owned(), io_error, - }, - )? as RawFd; + })?; self.data .links .insert(CgroupSockLink::new(CgroupSockLinkInner::Fd(FdLink::new( link_fd, )))) } else { - bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| { - ProgramError::SyscallError { + // TODO (AM) + bpf_prog_attach(prog_fd.as_raw_fd(), cgroup_fd, attach_type).map_err( + |(_, io_error)| ProgramError::SyscallError { call: "bpf_prog_attach".to_owned(), io_error, - } - })?; + }, + )?; self.data .links .insert(CgroupSockLink::new(CgroupSockLinkInner::ProgAttach( - ProgAttachLink::new(prog_fd, cgroup_fd, attach_type), + // TODO (AM) + ProgAttachLink::new(prog_fd.as_raw_fd(), cgroup_fd, attach_type), ))) } } diff --git a/aya/src/programs/cgroup_sock_addr.rs b/aya/src/programs/cgroup_sock_addr.rs index cc2b3106..2116a041 100644 --- a/aya/src/programs/cgroup_sock_addr.rs +++ b/aya/src/programs/cgroup_sock_addr.rs @@ -1,11 +1,7 @@ //! Cgroup socket address programs. pub use aya_obj::programs::CgroupSockAddrAttachType; -use std::{ - hash::Hash, - os::fd::{AsRawFd, RawFd}, - path::Path, -}; +use std::{hash::Hash, os::fd::AsRawFd, path::Path}; use crate::{ generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCK_ADDR, @@ -74,28 +70,30 @@ impl CgroupSockAddr { let attach_type = self.data.expected_attach_type.unwrap(); let k_ver = kernel_version().unwrap(); if k_ver >= (5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err( - |(_, io_error)| ProgramError::SyscallError { + // TODO (AM) + let link_fd = bpf_link_create(prog_fd.as_raw_fd(), cgroup_fd, attach_type, None, 0) + .map_err(|(_, io_error)| ProgramError::SyscallError { call: "bpf_link_create".to_owned(), io_error, - }, - )? as RawFd; + })?; self.data .links .insert(CgroupSockAddrLink::new(CgroupSockAddrLinkInner::Fd( FdLink::new(link_fd), ))) } else { - bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| { - ProgramError::SyscallError { + // TODO (AM) + bpf_prog_attach(prog_fd.as_raw_fd(), cgroup_fd, attach_type).map_err( + |(_, io_error)| ProgramError::SyscallError { call: "bpf_prog_attach".to_owned(), io_error, - } - })?; + }, + )?; self.data.links.insert(CgroupSockAddrLink::new( CgroupSockAddrLinkInner::ProgAttach(ProgAttachLink::new( - prog_fd, + // TODO (AM) + prog_fd.as_raw_fd(), cgroup_fd, attach_type, )), diff --git a/aya/src/programs/cgroup_sockopt.rs b/aya/src/programs/cgroup_sockopt.rs index eff006e9..3ca526ad 100644 --- a/aya/src/programs/cgroup_sockopt.rs +++ b/aya/src/programs/cgroup_sockopt.rs @@ -1,11 +1,7 @@ //! Cgroup socket option programs. pub use aya_obj::programs::CgroupSockoptAttachType; -use std::{ - hash::Hash, - os::fd::{AsRawFd, RawFd}, - path::Path, -}; +use std::{hash::Hash, os::fd::AsRawFd, path::Path}; use crate::{ generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCKOPT, @@ -71,29 +67,31 @@ impl CgroupSockopt { let attach_type = self.data.expected_attach_type.unwrap(); let k_ver = kernel_version().unwrap(); if k_ver >= (5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, None, 0).map_err( - |(_, io_error)| ProgramError::SyscallError { + // TODO (AM) + let link_fd = bpf_link_create(prog_fd.as_raw_fd(), cgroup_fd, attach_type, None, 0) + .map_err(|(_, io_error)| ProgramError::SyscallError { call: "bpf_link_create".to_owned(), io_error, - }, - )? as RawFd; + })?; self.data .links .insert(CgroupSockoptLink::new(CgroupSockoptLinkInner::Fd( FdLink::new(link_fd), ))) } else { - bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| { - ProgramError::SyscallError { + // TODO (AM) + bpf_prog_attach(prog_fd.as_raw_fd(), cgroup_fd, attach_type).map_err( + |(_, io_error)| ProgramError::SyscallError { call: "bpf_prog_attach".to_owned(), io_error, - } - })?; + }, + )?; self.data .links .insert(CgroupSockoptLink::new(CgroupSockoptLinkInner::ProgAttach( - ProgAttachLink::new(prog_fd, cgroup_fd, attach_type), + // TODO (AM) + ProgAttachLink::new(prog_fd.as_raw_fd(), cgroup_fd, attach_type), ))) } } diff --git a/aya/src/programs/cgroup_sysctl.rs b/aya/src/programs/cgroup_sysctl.rs index 81fd7a6b..ebc85df4 100644 --- a/aya/src/programs/cgroup_sysctl.rs +++ b/aya/src/programs/cgroup_sysctl.rs @@ -1,8 +1,5 @@ //! Cgroup sysctl programs. -use std::{ - hash::Hash, - os::fd::{AsRawFd, RawFd}, -}; +use std::{hash::Hash, os::fd::AsRawFd}; use crate::{ generated::{bpf_attach_type::BPF_CGROUP_SYSCTL, bpf_prog_type::BPF_PROG_TYPE_CGROUP_SYSCTL}, @@ -66,29 +63,32 @@ impl CgroupSysctl { let k_ver = kernel_version().unwrap(); if k_ver >= (5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL, None, 0).map_err( - |(_, io_error)| ProgramError::SyscallError { - call: "bpf_link_create".to_owned(), - io_error, - }, - )? as RawFd; + // TODO (AM) + let link_fd = + bpf_link_create(prog_fd.as_raw_fd(), cgroup_fd, BPF_CGROUP_SYSCTL, None, 0) + .map_err(|(_, io_error)| ProgramError::SyscallError { + call: "bpf_link_create".to_owned(), + io_error, + })?; self.data .links .insert(CgroupSysctlLink::new(CgroupSysctlLinkInner::Fd( FdLink::new(link_fd), ))) } else { - bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL).map_err(|(_, io_error)| { - ProgramError::SyscallError { + // TODO (AM) + bpf_prog_attach(prog_fd.as_raw_fd(), cgroup_fd, BPF_CGROUP_SYSCTL).map_err( + |(_, io_error)| ProgramError::SyscallError { call: "bpf_prog_attach".to_owned(), io_error, - } - })?; + }, + )?; self.data .links .insert(CgroupSysctlLink::new(CgroupSysctlLinkInner::ProgAttach( - ProgAttachLink::new(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL), + // TODO (AM) + ProgAttachLink::new(prog_fd.as_raw_fd(), cgroup_fd, BPF_CGROUP_SYSCTL), ))) } } diff --git a/aya/src/programs/extension.rs b/aya/src/programs/extension.rs index aaff4b61..25862466 100644 --- a/aya/src/programs/extension.rs +++ b/aya/src/programs/extension.rs @@ -42,9 +42,11 @@ pub enum ExtensionError { /// prog.attach("eth0", XdpFlags::default())?; /// /// let prog_fd = prog.fd().unwrap(); -/// let ext: &mut Extension = bpf.program_mut("extension").unwrap().try_into()?; -/// ext.load(prog_fd, "function_to_replace")?; -/// ext.attach()?; +/// // TODO (AM): can't borrow here becauase prog_fd is holding a reference already +/// // need to confirm what the API wants to be +/// // let ext: &mut Extension = bpf.program_mut("extension").unwrap().try_into()?; +/// // ext.load(prog_fd, "function_to_replace")?; +/// // ext.attach()?; /// Ok::<(), aya::BpfError>(()) /// ``` #[derive(Debug)] @@ -90,11 +92,18 @@ impl Extension { let target_fd = self.data.attach_prog_fd.ok_or(ProgramError::NotLoaded)?; let btf_id = self.data.attach_btf_id.ok_or(ProgramError::NotLoaded)?; // the attach type must be set as 0, which is bpf_attach_type::BPF_CGROUP_INET_INGRESS - let link_fd = bpf_link_create(prog_fd, target_fd, BPF_CGROUP_INET_INGRESS, Some(btf_id), 0) - .map_err(|(_, io_error)| ProgramError::SyscallError { - call: "bpf_link_create".to_owned(), - io_error, - })? as RawFd; + // TODO (AM) + let link_fd = bpf_link_create( + prog_fd.as_raw_fd(), + target_fd, + BPF_CGROUP_INET_INGRESS, + Some(btf_id), + 0, + ) + .map_err(|(_, io_error)| ProgramError::SyscallError { + call: "bpf_link_create".to_owned(), + io_error, + })?; self.data .links .insert(ExtensionLink::new(FdLink::new(link_fd))) @@ -120,11 +129,18 @@ impl Extension { let (_, btf_id) = get_btf_info(target_fd, func_name)?; let prog_fd = self.data.fd_or_err()?; // the attach type must be set as 0, which is bpf_attach_type::BPF_CGROUP_INET_INGRESS - let link_fd = bpf_link_create(prog_fd, target_fd, BPF_CGROUP_INET_INGRESS, Some(btf_id), 0) - .map_err(|(_, io_error)| ProgramError::SyscallError { - call: "bpf_link_create".to_owned(), - io_error, - })? as RawFd; + // TODO (AM) + let link_fd = bpf_link_create( + prog_fd.as_raw_fd(), + target_fd, + BPF_CGROUP_INET_INGRESS, + Some(btf_id), + 0, + ) + .map_err(|(_, io_error)| ProgramError::SyscallError { + call: "bpf_link_create".to_owned(), + io_error, + })?; self.data .links .insert(ExtensionLink::new(FdLink::new(link_fd))) diff --git a/aya/src/programs/links.rs b/aya/src/programs/links.rs index 86017b15..bd6a72ea 100644 --- a/aya/src/programs/links.rs +++ b/aya/src/programs/links.rs @@ -6,7 +6,7 @@ use std::{ collections::{hash_map::Entry, HashMap}, ffi::CString, io, - os::fd::RawFd, + os::fd::{AsRawFd, OwnedFd, RawFd}, path::{Path, PathBuf}, }; @@ -84,11 +84,11 @@ pub struct FdLinkId(pub(crate) RawFd); /// A file descriptor link. #[derive(Debug)] pub struct FdLink { - pub(crate) fd: RawFd, + pub(crate) fd: OwnedFd, } impl FdLink { - pub(crate) fn new(fd: RawFd) -> FdLink { + pub(crate) fn new(fd: OwnedFd) -> FdLink { FdLink { fd } } @@ -128,9 +128,12 @@ impl FdLink { error: e.to_string(), } })?; - bpf_pin_object(self.fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError { - name: "BPF_OBJ_PIN".to_string(), - io_error, + // TODO (AM) + bpf_pin_object(self.fd.as_raw_fd(), &path_string).map_err(|(_, io_error)| { + PinError::SyscallError { + name: "BPF_OBJ_PIN".to_string(), + io_error, + } })?; Ok(PinnedLink::new(PathBuf::from(path.as_ref()), self)) } @@ -140,7 +143,8 @@ impl Link for FdLink { type Id = FdLinkId; fn id(&self) -> Self::Id { - FdLinkId(self.fd) + // TODO (AM) + FdLinkId(self.fd.as_raw_fd()) } fn detach(self) -> Result<(), ProgramError> { @@ -159,12 +163,6 @@ impl From for FdLink { } } -impl Drop for FdLink { - fn drop(&mut self) { - unsafe { close(self.fd) }; - } -} - /// A pinned file descriptor link. /// /// This link has been pinned to the BPF filesystem. On drop, the file descriptor that backs @@ -189,7 +187,7 @@ impl PinnedLink { call: "BPF_OBJ_GET".to_string(), code, io_error, - })? as RawFd; + })?; Ok(PinnedLink::new( path.as_ref().to_path_buf(), FdLink::new(fd), @@ -329,7 +327,7 @@ pub enum LinkError { #[cfg(test)] mod tests { - use std::{cell::RefCell, env, fs::File, mem, os::unix::io::AsRawFd, rc::Rc}; + use std::{cell::RefCell, env, fs::File, rc::Rc}; use crate::{programs::ProgramError, sys::override_syscall}; @@ -469,10 +467,7 @@ mod tests { fn test_pin() { let dir = env::temp_dir(); let f1 = File::create(dir.join("f1")).expect("unable to create file in tmpdir"); - let fd_link = FdLink::new(f1.as_raw_fd()); - - // leak the fd, it will get closed when our pinned link is dropped - mem::forget(f1); + let fd_link = FdLink::new(f1.into()); // override syscall to allow for pin to happen in our tmpdir override_syscall(|_| Ok(0)); diff --git a/aya/src/programs/lirc_mode2.rs b/aya/src/programs/lirc_mode2.rs index 98f348b3..60b3829b 100644 --- a/aya/src/programs/lirc_mode2.rs +++ b/aya/src/programs/lirc_mode2.rs @@ -64,14 +64,18 @@ impl LircMode2 { let prog_fd = self.data.fd_or_err()?; let lircdev_fd = lircdev.as_raw_fd(); - bpf_prog_attach(prog_fd, lircdev_fd, BPF_LIRC_MODE2).map_err(|(_, io_error)| { - ProgramError::SyscallError { + // TODO (AM) + bpf_prog_attach(prog_fd.as_raw_fd(), lircdev_fd, BPF_LIRC_MODE2).map_err( + |(_, io_error)| ProgramError::SyscallError { call: "bpf_prog_attach".to_owned(), io_error, - } - })?; + }, + )?; - self.data.links.insert(LircLink::new(prog_fd, lircdev_fd)) + // TODO (AM) + self.data + .links + .insert(LircLink::new(prog_fd.as_raw_fd(), lircdev_fd)) } /// Detaches the program. diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 561b3a1a..6419ce76 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -68,7 +68,10 @@ use libc::ENOSPC; use std::{ ffi::CString, io, - os::unix::io::{AsRawFd, RawFd}, + os::{ + fd::{AsFd, BorrowedFd, OwnedFd}, + unix::io::{AsRawFd, RawFd}, + }, path::{Path, PathBuf}, }; use thiserror::Error; @@ -215,11 +218,17 @@ pub enum ProgramError { /// A [`Program`] file descriptor. #[derive(Copy, Clone)] -pub struct ProgramFd(RawFd); +pub struct ProgramFd<'f>(BorrowedFd<'f>); -impl AsRawFd for ProgramFd { +impl AsRawFd for ProgramFd<'_> { fn as_raw_fd(&self) -> RawFd { - self.0 + self.0.as_raw_fd() + } +} + +impl AsFd for ProgramFd<'_> { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() } } @@ -406,7 +415,7 @@ impl Program { pub(crate) struct ProgramData { pub(crate) name: Option, pub(crate) obj: Option<(obj::Program, obj::Function)>, - pub(crate) fd: Option, + pub(crate) fd: Option, pub(crate) links: LinkMap, pub(crate) expected_attach_type: Option, pub(crate) attach_btf_obj_fd: Option, @@ -443,7 +452,7 @@ impl ProgramData { pub(crate) fn from_bpf_prog_info( name: Option, - fd: RawFd, + fd: OwnedFd, path: &Path, info: bpf_prog_info, ) -> Result, ProgramError> { @@ -489,11 +498,14 @@ impl ProgramData { bpf_get_object(&path_string).map_err(|(_, io_error)| ProgramError::SyscallError { call: "bpf_obj_get".to_owned(), io_error, - })? as RawFd; + })?; - let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| ProgramError::SyscallError { - call: "bpf_prog_get_info_by_fd".to_owned(), - io_error, + // TODO: AM + let info = bpf_prog_get_info_by_fd(fd.as_raw_fd()).map_err(|io_error| { + ProgramError::SyscallError { + call: "bpf_prog_get_info_by_fd".to_owned(), + io_error, + } })?; let info = ProgramInfo(info); @@ -503,8 +515,11 @@ impl ProgramData { } impl ProgramData { - fn fd_or_err(&self) -> Result { - self.fd.ok_or(ProgramError::NotLoaded) + fn fd_or_err(&self) -> Result, ProgramError> { + self.fd + .as_ref() + .map(|f| f.as_fd()) + .ok_or(ProgramError::NotLoaded) } pub(crate) fn take_link(&mut self, link_id: T::Id) -> Result { @@ -514,10 +529,7 @@ impl ProgramData { fn unload_program(data: &mut ProgramData) -> Result<(), ProgramError> { data.links.remove_all()?; - let fd = data.fd.take().ok_or(ProgramError::NotLoaded)?; - unsafe { - libc::close(fd); - } + let _ = data.fd.take().ok_or(ProgramError::NotLoaded)?; Ok(()) } @@ -525,7 +537,7 @@ fn pin_program>( data: &mut ProgramData, path: P, ) -> Result<(), PinError> { - let fd = data.fd.ok_or(PinError::NoFd { + let fd = data.fd.as_ref().map(|f| f.as_fd()).ok_or(PinError::NoFd { name: data .name .as_ref() @@ -537,9 +549,12 @@ fn pin_program>( error: e.to_string(), } })?; - bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError { - name: "BPF_OBJ_PIN".to_string(), - io_error, + // TODO (AM) + bpf_pin_object(fd.as_raw_fd(), &path_string).map_err(|(_, io_error)| { + PinError::SyscallError { + name: "BPF_OBJ_PIN".to_string(), + io_error, + } })?; Ok(()) } @@ -620,7 +635,7 @@ fn load_program( match ret { Ok(prog_fd) => { - *fd = Some(prog_fd as RawFd); + *fd = Some(prog_fd); Ok(()) } Err((_, io_error)) => { @@ -729,8 +744,8 @@ macro_rules! impl_fd { $( impl $struct_name { /// Returns the file descriptor of this Program. - pub fn fd(&self) -> Option { - self.data.fd.map(|fd| ProgramFd(fd)) + pub fn fd(&self) -> Option> { + self.data.fd.as_ref().map(|fd| ProgramFd(fd.as_fd())) } } )+ @@ -961,15 +976,16 @@ impl ProgramInfo { bpf_get_object(&path_string).map_err(|(_, io_error)| ProgramError::SyscallError { call: "BPF_OBJ_GET".to_owned(), io_error, - })? as RawFd; + })?; - let info = bpf_prog_get_info_by_fd(fd).map_err(|io_error| ProgramError::SyscallError { - call: "bpf_prog_get_info_by_fd".to_owned(), - io_error, + // TODO (AM) + let info = bpf_prog_get_info_by_fd(fd.as_raw_fd()).map_err(|io_error| { + ProgramError::SyscallError { + call: "bpf_prog_get_info_by_fd".to_owned(), + io_error, + } })?; - unsafe { - libc::close(fd); - } + Ok(ProgramInfo(info)) } } diff --git a/aya/src/programs/perf_attach.rs b/aya/src/programs/perf_attach.rs index fe4fafe3..3fb1861e 100644 --- a/aya/src/programs/perf_attach.rs +++ b/aya/src/programs/perf_attach.rs @@ -80,7 +80,7 @@ pub(crate) fn perf_attach(prog_fd: RawFd, fd: RawFd) -> Result>( if k_ver < (4, 17, 0) { let (fd, event_alias) = create_as_trace_point(kind, fn_name, offset, pid)?; let link = T::from(perf_attach_debugfs( - program_data.fd_or_err()?, + // TODO (AM) + program_data.fd_or_err()?.as_raw_fd(), fd, kind, event_alias, @@ -62,7 +64,8 @@ pub(crate) fn attach>( }; let fd = create_as_probe(kind, fn_name, offset, pid)?; - let link = T::from(perf_attach(program_data.fd_or_err()?, fd)?); + // TODO (AM) + let link = T::from(perf_attach(program_data.fd_or_err()?.as_raw_fd(), fd)?); program_data.links.insert(link) } diff --git a/aya/src/programs/sk_lookup.rs b/aya/src/programs/sk_lookup.rs index 8230a81e..7031ccc6 100644 --- a/aya/src/programs/sk_lookup.rs +++ b/aya/src/programs/sk_lookup.rs @@ -1,4 +1,4 @@ -use std::os::fd::{AsRawFd, RawFd}; +use std::os::fd::AsRawFd; use crate::{ generated::{bpf_attach_type::BPF_SK_LOOKUP, bpf_prog_type::BPF_PROG_TYPE_SK_LOOKUP}, @@ -64,12 +64,12 @@ impl SkLookup { let prog_fd = self.data.fd_or_err()?; let netns_fd = netns.as_raw_fd(); - let link_fd = bpf_link_create(prog_fd, netns_fd, BPF_SK_LOOKUP, None, 0).map_err( - |(_, io_error)| ProgramError::SyscallError { + // TODO (AM) + let link_fd = bpf_link_create(prog_fd.as_raw_fd(), netns_fd, BPF_SK_LOOKUP, None, 0) + .map_err(|(_, io_error)| ProgramError::SyscallError { call: "bpf_link_create".to_owned(), io_error, - }, - )? as RawFd; + })?; self.data .links .insert(SkLookupLink::new(FdLink::new(link_fd))) diff --git a/aya/src/programs/sk_msg.rs b/aya/src/programs/sk_msg.rs index a60346d8..6bc57406 100644 --- a/aya/src/programs/sk_msg.rs +++ b/aya/src/programs/sk_msg.rs @@ -82,14 +82,16 @@ impl SkMsg { let prog_fd = self.data.fd_or_err()?; let map_fd = map.as_raw_fd(); - bpf_prog_attach(prog_fd, map_fd, BPF_SK_MSG_VERDICT).map_err(|(_, io_error)| { - ProgramError::SyscallError { + // TODO (AM) + bpf_prog_attach(prog_fd.as_raw_fd(), map_fd, BPF_SK_MSG_VERDICT).map_err( + |(_, io_error)| ProgramError::SyscallError { call: "bpf_prog_attach".to_owned(), io_error, - } - })?; + }, + )?; self.data.links.insert(SkMsgLink::new(ProgAttachLink::new( - prog_fd, + // TODO (AM) + prog_fd.as_raw_fd(), map_fd, BPF_SK_MSG_VERDICT, ))) diff --git a/aya/src/programs/sk_skb.rs b/aya/src/programs/sk_skb.rs index 34aade6d..5e271b80 100644 --- a/aya/src/programs/sk_skb.rs +++ b/aya/src/programs/sk_skb.rs @@ -78,14 +78,16 @@ impl SkSkb { SkSkbKind::StreamParser => BPF_SK_SKB_STREAM_PARSER, SkSkbKind::StreamVerdict => BPF_SK_SKB_STREAM_VERDICT, }; - bpf_prog_attach(prog_fd, map_fd, attach_type).map_err(|(_, io_error)| { + // TODO (AM) + bpf_prog_attach(prog_fd.as_raw_fd(), map_fd, attach_type).map_err(|(_, io_error)| { ProgramError::SyscallError { call: "bpf_prog_attach".to_owned(), io_error, } })?; + // TODO (AM) self.data.links.insert(SkSkbLink::new(ProgAttachLink::new( - prog_fd, + prog_fd.as_raw_fd(), map_fd, attach_type, ))) diff --git a/aya/src/programs/sock_ops.rs b/aya/src/programs/sock_ops.rs index 9021b312..ca34daf0 100644 --- a/aya/src/programs/sock_ops.rs +++ b/aya/src/programs/sock_ops.rs @@ -62,14 +62,16 @@ impl SockOps { let prog_fd = self.data.fd_or_err()?; let cgroup_fd = cgroup.as_raw_fd(); - bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SOCK_OPS).map_err(|(_, io_error)| { - ProgramError::SyscallError { + // TODO (AM) + bpf_prog_attach(prog_fd.as_raw_fd(), cgroup_fd, BPF_CGROUP_SOCK_OPS).map_err( + |(_, io_error)| ProgramError::SyscallError { call: "bpf_prog_attach".to_owned(), io_error, - } - })?; + }, + )?; + // TODO (AM) self.data.links.insert(SockOpsLink::new(ProgAttachLink::new( - prog_fd, + prog_fd.as_raw_fd(), cgroup_fd, BPF_CGROUP_SOCK_OPS, ))) diff --git a/aya/src/programs/socket_filter.rs b/aya/src/programs/socket_filter.rs index 920052d0..84ab6818 100644 --- a/aya/src/programs/socket_filter.rs +++ b/aya/src/programs/socket_filter.rs @@ -92,6 +92,8 @@ impl SocketFilter { .into()); } + // TODO (AM) + let prog_fd = prog_fd.as_raw_fd(); self.data.links.insert(SocketFilterLink { socket, prog_fd }) } diff --git a/aya/src/programs/tc.rs b/aya/src/programs/tc.rs index ad86b65c..1528ce43 100644 --- a/aya/src/programs/tc.rs +++ b/aya/src/programs/tc.rs @@ -4,6 +4,7 @@ use thiserror::Error; use std::{ ffi::{CStr, CString}, io, + os::fd::AsRawFd, path::Path, }; @@ -158,7 +159,8 @@ impl SchedClassifier { netlink_qdisc_attach( if_index as i32, &attach_type, - prog_fd, + // TODO (AM) + prog_fd.as_raw_fd(), &self.name, options.priority, options.handle, diff --git a/aya/src/programs/trace_point.rs b/aya/src/programs/trace_point.rs index f43cd77e..ff112122 100644 --- a/aya/src/programs/trace_point.rs +++ b/aya/src/programs/trace_point.rs @@ -1,5 +1,5 @@ //! Tracepoint programs. -use std::{fs, io, path::Path}; +use std::{fs, io, os::fd::AsRawFd, path::Path}; use thiserror::Error; use crate::{ @@ -87,7 +87,8 @@ impl TracePoint { } })? as i32; - let link = perf_attach(self.data.fd_or_err()?, fd)?; + // TODO (AM) + let link = perf_attach(self.data.fd_or_err()?.as_raw_fd(), fd)?; self.data.links.insert(TracePointLink::new(link)) } diff --git a/aya/src/programs/utils.rs b/aya/src/programs/utils.rs index 4a12d0a5..3d7befd7 100644 --- a/aya/src/programs/utils.rs +++ b/aya/src/programs/utils.rs @@ -1,5 +1,5 @@ //! Common functions shared between multiple eBPF program types. -use std::{ffi::CStr, io, os::unix::io::RawFd, path::Path}; +use std::{ffi::CStr, io, os::fd::AsRawFd, path::Path}; use crate::{ programs::{FdLink, Link, ProgramData, ProgramError}, @@ -13,12 +13,14 @@ pub(crate) fn attach_raw_tracepoint>( ) -> Result { let prog_fd = program_data.fd_or_err()?; - let pfd = bpf_raw_tracepoint_open(tp_name, prog_fd).map_err(|(_code, io_error)| { - ProgramError::SyscallError { - call: "bpf_raw_tracepoint_open".to_owned(), - io_error, - } - })? as RawFd; + // TODO (AM) + let pfd = + bpf_raw_tracepoint_open(tp_name, prog_fd.as_raw_fd()).map_err(|(_code, io_error)| { + ProgramError::SyscallError { + call: "bpf_raw_tracepoint_open".to_owned(), + io_error, + } + })?; program_data.links.insert(FdLink::new(pfd).into()) } diff --git a/aya/src/programs/xdp.rs b/aya/src/programs/xdp.rs index 1fad9da1..e2177cdb 100644 --- a/aya/src/programs/xdp.rs +++ b/aya/src/programs/xdp.rs @@ -1,7 +1,13 @@ //! eXpress Data Path (XDP) programs. use bitflags; use libc::if_nametoindex; -use std::{convert::TryFrom, ffi::CString, hash::Hash, io, mem, os::unix::io::RawFd}; +use std::{ + convert::TryFrom, + ffi::CString, + hash::Hash, + io, + os::{fd::AsRawFd, unix::io::RawFd}, +}; use thiserror::Error; use crate::{ @@ -128,19 +134,23 @@ impl Xdp { let k_ver = kernel_version().unwrap(); if k_ver >= (5, 9, 0) { - let link_fd = bpf_link_create(prog_fd, if_index, BPF_XDP, None, flags.bits()).map_err( - |(_, io_error)| ProgramError::SyscallError { - call: "bpf_link_create".to_owned(), - io_error, - }, - )? as RawFd; + // TODO (AM) + let link_fd = + bpf_link_create(prog_fd.as_raw_fd(), if_index, BPF_XDP, None, flags.bits()) + .map_err(|(_, io_error)| ProgramError::SyscallError { + call: "bpf_link_create".to_owned(), + io_error, + })?; self.data .links .insert(XdpLink::new(XdpLinkInner::FdLink(FdLink::new(link_fd)))) } else { - unsafe { netlink_set_xdp_fd(if_index, prog_fd, None, flags.bits()) } + // TODO (AM) + unsafe { netlink_set_xdp_fd(if_index, prog_fd.as_raw_fd(), None, flags.bits()) } .map_err(|io_error| XdpError::NetlinkError { io_error })?; + // TODO (AM) + let prog_fd = prog_fd.as_raw_fd(); self.data .links .insert(XdpLink::new(XdpLinkInner::NlLink(NlLink { @@ -171,20 +181,19 @@ impl Xdp { /// Ownership of the link will transfer to this program. pub fn attach_to_link(&mut self, link: XdpLink) -> Result { let prog_fd = self.data.fd_or_err()?; - match link.inner() { + + match link.into_inner() { XdpLinkInner::FdLink(fd_link) => { - let link_fd = fd_link.fd; - bpf_link_update(link_fd, prog_fd, None, 0).map_err(|(_, io_error)| { - ProgramError::SyscallError { + // TODO (AM) + bpf_link_update(fd_link.fd.as_raw_fd(), prog_fd.as_raw_fd(), None, 0).map_err( + |(_, io_error)| ProgramError::SyscallError { call: "bpf_link_update".to_string(), io_error, - } - })?; - // dispose of link and avoid detach on drop - mem::forget(link); + }, + )?; self.data .links - .insert(XdpLink::new(XdpLinkInner::FdLink(FdLink::new(link_fd)))) + .insert(XdpLink::new(XdpLinkInner::FdLink(FdLink::new(fd_link.fd)))) } XdpLinkInner::NlLink(nl_link) => { let if_index = nl_link.if_index; @@ -192,11 +201,17 @@ impl Xdp { let flags = nl_link.flags; let replace_flags = flags | XdpFlags::REPLACE; unsafe { - netlink_set_xdp_fd(if_index, prog_fd, Some(old_prog_fd), replace_flags.bits()) - .map_err(|io_error| XdpError::NetlinkError { io_error })?; + // TODO (AM) + netlink_set_xdp_fd( + if_index, + prog_fd.as_raw_fd(), + Some(old_prog_fd), + replace_flags.bits(), + ) + .map_err(|io_error| XdpError::NetlinkError { io_error })?; } - // dispose of link and avoid detach on drop - mem::forget(link); + // TODO (AM) + let prog_fd = prog_fd.as_raw_fd(); self.data .links .insert(XdpLink::new(XdpLinkInner::NlLink(NlLink { @@ -209,6 +224,7 @@ impl Xdp { } } +// TODO (AM): implement Drop to force detach? #[derive(Debug)] pub(crate) struct NlLink { if_index: i32, @@ -283,7 +299,8 @@ impl TryFrom for XdpLink { fn try_from(fd_link: FdLink) -> Result { // unwrap of fd_link.fd will not panic since it's only None when being dropped. let info = - bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| LinkError::SyscallError { + // TODO (AM) + bpf_link_get_info_by_fd(fd_link.fd.as_raw_fd()).map_err(|io_error| LinkError::SyscallError { call: "BPF_OBJ_GET_INFO_BY_FD".to_string(), code: 0, io_error, diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index 1b486840..20ed10a4 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -3,7 +3,10 @@ use std::{ ffi::{CStr, CString}, io, mem::{self, MaybeUninit}, - os::unix::io::RawFd, + os::{ + fd::{AsRawFd, FromRawFd, OwnedFd}, + unix::io::RawFd, + }, slice, }; @@ -34,7 +37,11 @@ use crate::{ type Result = std::result::Result; -pub(crate) fn bpf_create_map(name: &CStr, def: &obj::Map, btf_fd: Option) -> SysResult { +pub(crate) fn bpf_create_map( + name: &CStr, + def: &obj::Map, + btf_fd: Option, +) -> Result { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_1 }; @@ -88,7 +95,9 @@ pub(crate) fn bpf_create_map(name: &CStr, def: &obj::Map, btf_fd: Option) .copy_from_slice(unsafe { slice::from_raw_parts(name.as_ptr(), name_len) }); } - sys_bpf(bpf_cmd::BPF_MAP_CREATE, &attr) + let fd = sys_bpf(bpf_cmd::BPF_MAP_CREATE, &attr)? as RawFd; + // SAFETY: BPF_MAP_CREATE creates a new file descriptor + Ok(unsafe { OwnedFd::from_raw_fd(fd) }) } pub(crate) fn bpf_pin_object(fd: RawFd, path: &CStr) -> SysResult { @@ -99,11 +108,13 @@ pub(crate) fn bpf_pin_object(fd: RawFd, path: &CStr) -> SysResult { sys_bpf(bpf_cmd::BPF_OBJ_PIN, &attr) } -pub(crate) fn bpf_get_object(path: &CStr) -> SysResult { +pub(crate) fn bpf_get_object(path: &CStr) -> Result { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_4 }; u.pathname = path.as_ptr() as u64; - sys_bpf(bpf_cmd::BPF_OBJ_GET, &attr) + let fd = sys_bpf(bpf_cmd::BPF_OBJ_GET, &attr)? as RawFd; + // SAFETY: BPF_OBJ_GET creates a new file descriptor + Ok(unsafe { OwnedFd::from_raw_fd(fd) }) } pub(crate) struct BpfLoadProgramAttrs<'a> { @@ -128,7 +139,7 @@ pub(crate) fn bpf_load_program( aya_attr: &BpfLoadProgramAttrs, logger: &mut VerifierLog, verifier_log_level: u32, -) -> SysResult { +) -> Result { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_3 }; @@ -187,7 +198,9 @@ pub(crate) fn bpf_load_program( if let Some(v) = aya_attr.attach_btf_id { u.attach_btf_id = v; } - sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr) + let fd = sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr)? as RawFd; + // SAFETY: BPF_PROG_LOAD returns a new fd + Ok(unsafe { OwnedFd::from_raw_fd(fd) }) } fn lookup( @@ -366,7 +379,7 @@ pub(crate) fn bpf_link_create( attach_type: bpf_attach_type, btf_id: Option, flags: u32, -) -> SysResult { +) -> Result { let mut attr = unsafe { mem::zeroed::() }; attr.link_create.__bindgen_anon_1.prog_fd = prog_fd as u32; @@ -377,7 +390,9 @@ pub(crate) fn bpf_link_create( attr.link_create.__bindgen_anon_3.target_btf_id = btf_id; } - sys_bpf(bpf_cmd::BPF_LINK_CREATE, &attr) + let fd = sys_bpf(bpf_cmd::BPF_LINK_CREATE, &attr)? as RawFd; + // Safety: BPF_LINK_CREATE returns a new file descriptor + Ok(unsafe { OwnedFd::from_raw_fd(fd) }) } // since kernel 5.7 @@ -528,7 +543,7 @@ pub(crate) fn btf_obj_get_info_by_fd(prog_fd: RawFd, buf: &mut [u8]) -> io::Resu } } -pub(crate) fn bpf_raw_tracepoint_open(name: Option<&CStr>, prog_fd: RawFd) -> SysResult { +pub(crate) fn bpf_raw_tracepoint_open(name: Option<&CStr>, prog_fd: RawFd) -> Result { let mut attr = unsafe { mem::zeroed::() }; attr.raw_tracepoint.name = match name { @@ -537,7 +552,9 @@ pub(crate) fn bpf_raw_tracepoint_open(name: Option<&CStr>, prog_fd: RawFd) -> Sy }; attr.raw_tracepoint.prog_fd = prog_fd as u32; - sys_bpf(bpf_cmd::BPF_RAW_TRACEPOINT_OPEN, &attr) + let fd = sys_bpf(bpf_cmd::BPF_RAW_TRACEPOINT_OPEN, &attr)? as RawFd; + // Safety: BPF_RAW_TRACEPOINT_OPEN returns a new fd + Ok(unsafe { OwnedFd::from_raw_fd(fd) }) } pub(crate) fn bpf_load_btf(raw_btf: &[u8], log: &mut VerifierLog) -> SysResult { @@ -694,22 +711,27 @@ pub(crate) fn is_bpf_global_data_supported() -> bool { btf_fd: None, }; - if let Ok(map_fd) = map_data.create("aya_global") { - insns[0].imm = map_fd; + if map_data.create("aya_global").is_err() { + return false; + } - let gpl = b"GPL\0"; - u.license = gpl.as_ptr() as u64; - u.insn_cnt = insns.len() as u32; - u.insns = insns.as_ptr() as u64; - u.prog_type = bpf_prog_type::BPF_PROG_TYPE_SOCKET_FILTER as u32; + // OK: we just created this fd + let map_fd = map_data.fd.as_ref().unwrap(); - if let Ok(v) = sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr) { - let fd = v as RawFd; + insns[0].imm = map_fd.as_raw_fd(); - unsafe { close(fd) }; + let gpl = b"GPL\0"; + u.license = gpl.as_ptr() as u64; + u.insn_cnt = insns.len() as u32; + u.insns = insns.as_ptr() as u64; + u.prog_type = bpf_prog_type::BPF_PROG_TYPE_SOCKET_FILTER as u32; - return true; - } + if let Ok(v) = sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr) { + let fd = v as RawFd; + + unsafe { close(fd) }; + + return true; } false @@ -982,14 +1004,11 @@ pub(crate) fn bpf_prog_get_next_id(id: u32) -> Result> { } } -pub(crate) fn retry_with_verifier_logs( +pub(crate) fn retry_with_verifier_logs( max_retries: usize, log: &mut VerifierLog, - f: F, -) -> SysResult -where - F: Fn(&mut VerifierLog) -> SysResult, -{ + f: impl Fn(&mut VerifierLog) -> Result, +) -> Result { // 1. Try the syscall let ret = f(log); if ret.is_ok() {