From 2e5f5efbf13c71dc1462d1221e77055c7c3e857a Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Thu, 16 Oct 2025 15:28:24 -0400 Subject: [PATCH] aya: make ProgramInfo a proper enum This allows us to distinguish between LSM and LSM_CGROUP programs and do the proper capability check in is_program_supported. --- aya/src/programs/info.rs | 162 +++++++++--------- aya/src/programs/lsm.rs | 6 +- aya/src/programs/mod.rs | 8 +- aya/src/sys/bpf.rs | 8 +- aya/src/sys/feature_probe.rs | 6 +- .../src/tests/feature_probe.rs | 6 +- test/integration-test/src/tests/info.rs | 5 +- test/integration-test/src/tests/lsm.rs | 6 +- xtask/public-api/aya.txt | 112 ++++++++---- 9 files changed, 183 insertions(+), 136 deletions(-) diff --git a/aya/src/programs/info.rs b/aya/src/programs/info.rs index 7755d870..1a491b49 100644 --- a/aya/src/programs/info.rs +++ b/aya/src/programs/info.rs @@ -40,10 +40,8 @@ impl ProgramInfo { /// The type of program. /// /// Introduced in kernel v4.13. - pub fn program_type(&self) -> Result { - bpf_prog_type::try_from(self.0.type_) - .unwrap_or(bpf_prog_type::__MAX_BPF_PROG_TYPE) - .try_into() + pub fn program_type(&self) -> bpf_prog_type { + bpf_prog_type::try_from(self.0.type_).unwrap_or(bpf_prog_type::__MAX_BPF_PROG_TYPE) } /// The unique ID for this program. @@ -295,236 +293,242 @@ pub fn loaded_programs() -> impl Iterator for ProgramType { - type Error = ProgramError; - - fn try_from(prog_type: bpf_prog_type) -> Result { - use bpf_prog_type::*; - Ok(match prog_type { - BPF_PROG_TYPE_UNSPEC => Self::Unspecified, - BPF_PROG_TYPE_SOCKET_FILTER => Self::SocketFilter, - BPF_PROG_TYPE_KPROBE => Self::KProbe, - BPF_PROG_TYPE_SCHED_CLS => Self::SchedClassifier, - BPF_PROG_TYPE_SCHED_ACT => Self::SchedAction, - BPF_PROG_TYPE_TRACEPOINT => Self::TracePoint, - BPF_PROG_TYPE_XDP => Self::Xdp, - BPF_PROG_TYPE_PERF_EVENT => Self::PerfEvent, - BPF_PROG_TYPE_CGROUP_SKB => Self::CgroupSkb, - BPF_PROG_TYPE_CGROUP_SOCK => Self::CgroupSock, - BPF_PROG_TYPE_LWT_IN => Self::LwtInput, - BPF_PROG_TYPE_LWT_OUT => Self::LwtOutput, - BPF_PROG_TYPE_LWT_XMIT => Self::LwtXmit, - BPF_PROG_TYPE_SOCK_OPS => Self::SockOps, - BPF_PROG_TYPE_SK_SKB => Self::SkSkb, - BPF_PROG_TYPE_CGROUP_DEVICE => Self::CgroupDevice, - BPF_PROG_TYPE_SK_MSG => Self::SkMsg, - BPF_PROG_TYPE_RAW_TRACEPOINT => Self::RawTracePoint, - BPF_PROG_TYPE_CGROUP_SOCK_ADDR => Self::CgroupSockAddr, - BPF_PROG_TYPE_LWT_SEG6LOCAL => Self::LwtSeg6local, - BPF_PROG_TYPE_LIRC_MODE2 => Self::LircMode2, - BPF_PROG_TYPE_SK_REUSEPORT => Self::SkReuseport, - BPF_PROG_TYPE_FLOW_DISSECTOR => Self::FlowDissector, - BPF_PROG_TYPE_CGROUP_SYSCTL => Self::CgroupSysctl, - BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE => Self::RawTracePointWritable, - BPF_PROG_TYPE_CGROUP_SOCKOPT => Self::CgroupSockopt, - BPF_PROG_TYPE_TRACING => Self::Tracing, - BPF_PROG_TYPE_STRUCT_OPS => Self::StructOps, - BPF_PROG_TYPE_EXT => Self::Extension, - BPF_PROG_TYPE_LSM => Self::Lsm, - BPF_PROG_TYPE_SK_LOOKUP => Self::SkLookup, - BPF_PROG_TYPE_SYSCALL => Self::Syscall, - BPF_PROG_TYPE_NETFILTER => Self::Netfilter, - __MAX_BPF_PROG_TYPE => return Err(ProgramError::UnexpectedProgramType), - }) +impl From for bpf_prog_type { + fn from(value: ProgramType) -> Self { + match value { + ProgramType::Unspecified => Self::BPF_PROG_TYPE_UNSPEC, + ProgramType::SocketFilter => Self::BPF_PROG_TYPE_SOCKET_FILTER, + ProgramType::KProbe => Self::BPF_PROG_TYPE_KPROBE, + ProgramType::SchedClassifier => Self::BPF_PROG_TYPE_SCHED_CLS, + ProgramType::SchedAction => Self::BPF_PROG_TYPE_SCHED_ACT, + ProgramType::TracePoint => Self::BPF_PROG_TYPE_TRACEPOINT, + ProgramType::Xdp => Self::BPF_PROG_TYPE_XDP, + ProgramType::PerfEvent => Self::BPF_PROG_TYPE_PERF_EVENT, + ProgramType::CgroupSkb => Self::BPF_PROG_TYPE_CGROUP_SKB, + ProgramType::CgroupSock => Self::BPF_PROG_TYPE_CGROUP_SOCK, + ProgramType::LwtInput => Self::BPF_PROG_TYPE_LWT_IN, + ProgramType::LwtOutput => Self::BPF_PROG_TYPE_LWT_OUT, + ProgramType::LwtXmit => Self::BPF_PROG_TYPE_LWT_XMIT, + ProgramType::SockOps => Self::BPF_PROG_TYPE_SOCK_OPS, + ProgramType::SkSkb => Self::BPF_PROG_TYPE_SK_SKB, + ProgramType::CgroupDevice => Self::BPF_PROG_TYPE_CGROUP_DEVICE, + ProgramType::SkMsg => Self::BPF_PROG_TYPE_SK_MSG, + ProgramType::RawTracePoint => Self::BPF_PROG_TYPE_RAW_TRACEPOINT, + ProgramType::CgroupSockAddr => Self::BPF_PROG_TYPE_CGROUP_SOCK_ADDR, + ProgramType::LwtSeg6local => Self::BPF_PROG_TYPE_LWT_SEG6LOCAL, + ProgramType::LircMode2 => Self::BPF_PROG_TYPE_LIRC_MODE2, + ProgramType::SkReuseport => Self::BPF_PROG_TYPE_SK_REUSEPORT, + ProgramType::FlowDissector => Self::BPF_PROG_TYPE_FLOW_DISSECTOR, + ProgramType::CgroupSysctl => Self::BPF_PROG_TYPE_CGROUP_SYSCTL, + ProgramType::RawTracePointWritable => Self::BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE, + ProgramType::CgroupSockopt => Self::BPF_PROG_TYPE_CGROUP_SOCKOPT, + ProgramType::Tracing => Self::BPF_PROG_TYPE_TRACING, + ProgramType::StructOps => Self::BPF_PROG_TYPE_STRUCT_OPS, + ProgramType::Extension => Self::BPF_PROG_TYPE_EXT, + ProgramType::Lsm(_) => Self::BPF_PROG_TYPE_LSM, + ProgramType::SkLookup => Self::BPF_PROG_TYPE_SK_LOOKUP, + ProgramType::Syscall => Self::BPF_PROG_TYPE_SYSCALL, + ProgramType::Netfilter => Self::BPF_PROG_TYPE_NETFILTER, + } } } diff --git a/aya/src/programs/lsm.rs b/aya/src/programs/lsm.rs index d2f4fa44..776a5199 100644 --- a/aya/src/programs/lsm.rs +++ b/aya/src/programs/lsm.rs @@ -6,8 +6,8 @@ use aya_obj::{ }; use crate::programs::{ - FdLink, FdLinkId, ProgramData, ProgramError, ProgramType, define_link_wrapper, load_program, - utils::attach_raw_tracepoint, + FdLink, FdLinkId, LsmAttachType, ProgramData, ProgramError, ProgramType, define_link_wrapper, + load_program, utils::attach_raw_tracepoint, }; /// A program that attaches to Linux LSM hooks. Used to implement security policy and @@ -55,7 +55,7 @@ pub struct Lsm { impl Lsm { /// The type of the program according to the kernel. - pub const PROGRAM_TYPE: ProgramType = ProgramType::Lsm; + pub const PROGRAM_TYPE: ProgramType = ProgramType::Lsm(LsmAttachType::Mac); /// Loads the program inside the kernel. /// diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index ec7d1520..484b88d0 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -88,7 +88,7 @@ use aya_obj::{ programs::XdpAttachType, }; use info::impl_info; -pub use info::{ProgramInfo, ProgramType, loaded_programs}; +pub use info::{LsmAttachType, ProgramInfo, ProgramType, loaded_programs}; use libc::ENOSPC; use tc::SchedClassifierLink; use thiserror::Error; @@ -349,8 +349,8 @@ impl Program { Self::LircMode2(_) => ProgramType::LircMode2, Self::PerfEvent(_) => ProgramType::PerfEvent, Self::RawTracePoint(_) => ProgramType::RawTracePoint, - Self::Lsm(_) => ProgramType::Lsm, - Self::LsmCgroup(_) => ProgramType::Lsm, + Self::Lsm(_) => ProgramType::Lsm(LsmAttachType::Mac), + Self::LsmCgroup(_) => ProgramType::Lsm(LsmAttachType::Cgroup), // The following program types are a subset of `TRACING` programs: // // - `BPF_TRACE_RAW_TP` (`BtfTracePoint`) @@ -1042,7 +1042,7 @@ macro_rules! impl_from_prog_info { name: Cow<'static, str>, $($var: $var_ty,)? ) -> Result { - if info.program_type()? != Self::PROGRAM_TYPE { + if info.program_type() != Self::PROGRAM_TYPE.into() { return Err(ProgramError::UnexpectedProgramType {}); } let ProgramInfo(bpf_progam_info) = info; diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index 546de262..dc778181 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -32,7 +32,7 @@ use log::warn; use crate::{ Btf, Pod, VerifierLogLevel, maps::{MapData, PerCpuValues}, - programs::{ProgramType, links::LinkRef}, + programs::{LsmAttachType, ProgramType, links::LinkRef}, sys::{Syscall, SyscallError, syscall}, util::KernelVersion, }; @@ -820,7 +820,10 @@ where ProgramType::CgroupSysctl => Some(bpf_attach_type::BPF_CGROUP_SYSCTL), ProgramType::CgroupSockopt => Some(bpf_attach_type::BPF_CGROUP_GETSOCKOPT), ProgramType::Tracing => Some(bpf_attach_type::BPF_TRACE_FENTRY), - ProgramType::Lsm => Some(bpf_attach_type::BPF_LSM_MAC), + ProgramType::Lsm(lsm_attach_type) => match lsm_attach_type { + LsmAttachType::Mac => Some(bpf_attach_type::BPF_LSM_MAC), + LsmAttachType::Cgroup => Some(bpf_attach_type::BPF_LSM_CGROUP), + }, ProgramType::SkLookup => Some(bpf_attach_type::BPF_SK_LOOKUP), ProgramType::Netfilter => Some(bpf_attach_type::BPF_NETFILTER), // Program types below v4.17, or do not accept `expected_attach_type`, should leave the @@ -863,6 +866,7 @@ where _ => {} } + let program_type: bpf_prog_type = program_type.into(); u.prog_type = program_type as u32; if let Some(expected_attach_type) = expected_attach_type { u.expected_attach_type = expected_attach_type as u32; diff --git a/aya/src/sys/feature_probe.rs b/aya/src/sys/feature_probe.rs index 5651f6fa..0dd06120 100644 --- a/aya/src/sys/feature_probe.rs +++ b/aya/src/sys/feature_probe.rs @@ -64,7 +64,7 @@ pub fn is_program_supported(program_type: ProgramType) -> Result Result Some("bpf_lsm_bpf"), + ProgramType::Lsm(_) => Some("bpf_lsm_bpf"), _ => None, } .map(|func_name| { @@ -159,7 +159,7 @@ pub fn is_program_supported(program_type: ProgramType) -> Result 0, KernelVersion::new(4, 13, 0)); diff --git a/test/integration-test/src/tests/lsm.rs b/test/integration-test/src/tests/lsm.rs index 89c0db9d..c4726883 100644 --- a/test/integration-test/src/tests/lsm.rs +++ b/test/integration-test/src/tests/lsm.rs @@ -1,7 +1,7 @@ use assert_matches::assert_matches; use aya::{ Btf, Ebpf, - programs::{Lsm, LsmCgroup, ProgramError, ProgramType}, + programs::{Lsm, LsmAttachType, LsmCgroup, ProgramError, ProgramType}, sys::{SyscallError, is_program_supported}, }; @@ -33,7 +33,7 @@ fn lsm() { let link_id = { let result = prog.attach(); - if !is_program_supported(ProgramType::Lsm).unwrap() { + if !is_program_supported(ProgramType::Lsm(LsmAttachType::Mac)).unwrap() { assert_matches!(result, Err(ProgramError::SyscallError(SyscallError { call, io_error })) => { assert_eq!(call, "bpf_raw_tracepoint_open"); assert_eq!(io_error.raw_os_error(), Some(524)); @@ -68,7 +68,7 @@ fn lsm_cgroup() { let link_id = { let result = prog.attach(cgroup.fd()); - if !is_program_supported(ProgramType::Lsm).unwrap() { + if !is_program_supported(ProgramType::Lsm(LsmAttachType::Cgroup)).unwrap() { assert_matches!(result, Err(ProgramError::SyscallError(SyscallError { call, io_error })) => { assert_eq!(call, "bpf_link_create"); assert_eq!(io_error.raw_os_error(), Some(524)); diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index d4a5d1cc..fbc45fd5 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -7904,6 +7904,45 @@ impl core::borrow::BorrowMut for aya::programs::kprobe::KProbeError where pub fn aya::programs::kprobe::KProbeError::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::programs::kprobe::KProbeError pub fn aya::programs::kprobe::KProbeError::from(t: T) -> T +pub enum aya::programs::LsmAttachType +pub aya::programs::LsmAttachType::Cgroup +pub aya::programs::LsmAttachType::Mac +impl core::clone::Clone for aya::programs::LsmAttachType +pub fn aya::programs::LsmAttachType::clone(&self) -> aya::programs::LsmAttachType +impl core::cmp::PartialEq for aya::programs::LsmAttachType +pub fn aya::programs::LsmAttachType::eq(&self, other: &aya::programs::LsmAttachType) -> bool +impl core::fmt::Debug for aya::programs::LsmAttachType +pub fn aya::programs::LsmAttachType::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::marker::Copy for aya::programs::LsmAttachType +impl core::marker::StructuralPartialEq for aya::programs::LsmAttachType +impl core::marker::Freeze for aya::programs::LsmAttachType +impl core::marker::Send for aya::programs::LsmAttachType +impl core::marker::Sync for aya::programs::LsmAttachType +impl core::marker::Unpin for aya::programs::LsmAttachType +impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::LsmAttachType +impl core::panic::unwind_safe::UnwindSafe for aya::programs::LsmAttachType +impl core::convert::Into for aya::programs::LsmAttachType where U: core::convert::From +pub fn aya::programs::LsmAttachType::into(self) -> U +impl core::convert::TryFrom for aya::programs::LsmAttachType where U: core::convert::Into +pub type aya::programs::LsmAttachType::Error = core::convert::Infallible +pub fn aya::programs::LsmAttachType::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::programs::LsmAttachType where U: core::convert::TryFrom +pub type aya::programs::LsmAttachType::Error = >::Error +pub fn aya::programs::LsmAttachType::try_into(self) -> core::result::Result>::Error> +impl alloc::borrow::ToOwned for aya::programs::LsmAttachType where T: core::clone::Clone +pub type aya::programs::LsmAttachType::Owned = T +pub fn aya::programs::LsmAttachType::clone_into(&self, target: &mut T) +pub fn aya::programs::LsmAttachType::to_owned(&self) -> T +impl core::any::Any for aya::programs::LsmAttachType where T: 'static + ?core::marker::Sized +pub fn aya::programs::LsmAttachType::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::programs::LsmAttachType where T: ?core::marker::Sized +pub fn aya::programs::LsmAttachType::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::programs::LsmAttachType where T: ?core::marker::Sized +pub fn aya::programs::LsmAttachType::borrow_mut(&mut self) -> &mut T +impl core::clone::CloneToUninit for aya::programs::LsmAttachType where T: core::clone::Clone +pub unsafe fn aya::programs::LsmAttachType::clone_to_uninit(&self, dest: *mut u8) +impl core::convert::From for aya::programs::LsmAttachType +pub fn aya::programs::LsmAttachType::from(t: T) -> T pub enum aya::programs::PerfEventScope pub aya::programs::PerfEventScope::AllProcessesOneCpu pub aya::programs::PerfEventScope::AllProcessesOneCpu::cpu: u32 @@ -8286,46 +8325,45 @@ pub fn aya::programs::ProgramError::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::programs::ProgramError pub fn aya::programs::ProgramError::from(t: T) -> T #[non_exhaustive] pub enum aya::programs::ProgramType -pub aya::programs::ProgramType::CgroupDevice = 15 -pub aya::programs::ProgramType::CgroupSkb = 8 -pub aya::programs::ProgramType::CgroupSock = 9 -pub aya::programs::ProgramType::CgroupSockAddr = 18 -pub aya::programs::ProgramType::CgroupSockopt = 25 -pub aya::programs::ProgramType::CgroupSysctl = 23 -pub aya::programs::ProgramType::Extension = 28 -pub aya::programs::ProgramType::FlowDissector = 22 -pub aya::programs::ProgramType::KProbe = 2 -pub aya::programs::ProgramType::LircMode2 = 20 -pub aya::programs::ProgramType::Lsm = 29 -pub aya::programs::ProgramType::LwtInput = 10 -pub aya::programs::ProgramType::LwtOutput = 11 -pub aya::programs::ProgramType::LwtSeg6local = 19 -pub aya::programs::ProgramType::LwtXmit = 12 -pub aya::programs::ProgramType::Netfilter = 32 -pub aya::programs::ProgramType::PerfEvent = 7 -pub aya::programs::ProgramType::RawTracePoint = 17 -pub aya::programs::ProgramType::RawTracePointWritable = 24 -pub aya::programs::ProgramType::SchedAction = 4 -pub aya::programs::ProgramType::SchedClassifier = 3 -pub aya::programs::ProgramType::SkLookup = 30 -pub aya::programs::ProgramType::SkMsg = 16 -pub aya::programs::ProgramType::SkReuseport = 21 -pub aya::programs::ProgramType::SkSkb = 14 -pub aya::programs::ProgramType::SockOps = 13 -pub aya::programs::ProgramType::SocketFilter = 1 -pub aya::programs::ProgramType::StructOps = 27 -pub aya::programs::ProgramType::Syscall = 31 -pub aya::programs::ProgramType::TracePoint = 5 -pub aya::programs::ProgramType::Tracing = 26 -pub aya::programs::ProgramType::Unspecified = 0 -pub aya::programs::ProgramType::Xdp = 6 +pub aya::programs::ProgramType::CgroupDevice +pub aya::programs::ProgramType::CgroupSkb +pub aya::programs::ProgramType::CgroupSock +pub aya::programs::ProgramType::CgroupSockAddr +pub aya::programs::ProgramType::CgroupSockopt +pub aya::programs::ProgramType::CgroupSysctl +pub aya::programs::ProgramType::Extension +pub aya::programs::ProgramType::FlowDissector +pub aya::programs::ProgramType::KProbe +pub aya::programs::ProgramType::LircMode2 +pub aya::programs::ProgramType::Lsm(aya::programs::LsmAttachType) +pub aya::programs::ProgramType::LwtInput +pub aya::programs::ProgramType::LwtOutput +pub aya::programs::ProgramType::LwtSeg6local +pub aya::programs::ProgramType::LwtXmit +pub aya::programs::ProgramType::Netfilter +pub aya::programs::ProgramType::PerfEvent +pub aya::programs::ProgramType::RawTracePoint +pub aya::programs::ProgramType::RawTracePointWritable +pub aya::programs::ProgramType::SchedAction +pub aya::programs::ProgramType::SchedClassifier +pub aya::programs::ProgramType::SkLookup +pub aya::programs::ProgramType::SkMsg +pub aya::programs::ProgramType::SkReuseport +pub aya::programs::ProgramType::SkSkb +pub aya::programs::ProgramType::SockOps +pub aya::programs::ProgramType::SocketFilter +pub aya::programs::ProgramType::StructOps +pub aya::programs::ProgramType::Syscall +pub aya::programs::ProgramType::TracePoint +pub aya::programs::ProgramType::Tracing +pub aya::programs::ProgramType::Unspecified +pub aya::programs::ProgramType::Xdp impl core::clone::Clone for aya::programs::ProgramType pub fn aya::programs::ProgramType::clone(&self) -> aya::programs::ProgramType impl core::cmp::PartialEq for aya::programs::ProgramType pub fn aya::programs::ProgramType::eq(&self, other: &aya::programs::ProgramType) -> bool -impl core::convert::TryFrom for aya::programs::ProgramType -pub type aya::programs::ProgramType::Error = aya::programs::ProgramError -pub fn aya::programs::ProgramType::try_from(prog_type: aya_obj::generated::linux_bindings_x86_64::bpf_prog_type) -> core::result::Result +impl core::convert::From for aya_obj::generated::linux_bindings_x86_64::bpf_prog_type +pub fn aya_obj::generated::linux_bindings_x86_64::bpf_prog_type::from(value: aya::programs::ProgramType) -> Self impl core::fmt::Debug for aya::programs::ProgramType pub fn aya::programs::ProgramType::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::marker::Copy for aya::programs::ProgramType @@ -9661,7 +9699,7 @@ pub fn aya::programs::ProgramInfo::map_ids(&self) -> core::result::Result core::result::Result pub fn aya::programs::ProgramInfo::name(&self) -> &[u8] pub fn aya::programs::ProgramInfo::name_as_str(&self) -> core::option::Option<&str> -pub fn aya::programs::ProgramInfo::program_type(&self) -> core::result::Result +pub fn aya::programs::ProgramInfo::program_type(&self) -> aya_obj::generated::linux_bindings_x86_64::bpf_prog_type pub fn aya::programs::ProgramInfo::run_count(&self) -> u64 pub fn aya::programs::ProgramInfo::run_time(&self) -> core::time::Duration pub fn aya::programs::ProgramInfo::size_jitted(&self) -> u32