Browse Source

Merge pull request #770 from aya-rs/mapfd-is-owned

maps: `MapFd` and `SockMapFd` are owned
Tamir Duberstein 1 year ago
parent
commit
41d01f638b

+ 6 - 0
aya-obj/src/lib.rs

@@ -77,6 +77,12 @@ mod std {
         pub use core_error::Error;
     }
     pub use core::*;
+
+    pub mod os {
+        pub mod fd {
+            pub type RawFd = core::ffi::c_int;
+        }
+    }
 }
 
 pub mod btf;

+ 3 - 3
aya-obj/src/relocation.rs

@@ -105,7 +105,7 @@ pub(crate) struct Symbol {
 
 impl Object {
     /// Relocates the map references
-    pub fn relocate_maps<'a, I: Iterator<Item = (&'a str, i32, &'a Map)>>(
+    pub fn relocate_maps<'a, I: Iterator<Item = (&'a str, std::os::fd::RawFd, &'a Map)>>(
         &mut self,
         maps: I,
         text_sections: &HashSet<usize>,
@@ -178,8 +178,8 @@ impl Object {
 fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
     fun: &mut Function,
     relocations: I,
-    maps_by_section: &HashMap<usize, (&str, i32, &Map)>,
-    maps_by_symbol: &HashMap<usize, (&str, i32, &Map)>,
+    maps_by_section: &HashMap<usize, (&str, std::os::fd::RawFd, &Map)>,
+    maps_by_symbol: &HashMap<usize, (&str, std::os::fd::RawFd, &Map)>,
     symbol_table: &HashMap<usize, Symbol>,
     text_sections: &HashSet<usize>,
 ) -> Result<(), RelocationError> {

+ 9 - 26
aya/src/bpf.rs

@@ -3,7 +3,7 @@ use std::{
     collections::{HashMap, HashSet},
     fs, io,
     os::{
-        fd::{AsFd as _, OwnedFd},
+        fd::{AsFd as _, AsRawFd as _, OwnedFd},
         raw::c_int,
     },
     path::{Path, PathBuf},
@@ -36,12 +36,11 @@ use crate::{
         SkMsg, SkSkb, SkSkbKind, SockOps, SocketFilter, TracePoint, UProbe, Xdp,
     },
     sys::{
-        bpf_load_btf, bpf_map_freeze, bpf_map_update_elem_ptr, is_bpf_cookie_supported,
-        is_bpf_global_data_supported, is_btf_datasec_supported, is_btf_decl_tag_supported,
-        is_btf_enum64_supported, is_btf_float_supported, is_btf_func_global_supported,
-        is_btf_func_supported, is_btf_supported, is_btf_type_tag_supported, is_perf_link_supported,
+        bpf_load_btf, is_bpf_cookie_supported, is_bpf_global_data_supported,
+        is_btf_datasec_supported, is_btf_decl_tag_supported, is_btf_enum64_supported,
+        is_btf_float_supported, is_btf_func_global_supported, is_btf_func_supported,
+        is_btf_supported, is_btf_type_tag_supported, is_perf_link_supported,
         is_probe_read_kernel_supported, is_prog_name_supported, retry_with_verifier_logs,
-        SyscallError,
     },
     util::{bytes_of, bytes_of_slice, possible_cpus, POSSIBLE_CPUS},
 };
@@ -482,23 +481,7 @@ impl<'a> BpfLoader<'a> {
                     MapData::create_pinned(path, obj, &name, btf_fd)?
                 }
             };
-            let fd = map.fd;
-            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)| SyscallError {
-                        call: "bpf_map_update_elem",
-                        io_error,
-                    })
-                    .map_err(MapError::from)?;
-            }
-            if map.obj.section_kind() == BpfSectionKind::Rodata {
-                bpf_map_freeze(fd)
-                    .map_err(|(_, io_error)| SyscallError {
-                        call: "bpf_map_freeze",
-                        io_error,
-                    })
-                    .map_err(MapError::from)?;
-            }
+            map.finalize()?;
             maps.insert(name, map);
         }
 
