use std::{os::fd::AsFd, path::Path};
use aya_obj::{
btf::{Btf, BtfKind},
generated::{bpf_attach_type::BPF_LSM_CGROUP, bpf_prog_type::BPF_PROG_TYPE_LSM},
};
use crate::{
VerifierLogLevel,
programs::{FdLink, FdLinkId, ProgramData, ProgramError, define_link_wrapper, load_program},
sys::{LinkTarget, SyscallError, bpf_link_create},
};
#[derive(Debug)]
#[doc(alias = "BPF_PROG_TYPE_LSM")]
pub struct LsmCgroup {
pub(crate) data: ProgramData<LsmLink>,
}
impl LsmCgroup {
pub fn load(&mut self, lsm_hook_name: &str, btf: &Btf) -> Result<(), ProgramError> {
self.data.expected_attach_type = Some(BPF_LSM_CGROUP);
let type_name = format!("bpf_lsm_{lsm_hook_name}");
self.data.attach_btf_id =
Some(btf.id_by_type_name_kind(type_name.as_str(), BtfKind::Func)?);
load_program(BPF_PROG_TYPE_LSM, &mut self.data)
}
pub fn from_pin<P: AsRef<Path>>(path: P) -> Result<Self, ProgramError> {
let mut data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?;
data.expected_attach_type = Some(BPF_LSM_CGROUP);
Ok(Self { data })
}
pub fn attach<T: AsFd>(&mut self, cgroup: T) -> Result<LsmLinkId, ProgramError> {
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();
let link_fd = bpf_link_create(
prog_fd,
LinkTarget::Fd(cgroup_fd),
attach_type,
0,
None,
)
.map_err(|io_error| SyscallError {
call: "bpf_link_create",
io_error,
})?;
self.data.links.insert(LsmLink::new(FdLink::new(link_fd)))
}
}
define_link_wrapper!(LsmLink, LsmLinkId, FdLink, FdLinkId, LsmCgroup,);