From d613514b3d3fdc2b131001bf55be43d4b67bd296 Mon Sep 17 00:00:00 2001 From: Harvo Jones Date: Thu, 25 Jul 2024 22:02:42 +0000 Subject: [PATCH] Add support for `CgroupAttachFlags`. This change allows an eBPF program to attach when an existing program is in place, such as via the "ALLOW_MULTI" flag. --- aya/src/maps/mod.rs | 4 +-- aya/src/maps/sock/sock_hash.rs | 4 +-- aya/src/maps/sock/sock_map.rs | 4 +-- aya/src/programs/cgroup_device.rs | 18 ++++++----- aya/src/programs/cgroup_skb.rs | 26 ++++++++++------ aya/src/programs/cgroup_sock.rs | 31 ++++++++++++------- aya/src/programs/cgroup_sock_addr.rs | 31 ++++++++++++------- aya/src/programs/cgroup_sockopt.rs | 31 ++++++++++++------- aya/src/programs/cgroup_sysctl.rs | 17 +++++++---- aya/src/programs/links.rs | 31 +++++++++++++++++-- aya/src/programs/lirc_mode2.rs | 22 ++++++++++---- aya/src/programs/mod.rs | 2 +- aya/src/programs/sk_msg.rs | 16 ++++++---- aya/src/programs/sk_skb.rs | 16 ++++++---- aya/src/programs/sock_ops.rs | 21 +++++++++---- aya/src/sys/bpf.rs | 45 ++++++++++++++++++++++++++++ 16 files changed, 234 insertions(+), 85 deletions(-) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 82467aee8..a4394a8be 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -31,13 +31,13 @@ //! # } //! # let mut bpf = aya::Ebpf::load(&[])?; //! use aya::maps::SockMap; -//! use aya::programs::SkMsg; +//! use aya::programs::{CgroupAttachFlags, SkMsg}; //! //! let intercept_egress = SockMap::try_from(bpf.map_mut("INTERCEPT_EGRESS").unwrap())?; //! 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, CgroupAttachFlags::empty())?; //! //! # Ok::<(), Error>(()) //! ``` diff --git a/aya/src/maps/sock/sock_hash.rs b/aya/src/maps/sock/sock_hash.rs index 9be05ee4b..aff8a9ef0 100644 --- a/aya/src/maps/sock/sock_hash.rs +++ b/aya/src/maps/sock/sock_hash.rs @@ -45,14 +45,14 @@ use crate::{ /// use std::net::TcpStream; /// use std::os::fd::AsRawFd; /// use aya::maps::SockHash; -/// use aya::programs::SkMsg; +/// use aya::programs::{CgroupAttachFlags, SkMsg}; /// /// let mut intercept_egress = SockHash::<_, u32>::try_from(bpf.map("INTERCEPT_EGRESS").unwrap())?; /// 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, CgroupAttachFlags::empty())?; /// /// let mut client = TcpStream::connect("127.0.0.1:1234")?; /// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS").unwrap())?; diff --git a/aya/src/maps/sock/sock_map.rs b/aya/src/maps/sock/sock_map.rs index f0590467e..87b25a92c 100644 --- a/aya/src/maps/sock/sock_map.rs +++ b/aya/src/maps/sock/sock_map.rs @@ -39,14 +39,14 @@ use crate::{ /// # } /// # let mut bpf = aya::Ebpf::load(&[])?; /// use aya::maps::SockMap; -/// use aya::programs::SkSkb; +/// use aya::programs::{CgroupAttachFlags, SkSkb}; /// /// let intercept_ingress = SockMap::try_from(bpf.map("INTERCEPT_INGRESS").unwrap())?; /// 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, CgroupAttachFlags::empty())?; /// /// # Ok::<(), Error>(()) /// ``` diff --git a/aya/src/programs/cgroup_device.rs b/aya/src/programs/cgroup_device.rs index 152637911..ca5383f01 100644 --- a/aya/src/programs/cgroup_device.rs +++ b/aya/src/programs/cgroup_device.rs @@ -5,8 +5,8 @@ use std::os::fd::AsFd; use crate::{ generated::{bpf_attach_type::BPF_CGROUP_DEVICE, bpf_prog_type::BPF_PROG_TYPE_CGROUP_DEVICE}, programs::{ - bpf_prog_get_fd_by_id, define_link_wrapper, load_program, query, FdLink, Link, - ProgAttachLink, ProgramData, ProgramError, ProgramFd, + bpf_prog_get_fd_by_id, define_link_wrapper, load_program, query, CgroupAttachFlags, FdLink, + Link, ProgAttachLink, ProgramData, ProgramError, ProgramFd, }, sys::{bpf_link_create, LinkTarget, SyscallError}, util::KernelVersion, @@ -38,12 +38,12 @@ use crate::{ /// # Ebpf(#[from] aya::EbpfError) /// # } /// # let mut bpf = aya::Ebpf::load(&[])?; -/// use aya::programs::CgroupDevice; +/// use aya::programs::{CgroupAttachFlags, CgroupDevice}; /// /// let cgroup = std::fs::File::open("/sys/fs/cgroup/unified")?; /// let program: &mut CgroupDevice = bpf.program_mut("cgroup_dev").unwrap().try_into()?; /// program.load()?; -/// program.attach(cgroup)?; +/// program.attach(cgroup, CgroupAttachFlags::empty())?; /// # Ok::<(), Error>(()) /// ``` #[derive(Debug)] @@ -61,7 +61,11 @@ impl CgroupDevice { /// Attaches the program to the given cgroup. /// /// The returned value can be used to detach, see [CgroupDevice::detach] - pub fn attach(&mut self, cgroup: T) -> Result { + pub fn attach( + &mut self, + cgroup: T, + flags: CgroupAttachFlags, + ) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); let cgroup_fd = cgroup.as_fd(); @@ -72,7 +76,7 @@ impl CgroupDevice { LinkTarget::Fd(cgroup_fd), BPF_CGROUP_DEVICE, None, - 0, + flags.bits(), ) .map_err(|(_, io_error)| SyscallError { call: "bpf_link_create", @@ -84,7 +88,7 @@ impl CgroupDevice { FdLink::new(link_fd), ))) } else { - let link = ProgAttachLink::attach(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE)?; + let link = ProgAttachLink::attach(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE, flags.bits())?; self.data .links diff --git a/aya/src/programs/cgroup_skb.rs b/aya/src/programs/cgroup_skb.rs index 847494233..2128ab850 100644 --- a/aya/src/programs/cgroup_skb.rs +++ b/aya/src/programs/cgroup_skb.rs @@ -8,7 +8,8 @@ use crate::{ bpf_prog_type::BPF_PROG_TYPE_CGROUP_SKB, }, programs::{ - define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError, + define_link_wrapper, load_program, CgroupAttachFlags, FdLink, Link, ProgAttachLink, + ProgramData, ProgramError, }, sys::{bpf_link_create, LinkTarget, SyscallError}, util::KernelVersion, @@ -43,12 +44,12 @@ use crate::{ /// # } /// # let mut bpf = aya::Ebpf::load(&[])?; /// use std::fs::File; -/// use aya::programs::{CgroupSkb, CgroupSkbAttachType}; +/// use aya::programs::{CgroupAttachFlags, CgroupSkb, CgroupSkbAttachType}; /// /// let file = File::open("/sys/fs/cgroup/unified")?; /// let egress: &mut CgroupSkb = bpf.program_mut("egress_filter").unwrap().try_into()?; /// egress.load()?; -/// egress.attach(file, CgroupSkbAttachType::Egress)?; +/// egress.attach(file, CgroupSkbAttachType::Egress, CgroupAttachFlags::empty())?; /// # Ok::<(), Error>(()) /// ``` #[derive(Debug)] @@ -87,6 +88,7 @@ impl CgroupSkb { &mut self, cgroup: T, attach_type: CgroupSkbAttachType, + flags: CgroupAttachFlags, ) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); @@ -97,18 +99,24 @@ impl CgroupSkb { CgroupSkbAttachType::Egress => BPF_CGROUP_INET_EGRESS, }; if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, LinkTarget::Fd(cgroup_fd), attach_type, None, 0) - .map_err(|(_, io_error)| SyscallError { - call: "bpf_link_create", - io_error, - })?; + let link_fd = bpf_link_create( + prog_fd, + LinkTarget::Fd(cgroup_fd), + attach_type, + None, + flags.bits(), + ) + .map_err(|(_, io_error)| SyscallError { + call: "bpf_link_create", + io_error, + })?; self.data .links .insert(CgroupSkbLink::new(CgroupSkbLinkInner::Fd(FdLink::new( link_fd, )))) } else { - let link = ProgAttachLink::attach(prog_fd, cgroup_fd, attach_type)?; + let link = ProgAttachLink::attach(prog_fd, cgroup_fd, attach_type, flags.bits())?; self.data .links diff --git a/aya/src/programs/cgroup_sock.rs b/aya/src/programs/cgroup_sock.rs index 24f078697..cf8e5dc8e 100644 --- a/aya/src/programs/cgroup_sock.rs +++ b/aya/src/programs/cgroup_sock.rs @@ -7,7 +7,8 @@ pub use aya_obj::programs::CgroupSockAttachType; use crate::{ generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCK, programs::{ - define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError, + define_link_wrapper, load_program, CgroupAttachFlags, FdLink, Link, ProgAttachLink, + ProgramData, ProgramError, }, sys::{bpf_link_create, LinkTarget, SyscallError}, util::KernelVersion, @@ -41,12 +42,12 @@ use crate::{ /// # } /// # let mut bpf = aya::Ebpf::load(&[])?; /// use std::fs::File; -/// use aya::programs::{CgroupSock, CgroupSockAttachType}; +/// use aya::programs::{CgroupAttachFlags, CgroupSock, CgroupSockAttachType}; /// /// let file = File::open("/sys/fs/cgroup/unified")?; /// let bind: &mut CgroupSock = bpf.program_mut("bind").unwrap().try_into()?; /// bind.load()?; -/// bind.attach(file)?; +/// bind.attach(file, CgroupAttachFlags::empty())?; /// # Ok::<(), Error>(()) /// ``` #[derive(Debug)] @@ -66,24 +67,34 @@ impl CgroupSock { /// Attaches the program to the given cgroup. /// /// The returned value can be used to detach, see [CgroupSock::detach]. - pub fn attach(&mut self, cgroup: T) -> Result { + pub fn attach( + &mut self, + cgroup: T, + flags: CgroupAttachFlags, + ) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); let cgroup_fd = cgroup.as_fd(); let attach_type = self.data.expected_attach_type.unwrap(); if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, LinkTarget::Fd(cgroup_fd), attach_type, None, 0) - .map_err(|(_, io_error)| SyscallError { - call: "bpf_link_create", - io_error, - })?; + let link_fd = bpf_link_create( + prog_fd, + LinkTarget::Fd(cgroup_fd), + attach_type, + None, + flags.bits(), + ) + .map_err(|(_, io_error)| SyscallError { + call: "bpf_link_create", + io_error, + })?; self.data .links .insert(CgroupSockLink::new(CgroupSockLinkInner::Fd(FdLink::new( link_fd, )))) } else { - let link = ProgAttachLink::attach(prog_fd, cgroup_fd, attach_type)?; + let link = ProgAttachLink::attach(prog_fd, cgroup_fd, attach_type, flags.bits())?; self.data .links diff --git a/aya/src/programs/cgroup_sock_addr.rs b/aya/src/programs/cgroup_sock_addr.rs index 79b607ca5..254e5c63c 100644 --- a/aya/src/programs/cgroup_sock_addr.rs +++ b/aya/src/programs/cgroup_sock_addr.rs @@ -7,7 +7,8 @@ pub use aya_obj::programs::CgroupSockAddrAttachType; use crate::{ generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCK_ADDR, programs::{ - define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError, + define_link_wrapper, load_program, CgroupAttachFlags, FdLink, Link, ProgAttachLink, + ProgramData, ProgramError, }, sys::{bpf_link_create, LinkTarget, SyscallError}, util::KernelVersion, @@ -42,12 +43,12 @@ use crate::{ /// # } /// # let mut bpf = aya::Ebpf::load(&[])?; /// use std::fs::File; -/// use aya::programs::{CgroupSockAddr, CgroupSockAddrAttachType}; +/// use aya::programs::{CgroupAttachFlags, CgroupSockAddr, CgroupSockAddrAttachType}; /// /// let file = File::open("/sys/fs/cgroup/unified")?; /// let egress: &mut CgroupSockAddr = bpf.program_mut("connect4").unwrap().try_into()?; /// egress.load()?; -/// egress.attach(file)?; +/// egress.attach(file, CgroupAttachFlags::empty())?; /// # Ok::<(), Error>(()) /// ``` #[derive(Debug)] @@ -67,24 +68,34 @@ impl CgroupSockAddr { /// Attaches the program to the given cgroup. /// /// The returned value can be used to detach, see [CgroupSockAddr::detach]. - pub fn attach(&mut self, cgroup: T) -> Result { + pub fn attach( + &mut self, + cgroup: T, + flags: CgroupAttachFlags, + ) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); let cgroup_fd = cgroup.as_fd(); let attach_type = self.data.expected_attach_type.unwrap(); if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, LinkTarget::Fd(cgroup_fd), attach_type, None, 0) - .map_err(|(_, io_error)| SyscallError { - call: "bpf_link_create", - io_error, - })?; + let link_fd = bpf_link_create( + prog_fd, + LinkTarget::Fd(cgroup_fd), + attach_type, + None, + flags.bits(), + ) + .map_err(|(_, io_error)| SyscallError { + call: "bpf_link_create", + io_error, + })?; self.data .links .insert(CgroupSockAddrLink::new(CgroupSockAddrLinkInner::Fd( FdLink::new(link_fd), ))) } else { - let link = ProgAttachLink::attach(prog_fd, cgroup_fd, attach_type)?; + let link = ProgAttachLink::attach(prog_fd, cgroup_fd, attach_type, flags.bits())?; self.data.links.insert(CgroupSockAddrLink::new( CgroupSockAddrLinkInner::ProgAttach(link), diff --git a/aya/src/programs/cgroup_sockopt.rs b/aya/src/programs/cgroup_sockopt.rs index 414fece6d..b1cf5c230 100644 --- a/aya/src/programs/cgroup_sockopt.rs +++ b/aya/src/programs/cgroup_sockopt.rs @@ -7,7 +7,8 @@ pub use aya_obj::programs::CgroupSockoptAttachType; use crate::{ generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCKOPT, programs::{ - define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError, + define_link_wrapper, load_program, CgroupAttachFlags, FdLink, Link, ProgAttachLink, + ProgramData, ProgramError, }, sys::{bpf_link_create, LinkTarget, SyscallError}, util::KernelVersion, @@ -39,12 +40,12 @@ use crate::{ /// # } /// # let mut bpf = aya::Ebpf::load(&[])?; /// use std::fs::File; -/// use aya::programs::CgroupSockopt; +/// use aya::programs::{CgroupAttachFlags, CgroupSockopt}; /// /// let file = File::open("/sys/fs/cgroup/unified")?; /// let program: &mut CgroupSockopt = bpf.program_mut("cgroup_sockopt").unwrap().try_into()?; /// program.load()?; -/// program.attach(file)?; +/// program.attach(file, CgroupAttachFlags::empty())?; /// # Ok::<(), Error>(()) /// ``` #[derive(Debug)] @@ -64,24 +65,34 @@ impl CgroupSockopt { /// Attaches the program to the given cgroup. /// /// The returned value can be used to detach, see [CgroupSockopt::detach]. - pub fn attach(&mut self, cgroup: T) -> Result { + pub fn attach( + &mut self, + cgroup: T, + flags: CgroupAttachFlags, + ) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); let cgroup_fd = cgroup.as_fd(); let attach_type = self.data.expected_attach_type.unwrap(); if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { - let link_fd = bpf_link_create(prog_fd, LinkTarget::Fd(cgroup_fd), attach_type, None, 0) - .map_err(|(_, io_error)| SyscallError { - call: "bpf_link_create", - io_error, - })?; + let link_fd = bpf_link_create( + prog_fd, + LinkTarget::Fd(cgroup_fd), + attach_type, + None, + flags.bits(), + ) + .map_err(|(_, io_error)| SyscallError { + call: "bpf_link_create", + io_error, + })?; self.data .links .insert(CgroupSockoptLink::new(CgroupSockoptLinkInner::Fd( FdLink::new(link_fd), ))) } else { - let link = ProgAttachLink::attach(prog_fd, cgroup_fd, attach_type)?; + let link = ProgAttachLink::attach(prog_fd, cgroup_fd, attach_type, flags.bits())?; self.data .links diff --git a/aya/src/programs/cgroup_sysctl.rs b/aya/src/programs/cgroup_sysctl.rs index 617e3dd88..ba9460a00 100644 --- a/aya/src/programs/cgroup_sysctl.rs +++ b/aya/src/programs/cgroup_sysctl.rs @@ -5,7 +5,8 @@ use std::{hash::Hash, os::fd::AsFd}; use crate::{ generated::{bpf_attach_type::BPF_CGROUP_SYSCTL, bpf_prog_type::BPF_PROG_TYPE_CGROUP_SYSCTL}, programs::{ - define_link_wrapper, load_program, FdLink, Link, ProgAttachLink, ProgramData, ProgramError, + define_link_wrapper, load_program, CgroupAttachFlags, FdLink, Link, ProgAttachLink, + ProgramData, ProgramError, }, sys::{bpf_link_create, LinkTarget, SyscallError}, util::KernelVersion, @@ -36,12 +37,12 @@ use crate::{ /// # } /// # let mut bpf = aya::Ebpf::load(&[])?; /// use std::fs::File; -/// use aya::programs::CgroupSysctl; +/// use aya::programs::{CgroupAttachFlags, CgroupSysctl}; /// /// let file = File::open("/sys/fs/cgroup/unified")?; /// let program: &mut CgroupSysctl = bpf.program_mut("cgroup_sysctl").unwrap().try_into()?; /// program.load()?; -/// program.attach(file)?; +/// program.attach(file, CgroupAttachFlags::empty())?; /// # Ok::<(), Error>(()) /// ``` #[derive(Debug)] @@ -59,7 +60,11 @@ impl CgroupSysctl { /// Attaches the program to the given cgroup. /// /// The returned value can be used to detach, see [CgroupSysctl::detach]. - pub fn attach(&mut self, cgroup: T) -> Result { + pub fn attach( + &mut self, + cgroup: T, + flags: CgroupAttachFlags, + ) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); let cgroup_fd = cgroup.as_fd(); @@ -70,7 +75,7 @@ impl CgroupSysctl { LinkTarget::Fd(cgroup_fd), BPF_CGROUP_SYSCTL, None, - 0, + flags.bits(), ) .map_err(|(_, io_error)| SyscallError { call: "bpf_link_create", @@ -82,7 +87,7 @@ impl CgroupSysctl { FdLink::new(link_fd), ))) } else { - let link = ProgAttachLink::attach(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL)?; + let link = ProgAttachLink::attach(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL, flags.bits())?; self.data .links diff --git a/aya/src/programs/links.rs b/aya/src/programs/links.rs index b809d1dce..aba6bafd2 100644 --- a/aya/src/programs/links.rs +++ b/aya/src/programs/links.rs @@ -10,7 +10,10 @@ use std::{ use thiserror::Error; use crate::{ - generated::bpf_attach_type, + generated::{ + bpf_attach_type, BPF_F_AFTER, BPF_F_ALLOW_MULTI, BPF_F_ALLOW_OVERRIDE, BPF_F_BEFORE, + BPF_F_ID, BPF_F_REPLACE, + }, pin::PinError, programs::{ProgramError, ProgramFd}, sys::{bpf_get_object, bpf_pin_object, bpf_prog_attach, bpf_prog_detach, SyscallError}, @@ -28,6 +31,17 @@ pub trait Link: std::fmt::Debug + 'static { fn detach(self) -> Result<(), ProgramError>; } +bitflags::bitflags! { + /// Program attachment flags. + #[derive(Clone, Copy, Debug, Default)] + pub struct CgroupAttachFlags: u32 { + /// Allows the eBPF program to be overridden by ones in a descendent cgroup. + const ALLOW_OVERRIDE = BPF_F_ALLOW_OVERRIDE; + /// Allows multiple eBPF programs to be attached. + const ALLOW_MULTI = BPF_F_ALLOW_MULTI; + } +} + #[derive(Debug)] pub(crate) struct LinkMap { links: HashMap, @@ -252,6 +266,7 @@ impl ProgAttachLink { prog_fd: BorrowedFd<'_>, target_fd: BorrowedFd<'_>, attach_type: bpf_attach_type, + flags: u32, ) -> Result { // The link is going to own this new file descriptor so we are // going to need a duplicate whose lifetime we manage. Let's @@ -259,7 +274,7 @@ impl ProgAttachLink { // descriptor is closed at drop in case it fails to attach. let prog_fd = prog_fd.try_clone_to_owned()?; let target_fd = target_fd.try_clone_to_owned()?; - bpf_prog_attach(prog_fd.as_fd(), target_fd.as_fd(), attach_type)?; + bpf_prog_attach(prog_fd.as_fd(), target_fd.as_fd(), attach_type, flags)?; let prog_fd = ProgramFd(prog_fd); Ok(Self { @@ -375,7 +390,10 @@ mod tests { use tempfile::tempdir; use super::{FdLink, Link, LinkMap}; - use crate::{programs::ProgramError, sys::override_syscall}; + use crate::{ + programs::{CgroupAttachFlags, ProgramError}, + sys::override_syscall, + }; #[derive(Debug, Hash, Eq, PartialEq)] struct TestLinkId(u8, u8); @@ -521,4 +539,11 @@ mod tests { pinned_link.unpin().expect("unpin failed"); assert!(!pin.exists()); } + + #[test] + fn test_cgroup_attach_flags() { + assert_eq!(CgroupAttachFlags::empty().bits(), 0); + assert!(CgroupAttachFlags::ALLOW_OVERRIDE.bits() != 0); + assert!(CgroupAttachFlags::ALLOW_MULTI.bits() != 0); + } } diff --git a/aya/src/programs/lirc_mode2.rs b/aya/src/programs/lirc_mode2.rs index cbd47d950..80412a3af 100644 --- a/aya/src/programs/lirc_mode2.rs +++ b/aya/src/programs/lirc_mode2.rs @@ -3,7 +3,10 @@ use std::os::fd::{AsFd, AsRawFd as _, OwnedFd, RawFd}; use crate::{ generated::{bpf_attach_type::BPF_LIRC_MODE2, bpf_prog_type::BPF_PROG_TYPE_LIRC_MODE2}, - programs::{load_program, query, Link, ProgramData, ProgramError, ProgramFd, ProgramInfo}, + programs::{ + load_program, query, CgroupAttachFlags, Link, ProgramData, ProgramError, ProgramFd, + ProgramInfo, + }, sys::{bpf_prog_attach, bpf_prog_detach, bpf_prog_get_fd_by_id}, }; @@ -34,13 +37,13 @@ use crate::{ /// # } /// # let mut bpf = aya::Ebpf::load(&[])?; /// use std::fs::File; -/// use aya::programs::LircMode2; +/// use aya::programs::{CgroupAttachFlags, LircMode2}; /// /// let file = File::open("/dev/lirc0")?; /// let mut bpf = aya::Ebpf::load_file("imon_rsc.o")?; /// let decoder: &mut LircMode2 = bpf.program_mut("imon_rsc").unwrap().try_into().unwrap(); /// decoder.load()?; -/// decoder.attach(file)?; +/// decoder.attach(file, CgroupAttachFlags::empty())?; /// # Ok::<(), Error>(()) /// ``` #[derive(Debug)] @@ -58,7 +61,11 @@ impl LircMode2 { /// Attaches the program to the given lirc device. /// /// The returned value can be used to detach, see [LircMode2::detach]. - pub fn attach(&mut self, lircdev: T) -> Result { + pub fn attach( + &mut self, + lircdev: T, + flags: CgroupAttachFlags, + ) -> Result { let prog_fd = self.fd()?; // The link is going to own this new file descriptor so we are @@ -68,7 +75,12 @@ impl LircMode2 { let prog_fd = prog_fd.try_clone()?; let lircdev_fd = lircdev.as_fd().try_clone_to_owned()?; - bpf_prog_attach(prog_fd.as_fd(), lircdev_fd.as_fd(), BPF_LIRC_MODE2)?; + bpf_prog_attach( + prog_fd.as_fd(), + lircdev_fd.as_fd(), + BPF_LIRC_MODE2, + flags.bits(), + )?; self.data.links.insert(LircLink::new(prog_fd, lircdev_fd)) } diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 675e36f0a..82969bd83 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -93,7 +93,7 @@ pub use crate::programs::{ fentry::FEntry, fexit::FExit, kprobe::{KProbe, KProbeError}, - links::Link, + links::{CgroupAttachFlags, Link}, lirc_mode2::LircMode2, lsm::Lsm, perf_event::{PerfEvent, PerfEventScope, PerfTypeId, SamplePolicy}, diff --git a/aya/src/programs/sk_msg.rs b/aya/src/programs/sk_msg.rs index b5a89b878..1b2e51331 100644 --- a/aya/src/programs/sk_msg.rs +++ b/aya/src/programs/sk_msg.rs @@ -6,8 +6,8 @@ use crate::{ generated::{bpf_attach_type::BPF_SK_MSG_VERDICT, bpf_prog_type::BPF_PROG_TYPE_SK_MSG}, maps::sock::SockMapFd, programs::{ - define_link_wrapper, load_program, ProgAttachLink, ProgAttachLinkId, ProgramData, - ProgramError, + define_link_wrapper, load_program, CgroupAttachFlags, ProgAttachLink, ProgAttachLinkId, + ProgramData, ProgramError, }, }; @@ -40,14 +40,14 @@ use crate::{ /// use std::net::TcpStream; /// use std::os::fd::AsRawFd; /// use aya::maps::SockHash; -/// use aya::programs::SkMsg; +/// use aya::programs::{CgroupAttachFlags, SkMsg}; /// /// let intercept_egress: SockHash<_, u32> = bpf.map("INTERCEPT_EGRESS").unwrap().try_into()?; /// 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, CgroupAttachFlags::empty())?; /// /// 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,10 +77,14 @@ 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 { + pub fn attach( + &mut self, + map: &SockMapFd, + flags: CgroupAttachFlags, + ) -> Result { 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)?; + let link = ProgAttachLink::attach(prog_fd, map.as_fd(), BPF_SK_MSG_VERDICT, flags.bits())?; self.data.links.insert(SkMsgLink::new(link)) } diff --git a/aya/src/programs/sk_skb.rs b/aya/src/programs/sk_skb.rs index 4d571dcbb..24bf7c3f0 100644 --- a/aya/src/programs/sk_skb.rs +++ b/aya/src/programs/sk_skb.rs @@ -9,8 +9,8 @@ use crate::{ }, maps::sock::SockMapFd, programs::{ - define_link_wrapper, load_program, ProgAttachLink, ProgAttachLinkId, ProgramData, - ProgramError, + define_link_wrapper, load_program, CgroupAttachFlags, ProgAttachLink, ProgAttachLinkId, + ProgramData, ProgramError, }, VerifierLogLevel, }; @@ -50,14 +50,14 @@ pub enum SkSkbKind { /// # } /// # let mut bpf = aya::Ebpf::load(&[])?; /// use aya::maps::SockMap; -/// use aya::programs::SkSkb; +/// use aya::programs::{CgroupAttachFlags, SkSkb}; /// /// let intercept_ingress: SockMap<_> = bpf.map("INTERCEPT_INGRESS").unwrap().try_into()?; /// 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, CgroupAttachFlags::empty())?; /// /// # Ok::<(), Error>(()) /// ``` @@ -81,7 +81,11 @@ 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 { + pub fn attach( + &mut self, + map: &SockMapFd, + flags: CgroupAttachFlags, + ) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); @@ -90,7 +94,7 @@ impl SkSkb { SkSkbKind::StreamVerdict => BPF_SK_SKB_STREAM_VERDICT, }; - let link = ProgAttachLink::attach(prog_fd, map.as_fd(), attach_type)?; + let link = ProgAttachLink::attach(prog_fd, map.as_fd(), attach_type, flags.bits())?; self.data.links.insert(SkSkbLink::new(link)) } diff --git a/aya/src/programs/sock_ops.rs b/aya/src/programs/sock_ops.rs index 0694dcbd9..4c80729db 100644 --- a/aya/src/programs/sock_ops.rs +++ b/aya/src/programs/sock_ops.rs @@ -4,8 +4,8 @@ use std::os::fd::AsFd; use crate::{ generated::{bpf_attach_type::BPF_CGROUP_SOCK_OPS, bpf_prog_type::BPF_PROG_TYPE_SOCK_OPS}, programs::{ - define_link_wrapper, load_program, ProgAttachLink, ProgAttachLinkId, ProgramData, - ProgramError, + define_link_wrapper, load_program, CgroupAttachFlags, ProgAttachLink, ProgAttachLinkId, + ProgramData, ProgramError, }, }; @@ -35,12 +35,12 @@ use crate::{ /// # } /// # let mut bpf = aya::Ebpf::load(&[])?; /// use std::fs::File; -/// use aya::programs::SockOps; +/// use aya::programs::{CgroupAttachFlags, SockOps}; /// /// let file = File::open("/sys/fs/cgroup/unified")?; /// let prog: &mut SockOps = bpf.program_mut("intercept_active_sockets").unwrap().try_into()?; /// prog.load()?; -/// prog.attach(file)?; +/// prog.attach(file, CgroupAttachFlags::empty())?; /// # Ok::<(), Error>(()) #[derive(Debug)] #[doc(alias = "BPF_PROG_TYPE_SOCK_OPS")] @@ -57,10 +57,19 @@ impl SockOps { /// Attaches the program to the given cgroup. /// /// The returned value can be used to detach, see [SockOps::detach]. - pub fn attach(&mut self, cgroup: T) -> Result { + pub fn attach( + &mut self, + cgroup: T, + flags: CgroupAttachFlags, + ) -> Result { let prog_fd = self.fd()?; - let link = ProgAttachLink::attach(prog_fd.as_fd(), cgroup.as_fd(), BPF_CGROUP_SOCK_OPS)?; + let link = ProgAttachLink::attach( + prog_fd.as_fd(), + cgroup.as_fd(), + BPF_CGROUP_SOCK_OPS, + flags.bits(), + )?; self.data.links.insert(SockOpsLink::new(link)) } diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index 1ae1dc950..95026ec81 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -431,12 +431,14 @@ pub(crate) fn bpf_prog_attach( prog_fd: BorrowedFd<'_>, target_fd: BorrowedFd<'_>, attach_type: bpf_attach_type, + flags: u32, ) -> Result<(), SyscallError> { let mut attr = unsafe { mem::zeroed::() }; attr.__bindgen_anon_5.attach_bpf_fd = prog_fd.as_raw_fd() as u32; attr.__bindgen_anon_5.__bindgen_anon_1.target_fd = target_fd.as_raw_fd() as u32; attr.__bindgen_anon_5.attach_type = attach_type as u32; + attr.__bindgen_anon_5.attach_flags = flags; let ret = sys_bpf(bpf_cmd::BPF_PROG_ATTACH, &mut attr).map_err(|(code, io_error)| { assert_eq!(code, -1); @@ -1096,6 +1098,49 @@ mod tests { use super::*; use crate::sys::override_syscall; + #[test] + fn test_attach_with_attributes() { + const FAKE_FLAGS: u32 = 1234; + const FAKE_FD: i32 = 4321; + + // Test attach flags propagated to system call. + override_syscall(|call| match call { + Syscall::Ebpf { + cmd: bpf_cmd::BPF_PROG_ATTACH, + attr, + } => { + assert_eq!(unsafe { attr.__bindgen_anon_5.attach_flags }, FAKE_FLAGS); + Ok(0) + } + _ => Err((-1, io::Error::from_raw_os_error(EINVAL))), + }); + + let prog_fd = unsafe { BorrowedFd::borrow_raw(FAKE_FD) }; + let tgt_fd = unsafe { BorrowedFd::borrow_raw(FAKE_FD) }; + let mut result = bpf_prog_attach( + prog_fd, + tgt_fd, + bpf_attach_type::BPF_CGROUP_SOCK_OPS, + FAKE_FLAGS, + ); + result.unwrap(); + + // Test with no flags. + override_syscall(|call| match call { + Syscall::Ebpf { + cmd: bpf_cmd::BPF_PROG_ATTACH, + attr, + } => { + assert_eq!(unsafe { attr.__bindgen_anon_5.attach_flags }, 0); + Ok(0) + } + _ => Err((-1, io::Error::from_raw_os_error(EINVAL))), + }); + + result = bpf_prog_attach(prog_fd, tgt_fd, bpf_attach_type::BPF_CGROUP_SOCK_OPS, 0); + result.unwrap(); + } + #[test] fn test_perf_link_supported() { override_syscall(|call| match call {