@@ -510,7 +493,7 @@ impl<'a> BpfLoader<'a> {
 
         obj.relocate_maps(
             maps.iter()
-                .map(|(s, data)| (s.as_str(), data.fd, &data.obj)),
+                .map(|(s, data)| (s.as_str(), data.fd().as_fd().as_raw_fd(), data.obj())),
             &text_sections,
         )?;
         obj.relocate_calls(&text_sections)?;
@@ -691,7 +674,7 @@ impl<'a> BpfLoader<'a> {
         if !*allow_unsupported_maps {
             maps.iter().try_for_each(|(_, x)| match x {
                 Map::Unsupported(map) => Err(BpfError::MapError(MapError::Unsupported {
-                    map_type: map.obj.map_type(),
+                    map_type: map.obj().map_type(),
                 })),
                 _ => Ok(()),
             })?;
@@ -705,7 +688,7 @@ fn parse_map(data: (String, MapData)) -> Result<(String, Map), BpfError> {
     let name = data.0;
     let map = data.1;
     let map_type =
-        bpf_map_type::try_from(map.obj.map_type()).map_err(|e| MapError::InvalidMapType {
+        bpf_map_type::try_from(map.obj().map_type()).map_err(|e| MapError::InvalidMapType {
             map_type: e.map_type,
         })?;
     let map = match map_type {

+ 3 - 2
aya/src/maps/array/array.rs

@@ -1,6 +1,7 @@
 use std::{
     borrow::{Borrow, BorrowMut},
     marker::PhantomData,
+    os::fd::AsFd as _,
 };
 
 use crate::{
@@ -61,7 +62,7 @@ impl<T: Borrow<MapData>, V: Pod> Array<T, V> {
     pub fn get(&self, index: &u32, flags: u64) -> Result<V, MapError> {
         let data = self.inner.borrow();
         check_bounds(data, *index)?;
-        let fd = data.fd;
+        let fd = data.fd().as_fd();
 
         let value =
             bpf_map_lookup_elem(fd, index, flags).map_err(|(_, io_error)| SyscallError {
@@ -88,7 +89,7 @@ impl<T: BorrowMut<MapData>, V: Pod> Array<T, V> {
     pub fn set(&mut self, index: u32, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> {
         let data = self.inner.borrow_mut();
         check_bounds(data, index)?;
-        let fd = data.fd;
+        let fd = data.fd().as_fd();
         bpf_map_update_elem(fd, Some(&index), value.borrow(), flags).map_err(|(_, io_error)| {
             SyscallError {
                 call: "bpf_map_update_elem",

+ 3 - 2
aya/src/maps/array/per_cpu_array.rs

@@ -1,6 +1,7 @@
 use std::{
     borrow::{Borrow, BorrowMut},
     marker::PhantomData,
+    os::fd::AsFd as _,
 };
 
 use crate::{
@@ -80,7 +81,7 @@ impl<T: Borrow<MapData>, V: Pod> PerCpuArray<T, V> {
     pub fn get(&self, index: &u32, flags: u64) -> Result<PerCpuValues<V>, MapError> {
         let data = self.inner.borrow();
         check_bounds(data, *index)?;
-        let fd = data.fd;
+        let fd = data.fd().as_fd();
 
         let value = bpf_map_lookup_elem_per_cpu(fd, index, flags).map_err(|(_, io_error)| {
             SyscallError {
@@ -108,7 +109,7 @@ impl<T: BorrowMut<MapData>, V: Pod> PerCpuArray<T, V> {
     pub fn set(&mut self, index: u32, values: PerCpuValues<V>, flags: u64) -> Result<(), MapError> {
         let data = self.inner.borrow_mut();
         check_bounds(data, index)?;
-        let fd = data.fd;
+        let fd = data.fd().as_fd();
 
         bpf_map_update_elem_per_cpu(fd, &index, &values, flags).map_err(|(_, io_error)| {
             SyscallError {

+ 2 - 2
aya/src/maps/array/program_array.rs

@@ -74,7 +74,7 @@ impl<T: BorrowMut<MapData>> ProgramArray<T> {
     pub fn set(&mut self, index: u32, program: &ProgramFd, flags: u64) -> Result<(), MapError> {
         let data = self.inner.borrow_mut();
         check_bounds(data, index)?;
-        let fd = data.fd;
+        let fd = data.fd().as_fd();
         let prog_fd = program.as_fd();
         let prog_fd = prog_fd.as_raw_fd();
 
@@ -94,7 +94,7 @@ impl<T: BorrowMut<MapData>> ProgramArray<T> {
     pub fn clear_index(&mut self, index: &u32) -> Result<(), MapError> {
         let data = self.inner.borrow_mut();
         check_bounds(data, *index)?;
-        let fd = self.inner.borrow_mut().fd;
+        let fd = data.fd().as_fd();
 
         bpf_map_delete_elem(fd, index)
             .map(|_| ())

+ 3 - 2
aya/src/maps/bloom_filter.rs

@@ -2,6 +2,7 @@
 use std::{
     borrow::{Borrow, BorrowMut},
     marker::PhantomData,
+    os::fd::AsFd as _,
 };
 
 use crate::{
@@ -52,7 +53,7 @@ impl<T: Borrow<MapData>, V: Pod> BloomFilter<T, V> {
 
     /// Query the existence of the element.
     pub fn contains(&self, mut value: &V, flags: u64) -> Result<(), MapError> {
-        let fd = self.inner.borrow().fd;
+        let fd = self.inner.borrow().fd().as_fd();
 
         bpf_map_lookup_elem_ptr::<u32, _>(fd, None, &mut value, flags)
             .map_err(|(_, io_error)| SyscallError {
@@ -67,7 +68,7 @@ impl<T: Borrow<MapData>, V: Pod> BloomFilter<T, V> {
 impl<T: BorrowMut<MapData>, V: Pod> BloomFilter<T, V> {
     /// Inserts a value into the map.
     pub fn insert(&mut self, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> {
-        let fd = self.inner.borrow_mut().fd;
+        let fd = self.inner.borrow_mut().fd().as_fd();
         bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| SyscallError {
             call: "bpf_map_push_elem",
             io_error,

+ 2 - 1
aya/src/maps/hash_map/hash_map.rs

@@ -1,6 +1,7 @@
 use std::{
     borrow::{Borrow, BorrowMut},
     marker::PhantomData,
+    os::fd::AsFd as _,
 };
 
 use crate::{
@@ -52,7 +53,7 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> HashMap<T, K, V> {
 
     /// Returns a copy of the value associated with the key.
     pub fn get(&self, key: &K, flags: u64) -> Result<V, MapError> {
-        let fd = self.inner.borrow().fd;
+        let fd = self.inner.borrow().fd().as_fd();
         let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError {
             call: "bpf_map_lookup_elem",
             io_error,

+ 3 - 2
aya/src/maps/hash_map/mod.rs

@@ -4,6 +4,7 @@ use crate::{
     sys::{bpf_map_delete_elem, bpf_map_update_elem, SyscallError},
     Pod,
 };
+use std::os::fd::AsFd as _;
 
 #[allow(clippy::module_inception)]
 mod hash_map;
@@ -20,7 +21,7 @@ pub(crate) fn insert<K: Pod, V: Pod>(
     value: &V,
     flags: u64,
 ) -> Result<(), MapError> {
-    let fd = map.fd;
+    let fd = map.fd().as_fd();
     bpf_map_update_elem(fd, Some(key), value, flags).map_err(|(_, io_error)| SyscallError {
         call: "bpf_map_update_elem",
         io_error,
@@ -30,7 +31,7 @@ pub(crate) fn insert<K: Pod, V: Pod>(
 }
 
 pub(crate) fn remove<K: Pod>(map: &MapData, key: &K) -> Result<(), MapError> {
-    let fd = map.fd;
+    let fd = map.fd().as_fd();
     bpf_map_delete_elem(fd, key)
         .map(|_| ())
         .map_err(|(_, io_error)| {

+ 3 - 2
aya/src/maps/hash_map/per_cpu_hash_map.rs

@@ -2,6 +2,7 @@
 use std::{
     borrow::{Borrow, BorrowMut},
     marker::PhantomData,
+    os::fd::AsFd as _,
 };
 
 use crate::{
@@ -61,7 +62,7 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
 
     /// Returns a slice of values - one for each CPU - associated with the key.
     pub fn get(&self, key: &K, flags: u64) -> Result<PerCpuValues<V>, MapError> {
-        let fd = self.inner.borrow().fd;
+        let fd = self.inner.borrow().fd().as_fd();
         let values =
             bpf_map_lookup_elem_per_cpu(fd, key, flags).map_err(|(_, io_error)| SyscallError {
                 call: "bpf_map_lookup_elem",
@@ -118,7 +119,7 @@ impl<T: BorrowMut<MapData>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
         values: PerCpuValues<V>,
         flags: u64,
     ) -> Result<(), MapError> {
-        let fd = self.inner.borrow_mut().fd;
+        let fd = self.inner.borrow_mut().fd().as_fd();
         bpf_map_update_elem_per_cpu(fd, key.borrow(), &values, flags).map_err(
             |(_, io_error)| SyscallError {
                 call: "bpf_map_update_elem",

+ 4 - 3
aya/src/maps/lpm_trie.rs

@@ -2,6 +2,7 @@
 use std::{
     borrow::{Borrow, BorrowMut},
     marker::PhantomData,
+    os::fd::AsFd as _,
 };
 
 use crate::{
@@ -126,7 +127,7 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
 
     /// Returns a copy of the value associated with the longest prefix matching key in the LpmTrie.
     pub fn get(&self, key: &Key<K>, flags: u64) -> Result<V, MapError> {
-        let fd = self.inner.borrow().fd;
+        let fd = self.inner.borrow().fd().as_fd();
         let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError {
             call: "bpf_map_lookup_elem",
             io_error,
@@ -155,7 +156,7 @@ impl<T: BorrowMut<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
         value: impl Borrow<V>,
         flags: u64,
     ) -> Result<(), MapError> {
-        let fd = self.inner.borrow().fd;
+        let fd = self.inner.borrow().fd().as_fd();
         bpf_map_update_elem(fd, Some(key), value.borrow(), flags).map_err(|(_, io_error)| {
             SyscallError {
                 call: "bpf_map_update_elem",
@@ -170,7 +171,7 @@ impl<T: BorrowMut<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
     ///
     /// Both the prefix and data must match exactly - this method does not do a longest prefix match.
     pub fn remove(&mut self, key: &Key<K>) -> Result<(), MapError> {
-        let fd = self.inner.borrow().fd;
+        let fd = self.inner.borrow().fd().as_fd();
         bpf_map_delete_elem(fd, key)
             .map(|_| ())
             .map_err(|(_, io_error)| {

+ 99 - 70
aya/src/maps/mod.rs

@@ -18,17 +18,28 @@
 //! the [`TryFrom`] or [`TryInto`] trait. For example:
 //!
 //! ```no_run
+//! # #[derive(Debug, thiserror::Error)]
+//! # enum Error {
+//! #     #[error(transparent)]
+//! #     IO(#[from] std::io::Error),
+//! #     #[error(transparent)]
+//! #     Map(#[from] aya::maps::MapError),
+//! #     #[error(transparent)]
+//! #     Program(#[from] aya::programs::ProgramError),
+//! #     #[error(transparent)]
+//! #     Bpf(#[from] aya::BpfError)
+//! # }
 //! # let mut bpf = aya::Bpf::load(&[])?;
 //! use aya::maps::SockMap;
 //! use aya::programs::SkMsg;
 //!
 //! let intercept_egress = SockMap::try_from(bpf.map_mut("INTERCEPT_EGRESS").unwrap())?;
-//! let map_fd = intercept_egress.fd()?;
+//! let map_fd = intercept_egress.fd().try_clone()?;
 //! let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
 //! prog.load()?;
-//! prog.attach(map_fd)?;
+//! prog.attach(&map_fd)?;
 //!
-//! # Ok::<(), aya::BpfError>(())
+//! # Ok::<(), Error>(())
 //! ```
 //!
 //! # Maps and `Pod` values
@@ -42,22 +53,22 @@ use std::{
     marker::PhantomData,
     mem,
     ops::Deref,
-    os::fd::{AsFd as _, AsRawFd, BorrowedFd, IntoRawFd as _, OwnedFd, RawFd},
+    os::fd::{AsFd, BorrowedFd, OwnedFd},
     path::Path,
     ptr,
 };
 
 use crate::util::KernelVersion;
-use libc::{getrlimit, rlimit, RLIMIT_MEMLOCK, RLIM_INFINITY};
+use libc::{getrlimit, rlim_t, rlimit, RLIMIT_MEMLOCK, RLIM_INFINITY};
 use log::warn;
 use thiserror::Error;
 
 use crate::{
-    obj::{self, parse_map_info},
+    obj::{self, parse_map_info, BpfSectionKind},
     pin::PinError,
     sys::{
-        bpf_create_map, bpf_get_object, bpf_map_get_info_by_fd, bpf_map_get_next_key,
-        bpf_pin_object, SyscallError,
+        bpf_create_map, bpf_get_object, bpf_map_freeze, bpf_map_get_info_by_fd,
+        bpf_map_get_next_key, bpf_map_update_elem_ptr, bpf_pin_object, SyscallError,
     },
     util::nr_cpus,
     PinningType, Pod,
@@ -177,25 +188,13 @@ pub enum MapError {
 }
 
 /// A map file descriptor.
-pub struct MapFd(RawFd);
+#[derive(Debug)]
+pub struct MapFd(OwnedFd);
 
-impl AsRawFd for MapFd {
-    fn as_raw_fd(&self) -> RawFd {
-        self.0
-    }
-}
-
-#[derive(PartialEq, Eq, PartialOrd, Ord)]
-struct RlimitSize(usize);
-impl fmt::Display for RlimitSize {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if self.0 < 1024 {
-            write!(f, "{} bytes", self.0)
-        } else if self.0 < 1024 * 1024 {
-            write!(f, "{} KiB", self.0 / 1024)
-        } else {
-            write!(f, "{} MiB", self.0 / 1024 / 1024)
-        }
+impl AsFd for MapFd {
+    fn as_fd(&self) -> BorrowedFd<'_> {
+        let Self(fd) = self;
+        fd.as_fd()
     }
 }
 
@@ -207,15 +206,28 @@ fn maybe_warn_rlimit() {
     if ret == 0 {
         let limit = unsafe { limit.assume_init() };
 
-        let limit: RlimitSize = RlimitSize(limit.rlim_cur.try_into().unwrap());
-        if limit.0 == RLIM_INFINITY.try_into().unwrap() {
+        if limit.rlim_cur == RLIM_INFINITY {
             return;
         }
+        struct HumanSize(rlim_t);
+
+        impl fmt::Display for HumanSize {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                let &Self(size) = self;
+                if size < 1024 {
+                    write!(f, "{} bytes", size)
+                } else if size < 1024 * 1024 {
+                    write!(f, "{} KiB", size / 1024)
+                } else {
+                    write!(f, "{} MiB", size / 1024 / 1024)
+                }
+            }
+        }
         warn!(
-            "RLIMIT_MEMLOCK value is {}, not RLIM_INFNITY; if experiencing problems with creating \
-            maps, try raising RMILIT_MEMLOCK either to RLIM_INFINITY or to a higher value sufficient \
-            for size of your maps",
-            limit
+            "RLIMIT_MEMLOCK value is {}, not RLIM_INFINITY; if experiencing problems with creating \
+            maps, try raising RLIMIT_MEMLOCK either to RLIM_INFINITY or to a higher value sufficient \
+            for the size of your maps",
+            HumanSize(limit.rlim_cur)
         );
     }
 }
@@ -395,8 +407,8 @@ pub(crate) fn check_v_size<V>(map: &MapData) -> Result<(), MapError> {
 /// You should never need to use this unless you're implementing a new map type.
 #[derive(Debug)]
 pub struct MapData {
-    pub(crate) obj: obj::Map,
-    pub(crate) fd: RawFd,
+    obj: obj::Map,
+    fd: MapFd,
     /// Indicates if this map has been pinned to bpffs
     pub pinned: bool,
 }
@@ -426,9 +438,7 @@ impl MapData {
                     io_error,
                 }
             })?;
-
-        #[allow(trivial_numeric_casts)]
-        let fd = fd as RawFd;
+        let fd = MapFd(fd);
         Ok(Self {
             obj,
             fd,
@@ -459,11 +469,14 @@ impl MapData {
             call: "BPF_OBJ_GET",
             io_error,
         }) {
-            Ok(fd) => Ok(Self {
-                obj,
-                fd: fd.into_raw_fd(),
-                pinned: false,
-            }),
+            Ok(fd) => {
+                let fd = MapFd(fd);
+                Ok(Self {
+                    obj,
+                    fd,
+                    pinned: false,
+                })
+            }
             Err(_) => {
                 let mut map = Self::create(obj, name, btf_fd)?;
                 map.pin(name, path).map_err(|error| MapError::PinError {
@@ -475,6 +488,27 @@ impl MapData {
         }
     }
 
+    pub(crate) fn finalize(&mut self) -> Result<(), MapError> {
+        let Self { obj, fd, pinned: _ } = self;
+        if !obj.data().is_empty() && obj.section_kind() != BpfSectionKind::Bss {
+            bpf_map_update_elem_ptr(fd.as_fd(), &0 as *const _, obj.data_mut().as_mut_ptr(), 0)
+                .map_err(|(_, io_error)| SyscallError {
+                    call: "bpf_map_update_elem",
+                    io_error,
+                })
+                .map_err(MapError::from)?;
+        }
+        if obj.section_kind() == BpfSectionKind::Rodata {
+            bpf_map_freeze(fd.as_fd())
+                .map_err(|(_, io_error)| SyscallError {
+                    call: "bpf_map_freeze",
+                    io_error,
+                })
+                .map_err(MapError::from)?;
+        }
+        Ok(())
+    }
+
     /// Loads a map from a pinned path in bpffs.
     pub fn from_pin<P: AsRef<Path>>(path: P) -> Result<Self, MapError> {
         use std::os::unix::ffi::OsStrExt as _;
@@ -493,12 +527,13 @@ impl MapData {
             call: "BPF_OBJ_GET",
             io_error,
         })?;
+        let fd = MapFd(fd);
 
         let info = bpf_map_get_info_by_fd(fd.as_fd())?;
 
         Ok(Self {
             obj: parse_map_info(info, PinningType::ByName),
-            fd: fd.into_raw_fd(),
+            fd,
             pinned: true,
         })
     }
@@ -511,9 +546,10 @@ impl MapData {
     pub fn from_fd(fd: OwnedFd) -> Result<Self, MapError> {
         let info = bpf_map_get_info_by_fd(fd.as_fd())?;
 
+        let fd = MapFd(fd);
         Ok(Self {
             obj: parse_map_info(info, PinningType::None),
-            fd: fd.into_raw_fd(),
+            fd,
             pinned: false,
         })
     }
@@ -528,7 +564,7 @@ impl MapData {
         let path = path.as_ref().join(name);
         let path_string = CString::new(path.as_os_str().as_bytes())
             .map_err(|error| PinError::InvalidPinPath { path, error })?;
-        bpf_pin_object(*fd, &path_string).map_err(|(_, io_error)| SyscallError {
+        bpf_pin_object(fd.as_fd(), &path_string).map_err(|(_, io_error)| SyscallError {
             call: "BPF_OBJ_PIN",
             io_error,
         })?;
@@ -537,30 +573,22 @@ impl MapData {
     }
 
     /// Returns the file descriptor of the map.
-    ///
-    /// Can be converted to [`RawFd`] using [`AsRawFd`].
-    pub fn fd(&self) -> MapFd {
-        MapFd(self.fd)
-    }
-}
-
-impl Drop for MapData {
-    fn drop(&mut self) {
-        // TODO: Replace this with an OwnedFd once that is stabilized.
-        //
-        // SAFETY: `drop` is only called once.
-        unsafe { libc::close(self.fd) };
+    pub fn fd(&self) -> &MapFd {
+        let Self {
+            obj: _,
+            fd,
+            pinned: _,
+        } = self;
+        fd
     }
-}
 
-impl Clone for MapData {
-    fn clone(&self) -> Self {
-        let Self { obj, fd, pinned } = self;
-        Self {
-            obj: obj.clone(),
-            fd: unsafe { libc::dup(*fd) },
-            pinned: *pinned,
-        }
+    pub(crate) fn obj(&self) -> &obj::Map {
+        let Self {
+            obj,
+            fd: _,
+            pinned: _,
+        } = self;
+        obj
     }
 }
 
@@ -598,7 +626,7 @@ impl<K: Pod> Iterator for MapKeys<'_, K> {
             return None;
         }
 
-        let fd = self.map.fd;
+        let fd = self.map.fd().as_fd();
         let key =
             bpf_map_get_next_key(fd, self.key.as_ref()).map_err(|(_, io_error)| SyscallError {
                 call: "bpf_map_get_next_key",
@@ -754,6 +782,7 @@ impl<T: Pod> Deref for PerCpuValues<T> {
 mod tests {
     use assert_matches::assert_matches;
     use libc::EFAULT;
+    use std::os::fd::AsRawFd as _;
 
     use crate::{
         bpf_map_def,
@@ -795,9 +824,9 @@ mod tests {
             MapData::create(new_obj_map(), "foo", None),
             Ok(MapData {
                 obj: _,
-                fd: 42,
+                fd,
                 pinned: false
-            })
+            }) => assert_eq!(fd.as_fd().as_raw_fd(), 42)
         );
     }
 

+ 2 - 2
aya/src/maps/perf/perf_event_array.rs

@@ -4,7 +4,7 @@
 use std::{
     borrow::{Borrow, BorrowMut},
     ops::Deref,
-    os::fd::{AsRawFd, RawFd},
+    os::fd::{AsFd as _, AsRawFd, RawFd},
     sync::Arc,
 };
 
@@ -181,7 +181,7 @@ impl<T: BorrowMut<MapData>> PerfEventArray<T> {
         // FIXME: keep track of open buffers
 
         let map_data: &MapData = self.map.deref().borrow();
-        let map_fd = map_data.fd;
+        let map_fd = map_data.fd().as_fd();
         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)
             .map_err(|(_, io_error)| io_error)?;

+ 3 - 2
aya/src/maps/queue.rs

@@ -2,6 +2,7 @@
 use std::{
     borrow::{Borrow, BorrowMut},
     marker::PhantomData,
+    os::fd::AsFd as _,
 };
 
 use crate::{
@@ -60,7 +61,7 @@ impl<T: BorrowMut<MapData>, V: Pod> Queue<T, V> {
     /// Returns [`MapError::ElementNotFound`] if the queue is empty, [`MapError::SyscallError`]
     /// if `bpf_map_lookup_and_delete_elem` fails.
     pub fn pop(&mut self, flags: u64) -> Result<V, MapError> {
-        let fd = self.inner.borrow().fd;
+        let fd = self.inner.borrow().fd().as_fd();
 
         let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err(
             |(_, io_error)| SyscallError {
@@ -77,7 +78,7 @@ impl<T: BorrowMut<MapData>, V: Pod> Queue<T, V> {
     ///
     /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails.
     pub fn push(&mut self, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> {
-        let fd = self.inner.borrow().fd;
+        let fd = self.inner.borrow().fd().as_fd();
         bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| SyscallError {
             call: "bpf_map_push_elem",
             io_error,

+ 19 - 7
aya/src/maps/sock/mod.rs

@@ -5,17 +5,29 @@ mod sock_map;
 pub use sock_hash::SockHash;
 pub use sock_map::SockMap;
 
-use std::os::fd::{AsFd, BorrowedFd, RawFd};
+use std::{
+    io,
+    os::fd::{AsFd, BorrowedFd},
+};
 
 /// A socket map file descriptor.
-#[derive(Copy, Clone)]
-pub struct SockMapFd(RawFd);
+#[repr(transparent)]
+pub struct SockMapFd(super::MapFd);
+
+impl SockMapFd {
+    /// Creates a new instance that shares the same underlying file description as [`self`].
+    pub fn try_clone(&self) -> io::Result<Self> {
+        let Self(inner) = self;
+        let super::MapFd(inner) = inner;
+        let inner = inner.try_clone()?;
+        let inner = super::MapFd(inner);
+        Ok(Self(inner))
+    }
+}
 
 impl AsFd for SockMapFd {
     fn as_fd(&self) -> BorrowedFd<'_> {
-        // SAFETY: This isn't necessarily safe, we need to find ways
-        // to enforce that the file descriptor is still
-        // valid. TODO(#612)
-        unsafe { BorrowedFd::borrow_raw(self.0) }
+        let Self(fd) = self;
+        fd.as_fd()
     }
 }

+ 11 - 7
aya/src/maps/sock/sock_hash.rs

@@ -1,12 +1,13 @@
 use std::{
     borrow::{Borrow, BorrowMut},
     marker::PhantomData,
-    os::fd::{AsRawFd, RawFd},
+    os::fd::{AsFd as _, AsRawFd, RawFd},
 };
 
 use crate::{
     maps::{
-        check_kv_size, hash_map, sock::SockMapFd, IterableMap, MapData, MapError, MapIter, MapKeys,
+        check_kv_size, hash_map, sock::SockMapFd, IterableMap, MapData, MapError, MapFd, MapIter,
+        MapKeys,
     },
     sys::{bpf_map_lookup_elem, SyscallError},
     Pod,
@@ -47,11 +48,11 @@ use crate::{
 /// use aya::programs::SkMsg;
 ///
 /// let mut intercept_egress = SockHash::<_, u32>::try_from(bpf.map("INTERCEPT_EGRESS").unwrap())?;
-/// let map_fd = intercept_egress.fd()?;
+/// let map_fd = intercept_egress.fd().try_clone()?;
 ///
 /// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
 /// prog.load()?;
-/// prog.attach(map_fd)?;
+/// prog.attach(&map_fd)?;
 ///
 /// let mut client = TcpStream::connect("127.0.0.1:1234")?;
 /// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS").unwrap())?;
@@ -81,7 +82,7 @@ impl<T: Borrow<MapData>, K: Pod> SockHash<T, K> {
 
     /// Returns the fd of the socket stored at the given key.
     pub fn get(&self, key: &K, flags: u64) -> Result<RawFd, MapError> {
-        let fd = self.inner.borrow().fd;
+        let fd = self.inner.borrow().fd().as_fd();
         let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError {
             call: "bpf_map_lookup_elem",
             io_error,
@@ -105,8 +106,11 @@ impl<T: Borrow<MapData>, K: Pod> SockHash<T, K> {
     ///
     /// 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<SockMapFd, MapError> {
-        Ok(SockMapFd(self.inner.borrow().fd))
+    pub fn fd(&self) -> &SockMapFd {
+        let fd: &MapFd = self.inner.borrow().fd();
+        // TODO(https://github.com/rust-lang/rfcs/issues/3066): avoid this unsafe.
+        // SAFETY: `SockMapFd` is #[repr(transparent)] over `MapFd`.
+        unsafe { std::mem::transmute(fd) }
     }
 }
 

+ 23 - 9
aya/src/maps/sock/sock_map.rs

@@ -2,11 +2,11 @@
 
 use std::{
     borrow::{Borrow, BorrowMut},
-    os::fd::{AsRawFd, RawFd},
+    os::fd::{AsFd as _, AsRawFd, RawFd},
 };
 
 use crate::{
-    maps::{check_bounds, check_kv_size, sock::SockMapFd, MapData, MapError, MapKeys},
+    maps::{check_bounds, check_kv_size, sock::SockMapFd, MapData, MapError, MapFd, MapKeys},
     sys::{bpf_map_delete_elem, bpf_map_update_elem, SyscallError},
 };
 
@@ -26,18 +26,29 @@ use crate::{
 /// # Examples
 ///
 /// ```no_run
+/// # #[derive(Debug, thiserror::Error)]
+/// # enum Error {
+/// #     #[error(transparent)]
+/// #     IO(#[from] std::io::Error),
+/// #     #[error(transparent)]
+/// #     Map(#[from] aya::maps::MapError),
+/// #     #[error(transparent)]
+/// #     Program(#[from] aya::programs::ProgramError),
+/// #     #[error(transparent)]
+/// #     Bpf(#[from] aya::BpfError)
+/// # }
 /// # let mut bpf = aya::Bpf::load(&[])?;
 /// use aya::maps::SockMap;
 /// use aya::programs::SkSkb;
 ///
 /// let intercept_ingress = SockMap::try_from(bpf.map("INTERCEPT_INGRESS").unwrap())?;
-/// let map_fd = intercept_ingress.fd()?;
+/// let map_fd = intercept_ingress.fd().try_clone()?;
 ///
 /// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?;
 /// prog.load()?;
-/// prog.attach(map_fd)?;
+/// prog.attach(&map_fd)?;
 ///
-/// # Ok::<(), aya::BpfError>(())
+/// # Ok::<(), Error>(())
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_SOCKMAP")]
 pub struct SockMap<T> {
@@ -62,8 +73,11 @@ impl<T: Borrow<MapData>> SockMap<T> {
     ///
     /// 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<SockMapFd, MapError> {
-        Ok(SockMapFd(self.inner.borrow().fd))
+    pub fn fd(&self) -> &SockMapFd {
+        let fd: &MapFd = self.inner.borrow().fd();
+        // TODO(https://github.com/rust-lang/rfcs/issues/3066): avoid this unsafe.
+        // SAFETY: `SockMapFd` is #[repr(transparent)] over `MapFd`.
+        unsafe { std::mem::transmute(&fd) }
     }
 }
 
@@ -71,7 +85,7 @@ impl<T: BorrowMut<MapData>> SockMap<T> {
     /// Stores a socket into the map.
     pub fn set<I: AsRawFd>(&mut self, index: u32, socket: &I, flags: u64) -> Result<(), MapError> {
         let data = self.inner.borrow_mut();
-        let fd = data.fd;
+        let fd = data.fd().as_fd();
         check_bounds(data, index)?;
         bpf_map_update_elem(fd, Some(&index), &socket.as_raw_fd(), flags).map_err(
             |(_, io_error)| SyscallError {
@@ -85,7 +99,7 @@ impl<T: BorrowMut<MapData>> SockMap<T> {
     /// Removes the socket stored at `index` from the map.
     pub fn clear_index(&mut self, index: &u32) -> Result<(), MapError> {
         let data = self.inner.borrow_mut();
-        let fd = data.fd;
+        let fd = data.fd().as_fd();
         check_bounds(data, *index)?;
         bpf_map_delete_elem(fd, index)
             .map(|_| ())

+ 3 - 2
aya/src/maps/stack.rs

@@ -2,6 +2,7 @@
 use std::{
     borrow::{Borrow, BorrowMut},
     marker::PhantomData,
+    os::fd::AsFd as _,
 };
 
 use crate::{
@@ -60,7 +61,7 @@ impl<T: BorrowMut<MapData>, V: Pod> Stack<T, V> {
     /// Returns [`MapError::ElementNotFound`] if the stack is empty, [`MapError::SyscallError`]
     /// if `bpf_map_lookup_and_delete_elem` fails.
     pub fn pop(&mut self, flags: u64) -> Result<V, MapError> {
-        let fd = self.inner.borrow().fd;
+        let fd = self.inner.borrow().fd().as_fd();
 
         let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err(
             |(_, io_error)| SyscallError {
@@ -77,7 +78,7 @@ impl<T: BorrowMut<MapData>, V: Pod> Stack<T, V> {
     ///
     /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails.
     pub fn push(&mut self, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> {
-        let fd = self.inner.borrow().fd;
+        let fd = self.inner.borrow().fd().as_fd();
         bpf_map_update_elem(fd, None::<&u32>, value.borrow(), flags).map_err(|(_, io_error)| {
             SyscallError {
                 call: "bpf_map_update_elem",

+ 2 - 2
aya/src/maps/stack_trace.rs

@@ -1,7 +1,7 @@
 //! A hash map of kernel or user space stack traces.
 //!
 //! See [`StackTraceMap`] for documentation and examples.
-use std::{borrow::Borrow, fs, io, mem, path::Path, str::FromStr};
+use std::{borrow::Borrow, fs, io, mem, os::fd::AsFd as _, path::Path, str::FromStr};
 
 use crate::{
     maps::{IterableMap, MapData, MapError, MapIter, MapKeys},
@@ -103,7 +103,7 @@ impl<T: Borrow<MapData>> StackTraceMap<T> {
     /// Returns [`MapError::KeyNotFound`] if there is no stack trace with the
     /// given `stack_id`, or [`MapError::SyscallError`] if `bpf_map_lookup_elem` fails.
     pub fn get(&self, stack_id: &u32, flags: u64) -> Result<StackTrace, MapError> {
-        let fd = self.inner.borrow().fd;
+        let fd = self.inner.borrow().fd().as_fd();
 
         let mut frames = vec![0; self.max_stack_depth];
         bpf_map_lookup_elem_ptr(fd, Some(stack_id), frames.as_mut_ptr(), flags)

+ 3 - 5
aya/src/programs/links.rs

@@ -154,11 +154,9 @@ impl FdLink {
                 error,
             }
         })?;
-        bpf_pin_object(self.fd.as_raw_fd(), &path_string).map_err(|(_, io_error)| {
-            SyscallError {
-                call: "BPF_OBJ_PIN",
-                io_error,
-            }
+        bpf_pin_object(self.fd.as_fd(), &path_string).map_err(|(_, io_error)| SyscallError {
+            call: "BPF_OBJ_PIN",
+            io_error,
         })?;
         Ok(PinnedLink::new(path.into(), self))
     }

+ 3 - 4
aya/src/programs/mod.rs

@@ -218,9 +218,8 @@ pub enum ProgramError {
 pub struct ProgramFd(OwnedFd);
 
 impl ProgramFd {
-    /// Creates a new `ProgramFd` instance that shares the same underlying file
-    /// description as the existing `ProgramFd` instance.
-    pub fn try_clone(&self) -> Result<Self, ProgramError> {
+    /// Creates a new instance that shares the same underlying file description as [`self`].
+    pub fn try_clone(&self) -> io::Result<Self> {
         let Self(inner) = self;
         let inner = inner.try_clone()?;
         Ok(Self(inner))
@@ -536,7 +535,7 @@ fn pin_program<T: Link, P: AsRef<Path>>(data: &ProgramData<T>, path: P) -> Resul
             path: path.into(),
             error,
         })?;
-    bpf_pin_object(fd.as_fd().as_raw_fd(), &path_string).map_err(|(_, io_error)| SyscallError {
+    bpf_pin_object(fd.as_fd(), &path_string).map_err(|(_, io_error)| SyscallError {
         call: "BPF_OBJ_PIN",
         io_error,
     })?;

+ 3 - 3
aya/src/programs/sk_msg.rs

@@ -43,11 +43,11 @@ use crate::{
 /// use aya::programs::SkMsg;
 ///
 /// let intercept_egress: SockHash<_, u32> = bpf.map("INTERCEPT_EGRESS").unwrap().try_into()?;
-/// let map_fd = intercept_egress.fd()?;
+/// let map_fd = intercept_egress.fd().try_clone()?;
 ///
 /// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
 /// prog.load()?;
-/// prog.attach(map_fd)?;
+/// prog.attach(&map_fd)?;
 ///
 /// let mut client = TcpStream::connect("127.0.0.1:1234")?;
 /// let mut intercept_egress: SockHash<_, u32> = bpf.map_mut("INTERCEPT_EGRESS").unwrap().try_into()?;
@@ -77,7 +77,7 @@ impl SkMsg {
     /// Attaches the program to the given sockmap.
     ///
     /// The returned value can be used to detach, see [SkMsg::detach].
-    pub fn attach(&mut self, map: SockMapFd) -> Result<SkMsgLinkId, ProgramError> {
+    pub fn attach(&mut self, map: &SockMapFd) -> Result<SkMsgLinkId, ProgramError> {
         let prog_fd = self.fd()?;
         let prog_fd = prog_fd.as_fd();
         let link = ProgAttachLink::attach(prog_fd, map.as_fd(), BPF_SK_MSG_VERDICT)?;

+ 15 - 4
aya/src/programs/sk_skb.rs

@@ -37,18 +37,29 @@ pub enum SkSkbKind {
 /// # Examples
 ///
 /// ```no_run
+/// # #[derive(Debug, thiserror::Error)]
+/// # enum Error {
+/// #     #[error(transparent)]
+/// #     IO(#[from] std::io::Error),
+/// #     #[error(transparent)]
+/// #     Map(#[from] aya::maps::MapError),
+/// #     #[error(transparent)]
+/// #     Program(#[from] aya::programs::ProgramError),
+/// #     #[error(transparent)]
+/// #     Bpf(#[from] aya::BpfError)
+/// # }
 /// # let mut bpf = aya::Bpf::load(&[])?;
 /// use aya::maps::SockMap;
 /// use aya::programs::SkSkb;
 ///
 /// let intercept_ingress: SockMap<_> = bpf.map("INTERCEPT_INGRESS").unwrap().try_into()?;
-/// let map_fd = intercept_ingress.fd()?;
+/// let map_fd = intercept_ingress.fd().try_clone()?;
 ///
 /// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?;
 /// prog.load()?;
-/// prog.attach(map_fd)?;
+/// prog.attach(&map_fd)?;
 ///
-/// # Ok::<(), aya::BpfError>(())
+/// # Ok::<(), Error>(())
 /// ```
 ///
 /// [socket maps]: crate::maps::sock
@@ -70,7 +81,7 @@ impl SkSkb {
     /// Attaches the program to the given socket map.
     ///
     /// The returned value can be used to detach, see [SkSkb::detach].
-    pub fn attach(&mut self, map: SockMapFd) -> Result<SkSkbLinkId, ProgramError> {
+    pub fn attach(&mut self, map: &SockMapFd) -> Result<SkSkbLinkId, ProgramError> {
         let prog_fd = self.fd()?;
         let prog_fd = prog_fd.as_fd();
 

+ 1 - 1
aya/src/programs/utils.rs

@@ -82,7 +82,7 @@ pub(crate) fn get_fdinfo(fd: BorrowedFd<'_>, key: &str) -> Result<u32, ProgramEr
     let info = File::open(format!("/proc/self/fdinfo/{}", fd.as_raw_fd()))?;
     let reader = BufReader::new(info);
     for line in reader.lines() {
-        let line = line.map_err(ProgramError::IOError)?;
+        let line = line?;
         if !line.contains(key) {
             continue;
         }

+ 30 - 25
aya/src/sys/bpf.rs

@@ -38,7 +38,7 @@ pub(crate) fn bpf_create_map(
     def: &obj::Map,
     btf_fd: Option<BorrowedFd<'_>>,
     kernel_version: KernelVersion,
-) -> SysResult<c_long> {
+) -> SysResult<OwnedFd> {
     let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
 
     let u = unsafe { &mut attr.__bindgen_anon_1 };
@@ -91,13 +91,14 @@ pub(crate) fn bpf_create_map(
             .copy_from_slice(unsafe { slice::from_raw_parts(name.as_ptr(), name_len) });
     }
 
-    sys_bpf(bpf_cmd::BPF_MAP_CREATE, &mut attr)
+    // SAFETY: BPF_MAP_CREATE returns a new file descriptor.
+    unsafe { fd_sys_bpf(bpf_cmd::BPF_MAP_CREATE, &mut attr) }
 }
 
-pub(crate) fn bpf_pin_object(fd: RawFd, path: &CStr) -> SysResult<c_long> {
+pub(crate) fn bpf_pin_object(fd: BorrowedFd<'_>, path: &CStr) -> SysResult<c_long> {
     let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
     let u = unsafe { &mut attr.__bindgen_anon_4 };
-    u.bpf_fd = fd as u32;
+    u.bpf_fd = fd.as_raw_fd() as u32;
     u.pathname = path.as_ptr() as u64;
     sys_bpf(bpf_cmd::BPF_OBJ_PIN, &mut attr)
 }
@@ -194,7 +195,7 @@ pub(crate) fn bpf_load_program(
 }
 
 fn lookup<K: Pod, V: Pod>(
-    fd: RawFd,
+    fd: BorrowedFd<'_>,
     key: Option<&K>,
     flags: u64,
     cmd: bpf_cmd,
@@ -203,7 +204,7 @@ fn lookup<K: Pod, V: Pod>(
     let mut value = MaybeUninit::zeroed();
 
     let u = unsafe { &mut attr.__bindgen_anon_2 };
-    u.map_fd = fd as u32;
+    u.map_fd = fd.as_raw_fd() as u32;
     if let Some(key) = key {
         u.key = key as *const _ as u64;
     }
@@ -218,7 +219,7 @@ fn lookup<K: Pod, V: Pod>(
 }
 
 pub(crate) fn bpf_map_lookup_elem<K: Pod, V: Pod>(
-    fd: RawFd,
+    fd: BorrowedFd<'_>,
     key: &K,
     flags: u64,
 ) -> Result<Option<V>, (c_long, io::Error)> {
@@ -226,7 +227,7 @@ pub(crate) fn bpf_map_lookup_elem<K: Pod, V: Pod>(
 }
 
 pub(crate) fn bpf_map_lookup_and_delete_elem<K: Pod, V: Pod>(
-    fd: RawFd,
+    fd: BorrowedFd<'_>,
     key: Option<&K>,
     flags: u64,
 ) -> Result<Option<V>, (c_long, io::Error)> {
@@ -234,7 +235,7 @@ pub(crate) fn bpf_map_lookup_and_delete_elem<K: Pod, V: Pod>(
 }
 
 pub(crate) fn bpf_map_lookup_elem_per_cpu<K: Pod, V: Pod>(
-    fd: RawFd,
+    fd: BorrowedFd<'_>,
     key: &K,
     flags: u64,
 ) -> Result<Option<PerCpuValues<V>>, (c_long, io::Error)> {
@@ -247,7 +248,7 @@ pub(crate) fn bpf_map_lookup_elem_per_cpu<K: Pod, V: Pod>(
 }
 
 pub(crate) fn bpf_map_lookup_elem_ptr<K: Pod, V>(
-    fd: RawFd,
+    fd: BorrowedFd<'_>,
     key: Option<&K>,
     value: *mut V,
     flags: u64,
@@ -255,7 +256,7 @@ pub(crate) fn bpf_map_lookup_elem_ptr<K: Pod, V>(
     let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
 
     let u = unsafe { &mut attr.__bindgen_anon_2 };
-    u.map_fd = fd as u32;
+    u.map_fd = fd.as_raw_fd() as u32;
     if let Some(key) = key {
         u.key = key as *const _ as u64;
     }
@@ -270,7 +271,7 @@ pub(crate) fn bpf_map_lookup_elem_ptr<K: Pod, V>(
 }
 
 pub(crate) fn bpf_map_update_elem<K: Pod, V: Pod>(
-    fd: RawFd,
+    fd: BorrowedFd<'_>,
     key: Option<&K>,
     value: &V,
     flags: u64,
@@ -278,7 +279,7 @@ pub(crate) fn bpf_map_update_elem<K: Pod, V: Pod>(
     let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
 
     let u = unsafe { &mut attr.__bindgen_anon_2 };
-    u.map_fd = fd as u32;
+    u.map_fd = fd.as_raw_fd() as u32;
     if let Some(key) = key {
         u.key = key as *const _ as u64;
     }
@@ -288,11 +289,15 @@ pub(crate) fn bpf_map_update_elem<K: Pod, V: Pod>(
     sys_bpf(bpf_cmd::BPF_MAP_UPDATE_ELEM, &mut attr)
 }
 
-pub(crate) fn bpf_map_push_elem<V: Pod>(fd: RawFd, value: &V, flags: u64) -> SysResult<c_long> {
+pub(crate) fn bpf_map_push_elem<V: Pod>(
+    fd: BorrowedFd<'_>,
+    value: &V,
+    flags: u64,
+) -> SysResult<c_long> {
     let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
 
     let u = unsafe { &mut attr.__bindgen_anon_2 };
-    u.map_fd = fd as u32;
+    u.map_fd = fd.as_raw_fd() as u32;
     u.__bindgen_anon_1.value = value as *const _ as u64;
     u.flags = flags;
 
@@ -300,7 +305,7 @@ pub(crate) fn bpf_map_push_elem<V: Pod>(fd: RawFd, value: &V, flags: u64) -> Sys
 }
 
 pub(crate) fn bpf_map_update_elem_ptr<K, V>(
-    fd: RawFd,
+    fd: BorrowedFd<'_>,
     key: *const K,
     value: *mut V,
     flags: u64,
@@ -308,7 +313,7 @@ pub(crate) fn bpf_map_update_elem_ptr<K, V>(
     let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
 
     let u = unsafe { &mut attr.__bindgen_anon_2 };
-    u.map_fd = fd as u32;
+    u.map_fd = fd.as_raw_fd() as u32;
     u.key = key as u64;
     u.__bindgen_anon_1.value = value as u64;
     u.flags = flags;
@@ -317,7 +322,7 @@ pub(crate) fn bpf_map_update_elem_ptr<K, V>(
 }
 
 pub(crate) fn bpf_map_update_elem_per_cpu<K: Pod, V: Pod>(
-    fd: RawFd,
+    fd: BorrowedFd<'_>,
     key: &K,
     values: &PerCpuValues<V>,
     flags: u64,
@@ -326,25 +331,25 @@ pub(crate) fn bpf_map_update_elem_per_cpu<K: Pod, V: Pod>(
     bpf_map_update_elem_ptr(fd, key, mem.as_mut_ptr(), flags)
 }
 
-pub(crate) fn bpf_map_delete_elem<K: Pod>(fd: RawFd, key: &K) -> SysResult<c_long> {
+pub(crate) fn bpf_map_delete_elem<K: Pod>(fd: BorrowedFd<'_>, key: &K) -> SysResult<c_long> {
     let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
 
     let u = unsafe { &mut attr.__bindgen_anon_2 };
-    u.map_fd = fd as u32;
+    u.map_fd = fd.as_raw_fd() as u32;
     u.key = key as *const _ as u64;
 
     sys_bpf(bpf_cmd::BPF_MAP_DELETE_ELEM, &mut attr)
 }
 
 pub(crate) fn bpf_map_get_next_key<K: Pod>(
-    fd: RawFd,
+    fd: BorrowedFd<'_>,
     key: Option<&K>,
 ) -> Result<Option<K>, (c_long, io::Error)> {
     let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
     let mut next_key = MaybeUninit::uninit();
 
     let u = unsafe { &mut attr.__bindgen_anon_2 };
-    u.map_fd = fd as u32;
+    u.map_fd = fd.as_raw_fd() as u32;
     if let Some(key) = key {
         u.key = key as *const _ as u64;
     }
@@ -358,10 +363,10 @@ pub(crate) fn bpf_map_get_next_key<K: Pod>(
 }
 
 // since kernel 5.2
-pub(crate) fn bpf_map_freeze(fd: RawFd) -> SysResult<c_long> {
+pub(crate) fn bpf_map_freeze(fd: BorrowedFd<'_>) -> SysResult<c_long> {
     let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
     let u = unsafe { &mut attr.__bindgen_anon_2 };
-    u.map_fd = fd as u32;
+    u.map_fd = fd.as_raw_fd() as u32;
     sys_bpf(bpf_cmd::BPF_MAP_FREEZE, &mut attr)
 }
 
@@ -754,7 +759,7 @@ pub(crate) fn is_bpf_global_data_supported() -> bool {
     );
 
     if let Ok(map) = map {
-        insns[0].imm = map.fd;
+        insns[0].imm = map.fd().as_fd().as_raw_fd();
 
         let gpl = b"GPL\0";
         u.license = gpl.as_ptr() as u64;

+ 1 - 1
test/integration-test/src/tests/rbpf.rs

@@ -58,7 +58,7 @@ fn use_map_with_rbpf() {
         );
 
         let map_id = if name == "map_1" { 0 } else { 1 };
-        let fd = map_id as i32 | 0xCAFE00;
+        let fd = map_id as std::os::fd::RawFd | 0xCAFE00;
         maps.insert(name.to_owned(), (fd, map.clone()));
 
         unsafe {

+ 2 - 2
xtask/public-api/aya-obj.txt

@@ -5972,7 +5972,7 @@ impl aya_obj::Object
 pub fn aya_obj::Object::relocate_btf(&mut self, target_btf: &aya_obj::btf::Btf) -> core::result::Result<(), aya_obj::btf::BtfRelocationError>
 impl aya_obj::Object
 pub fn aya_obj::Object::relocate_calls(&mut self, text_sections: &std::collections::hash::set::HashSet<usize>) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError>
-pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator<Item = (&'a str, i32, &'a aya_obj::maps::Map)>>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet<usize>) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError>
+pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator<Item = (&'a str, std::os::fd::raw::RawFd, &'a aya_obj::maps::Map)>>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet<usize>) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError>
 impl core::clone::Clone for aya_obj::Object
 pub fn aya_obj::Object::clone(&self) -> aya_obj::Object
 impl core::fmt::Debug for aya_obj::Object
@@ -6684,7 +6684,7 @@ impl aya_obj::Object
 pub fn aya_obj::Object::relocate_btf(&mut self, target_btf: &aya_obj::btf::Btf) -> core::result::Result<(), aya_obj::btf::BtfRelocationError>
 impl aya_obj::Object
 pub fn aya_obj::Object::relocate_calls(&mut self, text_sections: &std::collections::hash::set::HashSet<usize>) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError>
-pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator<Item = (&'a str, i32, &'a aya_obj::maps::Map)>>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet<usize>) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError>
+pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator<Item = (&'a str, std::os::fd::raw::RawFd, &'a aya_obj::maps::Map)>>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet<usize>) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError>
 impl core::clone::Clone for aya_obj::Object
 pub fn aya_obj::Object::clone(&self) -> aya_obj::Object
 impl core::fmt::Debug for aya_obj::Object

+ 15 - 26
xtask/public-api/aya.txt

@@ -559,7 +559,7 @@ pub fn aya::maps::queue::Queue<T, V>::from(t: T) -> T
 pub mod aya::maps::sock
 pub struct aya::maps::sock::SockHash<T, K>
 impl<T: core::borrow::Borrow<aya::maps::MapData>, K: aya::Pod> aya::maps::SockHash<T, K>
-pub fn aya::maps::SockHash<T, K>::fd(&self) -> core::result::Result<aya::maps::sock::SockMapFd, aya::maps::MapError>
+pub fn aya::maps::SockHash<T, K>::fd(&self) -> &aya::maps::sock::SockMapFd
 pub fn aya::maps::SockHash<T, K>::get(&self, key: &K, flags: u64) -> core::result::Result<std::os::fd::raw::RawFd, aya::maps::MapError>
 pub fn aya::maps::SockHash<T, K>::iter(&self) -> aya::maps::MapIter<'_, K, std::os::fd::raw::RawFd, Self>
 pub fn aya::maps::SockHash<T, K>::keys(&self) -> aya::maps::MapKeys<'_, K>
@@ -601,7 +601,7 @@ impl<T> core::convert::From<T> for aya::maps::SockHash<T, K>
 pub fn aya::maps::SockHash<T, K>::from(t: T) -> T
 pub struct aya::maps::sock::SockMap<T>
 impl<T: core::borrow::Borrow<aya::maps::MapData>> aya::maps::SockMap<T>
-pub fn aya::maps::SockMap<T>::fd(&self) -> core::result::Result<aya::maps::sock::SockMapFd, aya::maps::MapError>
+pub fn aya::maps::SockMap<T>::fd(&self) -> &aya::maps::sock::SockMapFd
 pub fn aya::maps::SockMap<T>::indices(&self) -> aya::maps::MapKeys<'_, u32>
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::SockMap<T>
 pub fn aya::maps::SockMap<T>::clear_index(&mut self, index: &u32) -> core::result::Result<(), aya::maps::MapError>
@@ -636,12 +636,11 @@ impl<T> core::borrow::BorrowMut<T> for aya::maps::SockMap<T> where T: core::mark
 pub fn aya::maps::SockMap<T>::borrow_mut(&mut self) -> &mut T
 impl<T> core::convert::From<T> for aya::maps::SockMap<T>
 pub fn aya::maps::SockMap<T>::from(t: T) -> T
-pub struct aya::maps::sock::SockMapFd(_)
+#[repr(transparent)] pub struct aya::maps::sock::SockMapFd(_)
+impl aya::maps::sock::SockMapFd
+pub fn aya::maps::sock::SockMapFd::try_clone(&self) -> std::io::error::Result<Self>
 impl std::os::fd::owned::AsFd for aya::maps::sock::SockMapFd
 pub fn aya::maps::sock::SockMapFd::as_fd(&self) -> std::os::fd::owned::BorrowedFd<'_>
-impl core::clone::Clone for aya::maps::sock::SockMapFd
-pub fn aya::maps::sock::SockMapFd::clone(&self) -> aya::maps::sock::SockMapFd
-impl core::marker::Copy for aya::maps::sock::SockMapFd
 impl core::marker::Send for aya::maps::sock::SockMapFd
 impl core::marker::Sync for aya::maps::sock::SockMapFd
 impl core::marker::Unpin for aya::maps::sock::SockMapFd
@@ -655,10 +654,6 @@ pub fn aya::maps::sock::SockMapFd::try_from(value: U) -> core::result::Result<T,
 impl<T, U> core::convert::TryInto<U> for aya::maps::sock::SockMapFd where U: core::convert::TryFrom<T>
 pub type aya::maps::sock::SockMapFd::Error = <U as core::convert::TryFrom<T>>::Error
 pub fn aya::maps::sock::SockMapFd::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error>
-impl<T> alloc::borrow::ToOwned for aya::maps::sock::SockMapFd where T: core::clone::Clone
-pub type aya::maps::sock::SockMapFd::Owned = T
-pub fn aya::maps::sock::SockMapFd::clone_into(&self, target: &mut T)
-pub fn aya::maps::sock::SockMapFd::to_owned(&self) -> T
 impl<T> core::any::Any for aya::maps::sock::SockMapFd where T: 'static + core::marker::Sized
 pub fn aya::maps::sock::SockMapFd::type_id(&self) -> core::any::TypeId
 impl<T> core::borrow::Borrow<T> for aya::maps::sock::SockMapFd where T: core::marker::Sized
@@ -1226,13 +1221,9 @@ pub struct aya::maps::MapData
 pub aya::maps::MapData::pinned: bool
 impl aya::maps::MapData
 pub fn aya::maps::MapData::create(obj: aya_obj::maps::Map, name: &str, btf_fd: core::option::Option<std::os::fd::owned::BorrowedFd<'_>>) -> core::result::Result<Self, aya::maps::MapError>
-pub fn aya::maps::MapData::fd(&self) -> aya::maps::MapFd
+pub fn aya::maps::MapData::fd(&self) -> &aya::maps::MapFd
 pub fn aya::maps::MapData::from_fd(fd: std::os::fd::owned::OwnedFd) -> core::result::Result<Self, aya::maps::MapError>
 pub fn aya::maps::MapData::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::maps::MapError>
-impl core::clone::Clone for aya::maps::MapData
-pub fn aya::maps::MapData::clone(&self) -> Self
-impl core::ops::drop::Drop for aya::maps::MapData
-pub fn aya::maps::MapData::drop(&mut self)
 impl core::fmt::Debug for aya::maps::MapData
 pub fn aya::maps::MapData::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
 impl core::marker::Send for aya::maps::MapData
@@ -1248,10 +1239,6 @@ pub fn aya::maps::MapData::try_from(value: U) -> core::result::Result<T, <T as c
 impl<T, U> core::convert::TryInto<U> for aya::maps::MapData where U: core::convert::TryFrom<T>
 pub type aya::maps::MapData::Error = <U as core::convert::TryFrom<T>>::Error
 pub fn aya::maps::MapData::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error>
-impl<T> alloc::borrow::ToOwned for aya::maps::MapData where T: core::clone::Clone
-pub type aya::maps::MapData::Owned = T
-pub fn aya::maps::MapData::clone_into(&self, target: &mut T)
-pub fn aya::maps::MapData::to_owned(&self) -> T
 impl<T> core::any::Any for aya::maps::MapData where T: 'static + core::marker::Sized
 pub fn aya::maps::MapData::type_id(&self) -> core::any::TypeId
 impl<T> core::borrow::Borrow<T> for aya::maps::MapData where T: core::marker::Sized
@@ -1261,8 +1248,10 @@ pub fn aya::maps::MapData::borrow_mut(&mut self) -> &mut T
 impl<T> core::convert::From<T> for aya::maps::MapData
 pub fn aya::maps::MapData::from(t: T) -> T
 pub struct aya::maps::MapFd(_)
-impl std::os::fd::raw::AsRawFd for aya::maps::MapFd
-pub fn aya::maps::MapFd::as_raw_fd(&self) -> std::os::fd::raw::RawFd
+impl std::os::fd::owned::AsFd for aya::maps::MapFd
+pub fn aya::maps::MapFd::as_fd(&self) -> std::os::fd::owned::BorrowedFd<'_>
+impl core::fmt::Debug for aya::maps::MapFd
+pub fn aya::maps::MapFd::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
 impl core::marker::Send for aya::maps::MapFd
 impl core::marker::Sync for aya::maps::MapFd
 impl core::marker::Unpin for aya::maps::MapFd
@@ -1566,7 +1555,7 @@ impl<T> core::convert::From<T> for aya::maps::queue::Queue<T, V>
 pub fn aya::maps::queue::Queue<T, V>::from(t: T) -> T
 pub struct aya::maps::SockHash<T, K>
 impl<T: core::borrow::Borrow<aya::maps::MapData>, K: aya::Pod> aya::maps::SockHash<T, K>
-pub fn aya::maps::SockHash<T, K>::fd(&self) -> core::result::Result<aya::maps::sock::SockMapFd, aya::maps::MapError>
+pub fn aya::maps::SockHash<T, K>::fd(&self) -> &aya::maps::sock::SockMapFd
 pub fn aya::maps::SockHash<T, K>::get(&self, key: &K, flags: u64) -> core::result::Result<std::os::fd::raw::RawFd, aya::maps::MapError>
 pub fn aya::maps::SockHash<T, K>::iter(&self) -> aya::maps::MapIter<'_, K, std::os::fd::raw::RawFd, Self>
 pub fn aya::maps::SockHash<T, K>::keys(&self) -> aya::maps::MapKeys<'_, K>
@@ -1608,7 +1597,7 @@ impl<T> core::convert::From<T> for aya::maps::SockHash<T, K>
 pub fn aya::maps::SockHash<T, K>::from(t: T) -> T
 pub struct aya::maps::SockMap<T>
 impl<T: core::borrow::Borrow<aya::maps::MapData>> aya::maps::SockMap<T>
-pub fn aya::maps::SockMap<T>::fd(&self) -> core::result::Result<aya::maps::sock::SockMapFd, aya::maps::MapError>
+pub fn aya::maps::SockMap<T>::fd(&self) -> &aya::maps::sock::SockMapFd
 pub fn aya::maps::SockMap<T>::indices(&self) -> aya::maps::MapKeys<'_, u32>
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::SockMap<T>
 pub fn aya::maps::SockMap<T>::clear_index(&mut self, index: &u32) -> core::result::Result<(), aya::maps::MapError>
@@ -6190,7 +6179,7 @@ impl<T> core::convert::From<T> for aya::programs::perf_event::PerfEvent
 pub fn aya::programs::perf_event::PerfEvent::from(t: T) -> T
 pub struct aya::programs::ProgramFd(_)
 impl aya::programs::ProgramFd
-pub fn aya::programs::ProgramFd::try_clone(&self) -> core::result::Result<Self, aya::programs::ProgramError>
+pub fn aya::programs::ProgramFd::try_clone(&self) -> std::io::error::Result<Self>
 impl std::os::fd::owned::AsFd for aya::programs::ProgramFd
 pub fn aya::programs::ProgramFd::as_fd(&self) -> std::os::fd::owned::BorrowedFd<'_>
 impl core::fmt::Debug for aya::programs::ProgramFd
@@ -6402,7 +6391,7 @@ impl<T> core::convert::From<T> for aya::programs::SkLookup
 pub fn aya::programs::SkLookup::from(t: T) -> T
 pub struct aya::programs::SkMsg
 impl aya::programs::SkMsg
-pub fn aya::programs::SkMsg::attach(&mut self, map: aya::maps::sock::SockMapFd) -> core::result::Result<SkMsgLinkId, aya::programs::ProgramError>
+pub fn aya::programs::SkMsg::attach(&mut self, map: &aya::maps::sock::SockMapFd) -> core::result::Result<SkMsgLinkId, aya::programs::ProgramError>
 pub fn aya::programs::SkMsg::detach(&mut self, link_id: SkMsgLinkId) -> core::result::Result<(), aya::programs::ProgramError>
 pub fn aya::programs::SkMsg::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
 pub fn aya::programs::SkMsg::take_link(&mut self, link_id: SkMsgLinkId) -> core::result::Result<SkMsgLink, aya::programs::ProgramError>
@@ -6450,7 +6439,7 @@ impl<T> core::convert::From<T> for aya::programs::SkMsg
 pub fn aya::programs::SkMsg::from(t: T) -> T
 pub struct aya::programs::SkSkb
 impl aya::programs::SkSkb
-pub fn aya::programs::SkSkb::attach(&mut self, map: aya::maps::sock::SockMapFd) -> core::result::Result<SkSkbLinkId, aya::programs::ProgramError>
+pub fn aya::programs::SkSkb::attach(&mut self, map: &aya::maps::sock::SockMapFd) -> core::result::Result<SkSkbLinkId, aya::programs::ProgramError>
 pub fn aya::programs::SkSkb::detach(&mut self, link_id: SkSkbLinkId) -> core::result::Result<(), aya::programs::ProgramError>
 pub fn aya::programs::SkSkb::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P, kind: aya::programs::SkSkbKind) -> core::result::Result<Self, aya::programs::ProgramError>
 pub fn aya::programs::SkSkb::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError>