diff --git a/aya/src/maps/array/program_array.rs b/aya/src/maps/array/program_array.rs index 0ceff2b9..e74b0856 100644 --- a/aya/src/maps/array/program_array.rs +++ b/aya/src/maps/array/program_array.rs @@ -4,7 +4,7 @@ use std::{ convert::TryFrom, mem, ops::{Deref, DerefMut}, - os::unix::prelude::RawFd, + os::unix::prelude::{AsRawFd, RawFd}, }; use crate::{ @@ -26,26 +26,28 @@ use crate::{ /// /// # Examples /// ```no_run -/// # let bpf = aya::Bpf::load(&[])?; +/// # let mut bpf = aya::Bpf::load(&[])?; /// use aya::maps::ProgramArray; -/// use aya::programs::{CgroupSkb, ProgramFd}; +/// use aya::programs::CgroupSkb; /// use std::convert::{TryFrom, TryInto}; /// /// let mut prog_array = ProgramArray::try_from(bpf.map_mut("JUMP_TABLE")?)?; /// let prog_0: &CgroupSkb = bpf.program("example_prog_0").unwrap().try_into()?; +/// let prog_0_fd = prog_0.fd().unwrap(); /// let prog_1: &CgroupSkb = bpf.program("example_prog_1").unwrap().try_into()?; +/// let prog_1_fd = prog_1.fd().unwrap(); /// let prog_2: &CgroupSkb = bpf.program("example_prog_2").unwrap().try_into()?; -/// +/// let prog_2_fd = prog_2.fd().unwrap(); /// let flags = 0; /// /// // bpf_tail_call(ctx, JUMP_TABLE, 0) will jump to prog_0 -/// prog_array.set(0, prog_0, flags); +/// prog_array.set(0, prog_0_fd, flags); /// /// // bpf_tail_call(ctx, JUMP_TABLE, 1) will jump to prog_1 -/// prog_array.set(1, prog_1, flags); +/// prog_array.set(1, prog_1_fd, flags); /// /// // bpf_tail_call(ctx, JUMP_TABLE, 2) will jump to prog_2 -/// prog_array.set(2, prog_2, flags); +/// prog_array.set(2, prog_2_fd, flags); /// # Ok::<(), aya::BpfError>(()) /// ``` #[doc(alias = "BPF_MAP_TYPE_PROG_ARRAY")] @@ -98,10 +100,10 @@ impl + DerefMut> ProgramArray { /// /// When an eBPF program calls `bpf_tail_call(ctx, prog_array, index)`, control /// flow will jump to `program`. - pub fn set(&mut self, index: u32, program: impl ProgramFd, flags: u64) -> Result<(), MapError> { + pub fn set(&mut self, index: u32, program: ProgramFd, flags: u64) -> Result<(), MapError> { let fd = self.inner.fd_or_err()?; self.check_bounds(index)?; - let prog_fd = program.fd().ok_or(MapError::ProgramNotLoaded)?; + let prog_fd = program.as_raw_fd(); bpf_map_update_elem(fd, &index, &prog_fd, flags).map_err(|(code, io_error)| { MapError::SyscallError { diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 5a7138d6..b2f3fe7a 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -214,10 +214,14 @@ pub enum ProgramError { }, } -/// Allows the Fd of a loaded [`Program`] to be retrieved -pub trait ProgramFd { - /// Returns the [`RawFd`] of the program if it has been loaded, or `None` - fn fd(&self) -> Option; +/// A [`Program`] file descriptor. +#[derive(Copy, Clone)] +pub struct ProgramFd(RawFd); + +impl AsRawFd for ProgramFd { + fn as_raw_fd(&self) -> RawFd { + self.0 + } } /// eBPF program type. @@ -359,6 +363,38 @@ impl Program { Program::CgroupSock(p) => p.unload(), } } + + /// Returns the file descriptor of a program. + /// + /// Can be used to add a program to a [`crate::maps::ProgramArray`] or attach an [`Extension`] program. + /// Can be converted to [`RawFd`] using [`AsRawFd`]. + pub fn fd(&self) -> Option { + match self { + Program::KProbe(p) => p.fd(), + Program::UProbe(p) => p.fd(), + Program::TracePoint(p) => p.fd(), + Program::SocketFilter(p) => p.fd(), + Program::Xdp(p) => p.fd(), + Program::SkMsg(p) => p.fd(), + Program::SkSkb(p) => p.fd(), + Program::SockOps(p) => p.fd(), + Program::SchedClassifier(p) => p.fd(), + Program::CgroupSkb(p) => p.fd(), + Program::CgroupSysctl(p) => p.fd(), + Program::CgroupSockopt(p) => p.fd(), + Program::LircMode2(p) => p.fd(), + Program::PerfEvent(p) => p.fd(), + Program::RawTracePoint(p) => p.fd(), + Program::Lsm(p) => p.fd(), + Program::BtfTracePoint(p) => p.fd(), + Program::FEntry(p) => p.fd(), + Program::FExit(p) => p.fd(), + Program::Extension(p) => p.fd(), + Program::CgroupSockAddr(p) => p.fd(), + Program::SkLookup(p) => p.fd(), + Program::CgroupSock(p) => p.fd(), + } + } } impl Drop for Program { @@ -555,42 +591,6 @@ pub(crate) fn query( } } -impl ProgramFd for Program { - fn fd(&self) -> Option { - match self { - Program::KProbe(p) => p.data.fd, - Program::UProbe(p) => p.data.fd, - Program::TracePoint(p) => p.data.fd, - Program::SocketFilter(p) => p.data.fd, - Program::Xdp(p) => p.data.fd, - Program::SkMsg(p) => p.data.fd, - Program::SkSkb(p) => p.data.fd, - Program::SockOps(p) => p.data.fd, - Program::SchedClassifier(p) => p.data.fd, - Program::CgroupSkb(p) => p.data.fd, - Program::CgroupSysctl(p) => p.data.fd, - Program::CgroupSockopt(p) => p.data.fd, - Program::LircMode2(p) => p.data.fd, - Program::PerfEvent(p) => p.data.fd, - Program::RawTracePoint(p) => p.data.fd, - Program::Lsm(p) => p.data.fd, - Program::BtfTracePoint(p) => p.data.fd, - Program::FEntry(p) => p.data.fd, - Program::FExit(p) => p.data.fd, - Program::Extension(p) => p.data.fd, - Program::CgroupSockAddr(p) => p.data.fd, - Program::SkLookup(p) => p.data.fd, - Program::CgroupSock(p) => p.data.fd, - } - } -} - -impl<'a, P: ProgramFd> ProgramFd for &'a P { - fn fd(&self) -> Option { - (*self).fd() - } -} - macro_rules! impl_program_unload { ($($struct_name:ident),+ $(,)?) => { $( @@ -634,25 +634,20 @@ impl_program_unload!( CgroupSock, ); -macro_rules! impl_program_fd { +macro_rules! impl_fd { ($($struct_name:ident),+ $(,)?) => { $( - impl ProgramFd for $struct_name { - fn fd(&self) -> Option { - self.data.fd - } - } - - impl ProgramFd for &mut $struct_name { - fn fd(&self) -> Option { - self.data.fd + impl $struct_name { + /// Returns the file descriptor of this Program. + pub fn fd(&self) -> Option { + self.data.fd.map(|fd| ProgramFd(fd)) } } )+ } } -impl_program_fd!( +impl_fd!( KProbe, UProbe, TracePoint, @@ -674,6 +669,7 @@ impl_program_fd!( Extension, CgroupSockAddr, SkLookup, + SockOps, CgroupSock, );