Ver código fonte

aya: add support for SockOps programs

Alessandro Decina 4 anos atrás
pai
commit
ca4b3bfc04

+ 3 - 2
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)

+ 10 - 1
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::<Vec<_>>();
         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(&section, ty, name)?);
                 if !section.relocations.is_empty() {

+ 17 - 3
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<RawFd>,
-    map_fd: Option<RawFd>,
+    target_fd: Option<RawFd>,
     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
+);

+ 1 - 1
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,
         }))
     }

+ 44 - 0
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<T: AsRawFd>(&mut self, cgroup: T) -> Result<LinkRef, ProgramError> {
+        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,
+        }))
+    }
+}