diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index f2536b9d..bb2af41f 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -19,8 +19,8 @@ use crate::{ Object, ParseError, ProgramKind, }, programs::{ - KProbe, ProbeKind, Program, ProgramData, ProgramError, SkSkb, SkSkbKind, SocketFilter, - TracePoint, UProbe, Xdp, + KProbe, ProbeKind, Program, ProgramData, ProgramError, SkSkb, SkSkbKind, SockOps, + SocketFilter, TracePoint, UProbe, Xdp, }, sys::bpf_map_update_elem_ptr, util::{possible_cpus, POSSIBLE_CPUS}, @@ -181,6 +181,7 @@ impl Bpf { data, kind: SkSkbKind::StreamVerdict, }), + ProgramKind::SockOps => Program::SockOps(SockOps { data }), }; (name, program) diff --git a/aya/src/obj/mod.rs b/aya/src/obj/mod.rs index 7f7fae73..6c430a45 100644 --- a/aya/src/obj/mod.rs +++ b/aya/src/obj/mod.rs @@ -75,6 +75,7 @@ pub enum ProgramKind { Xdp, SkSkbStreamParser, SkSkbStreamVerdict, + SockOps, } impl FromStr for ProgramKind { @@ -92,6 +93,7 @@ impl FromStr for ProgramKind { "socket_filter" => SocketFilter, "sk_skb/stream_parser" => SkSkbStreamParser, "sk_skb/stream_verdict" => SkSkbStreamVerdict, + "sockops" => SockOps, _ => { return Err(ParseError::InvalidProgramKind { kind: kind.to_string(), @@ -254,6 +256,12 @@ impl Object { let mut parts = section.name.rsplitn(2, "/").collect::>(); parts.reverse(); + if parts.len() == 1 { + if parts[0] == "xdp" || parts[0] == "sockops" { + parts.push(parts[0]); + } + } + match parts.as_slice() { &[name] if name == ".bss" || name.starts_with(".data") || name.starts_with(".rodata") => @@ -276,7 +284,8 @@ impl Object { | &[ty @ "xdp", name] | &[ty @ "trace_point", name] | &[ty @ "sk_skb/stream_parser", name] - | &[ty @ "sk_skb/stream_verdict", name] => { + | &[ty @ "sk_skb/stream_verdict", name] + | &[ty @ "sockops", name] => { self.programs .insert(name.to_string(), self.parse_program(§ion, ty, name)?); if !section.relocations.is_empty() { diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 38e7dd65..ba43609d 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -48,6 +48,7 @@ mod kprobe; mod perf_attach; mod probe; mod sk_skb; +mod sock_ops; mod socket_filter; mod trace_point; mod uprobe; @@ -61,6 +62,7 @@ pub use kprobe::{KProbe, KProbeError}; use perf_attach::*; pub use probe::ProbeKind; pub use sk_skb::{SkSkb, SkSkbKind}; +pub use sock_ops::SockOps; pub use socket_filter::{SocketFilter, SocketFilterError}; pub use trace_point::{TracePoint, TracePointError}; pub use uprobe::{UProbe, UProbeError}; @@ -141,6 +143,7 @@ pub enum Program { SocketFilter(SocketFilter), Xdp(Xdp), SkSkb(SkSkb), + SockOps(SockOps), } impl Program { @@ -168,6 +171,7 @@ impl Program { Program::SocketFilter(_) => BPF_PROG_TYPE_SOCKET_FILTER, Program::Xdp(_) => BPF_PROG_TYPE_XDP, Program::SkSkb(_) => BPF_PROG_TYPE_SK_SKB, + Program::SockOps(_) => BPF_PROG_TYPE_SOCK_OPS, } } @@ -184,6 +188,7 @@ impl Program { Program::SocketFilter(p) => &p.data, Program::Xdp(p) => &p.data, Program::SkSkb(p) => &p.data, + Program::SockOps(p) => &p.data, } } @@ -195,6 +200,7 @@ impl Program { Program::SocketFilter(p) => &mut p.data, Program::Xdp(p) => &mut p.data, Program::SkSkb(p) => &mut p.data, + Program::SockOps(p) => &mut p.data, } } } @@ -365,14 +371,14 @@ impl Drop for FdLink { #[derive(Debug)] struct ProgAttachLink { prog_fd: Option, - map_fd: Option, + target_fd: Option, attach_type: bpf_attach_type, } impl Link for ProgAttachLink { fn detach(&mut self) -> Result<(), ProgramError> { if let Some(prog_fd) = self.prog_fd.take() { - let _ = bpf_prog_detach(prog_fd, self.map_fd.take().unwrap(), self.attach_type); + let _ = bpf_prog_detach(prog_fd, self.target_fd.take().unwrap(), self.attach_type); Ok(()) } else { Err(ProgramError::AlreadyDetached) @@ -434,4 +440,12 @@ macro_rules! impl_try_from_program { } } -impl_try_from_program!(KProbe, UProbe, TracePoint, SocketFilter, Xdp, SkSkb); +impl_try_from_program!( + KProbe, + UProbe, + TracePoint, + SocketFilter, + Xdp, + SkSkb, + SockOps +); diff --git a/aya/src/programs/sk_skb.rs b/aya/src/programs/sk_skb.rs index 951fe5b8..1683b579 100644 --- a/aya/src/programs/sk_skb.rs +++ b/aya/src/programs/sk_skb.rs @@ -54,7 +54,7 @@ impl SkSkb { })?; Ok(self.data.link(ProgAttachLink { prog_fd: Some(prog_fd), - map_fd: Some(map_fd), + target_fd: Some(map_fd), attach_type, })) } diff --git a/aya/src/programs/sock_ops.rs b/aya/src/programs/sock_ops.rs new file mode 100644 index 00000000..e98bb46b --- /dev/null +++ b/aya/src/programs/sock_ops.rs @@ -0,0 +1,44 @@ +use std::os::unix::io::AsRawFd; + +use crate::{ + generated::{bpf_attach_type::BPF_CGROUP_SOCK_OPS, bpf_prog_type::BPF_PROG_TYPE_SOCK_OPS}, + programs::{load_program, LinkRef, ProgAttachLink, ProgramData, ProgramError}, + sys::bpf_prog_attach, +}; + +#[derive(Debug)] +pub struct SockOps { + pub(crate) data: ProgramData, +} + +impl SockOps { + /// Loads the program inside the kernel. + /// + /// See also [`Program::load`](crate::programs::Program::load). + pub fn load(&mut self) -> Result<(), ProgramError> { + load_program(BPF_PROG_TYPE_SOCK_OPS, &mut self.data) + } + + /// Returns the name of the program. + pub fn name(&self) -> String { + self.data.name.to_string() + } + + /// Attaches the program to the given sockmap. + pub fn attach(&mut self, cgroup: T) -> Result { + let prog_fd = self.data.fd_or_err()?; + let cgroup_fd = cgroup.as_raw_fd(); + + bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SOCK_OPS).map_err(|(_, io_error)| { + ProgramError::SyscallError { + call: "bpf_link_create".to_owned(), + io_error, + } + })?; + Ok(self.data.link(ProgAttachLink { + prog_fd: Some(prog_fd), + target_fd: Some(cgroup_fd), + attach_type: BPF_CGROUP_SOCK_OPS, + })) + } +}