Browse Source

bpf: Support BPF_PROG_TYPE_SK_LOOKUP

Signed-off-by: Dave Tucker <[email protected]>
Dave Tucker 2 years ago
parent
commit
74704c3b28

+ 32 - 0
bpf/aya-bpf-macros/src/expand.rs

@@ -743,6 +743,38 @@ impl FExit {
     }
 }
 
+pub struct SkLookup {
+    item: ItemFn,
+    name: Option<String>,
+}
+
+impl SkLookup {
+    pub fn from_syn(mut args: Args, item: ItemFn) -> Result<SkLookup> {
+        let name = name_arg(&mut args)?;
+
+        Ok(SkLookup { item, name })
+    }
+
+    pub fn expand(&self) -> Result<TokenStream> {
+        let section_name = if let Some(name) = &self.name {
+            format!("sk_lookup/{}", name)
+        } else {
+            "sk_lookup".to_owned()
+        };
+        let fn_name = &self.item.sig.ident;
+        let item = &self.item;
+        Ok(quote! {
+            #[no_mangle]
+            #[link_section = #section_name]
+            fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sk_lookup) -> u32 {
+                return #fn_name(::aya_bpf::programs::SkLookupContext::new(ctx));
+
+                #item
+            }
+        })
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use syn::parse_quote;

+ 31 - 2
bpf/aya-bpf-macros/src/lib.rs

@@ -2,8 +2,8 @@ mod expand;
 
 use expand::{
     Args, BtfTracePoint, CgroupSkb, CgroupSockAddr, CgroupSockopt, CgroupSysctl, FEntry, FExit,
-    Lsm, Map, PerfEvent, Probe, ProbeKind, RawTracePoint, SchedClassifier, SkMsg, SkSkb, SkSkbKind,
-    SockAddrArgs, SockOps, SocketFilter, SockoptArgs, TracePoint, Xdp,
+    Lsm, Map, PerfEvent, Probe, ProbeKind, RawTracePoint, SchedClassifier, SkLookup, SkMsg, SkSkb,
+    SkSkbKind, SockAddrArgs, SockOps, SocketFilter, SockoptArgs, TracePoint, Xdp,
 };
 use proc_macro::TokenStream;
 use syn::{parse_macro_input, ItemFn, ItemStatic};
@@ -467,3 +467,32 @@ pub fn fexit(attrs: TokenStream, item: TokenStream) -> TokenStream {
         .unwrap_or_else(|err| err.to_compile_error())
         .into()
 }
+
+/// Marks a function as an eBPF Socket Lookup program that can be attached to
+/// a network namespace.
+///
+/// # Minimum kernel version
+///
+/// The minimum kernel version required to use this feature is 5.9
+///
+/// # Examples
+///
+/// ```no_run
+/// use aya_bpf::{macros::sk_lookup, programs::SkLookupContext};
+///
+/// #[sk_lookup(name = "redirect")]
+/// pub fn accept_all(_ctx: SkLookupContext) -> u32 {
+///     // use sk_assign to redirect
+///     return 0
+/// }
+/// ```
+#[proc_macro_attribute]
+pub fn sk_lookup(attrs: TokenStream, item: TokenStream) -> TokenStream {
+    let args = parse_macro_input!(attrs as Args);
+    let item = parse_macro_input!(item as ItemFn);
+
+    SkLookup::from_syn(args, item)
+        .and_then(|u| u.expand())
+        .unwrap_or_else(|err| err.to_compile_error())
+        .into()
+}

+ 25 - 2
bpf/aya-bpf/src/maps/sock_hash.rs

@@ -4,9 +4,12 @@ use aya_bpf_cty::c_void;
 
 use crate::{
     bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_SOCKHASH, bpf_sock_ops},
-    helpers::{bpf_msg_redirect_hash, bpf_sk_redirect_hash, bpf_sock_hash_update},
+    helpers::{
+        bpf_map_lookup_elem, bpf_msg_redirect_hash, bpf_sk_assign, bpf_sk_redirect_hash,
+        bpf_sk_release, bpf_sock_hash_update,
+    },
     maps::PinningType,
-    programs::{SkBuffContext, SkMsgContext},
+    programs::{SkBuffContext, SkLookupContext, SkMsgContext},
     BpfContext,
 };
 
@@ -85,4 +88,24 @@ impl<K> SockHash<K> {
             )
         }
     }
+
+    pub fn redirect_sk_lookup(
+        &mut self,
+        ctx: &SkLookupContext,
+        key: K,
+        flags: u64,
+    ) -> Result<(), u32> {
+        unsafe {
+            let sk = bpf_map_lookup_elem(
+                &mut self.def as *mut _ as *mut _,
+                &key as *const _ as *const c_void,
+            );
+            if sk.is_null() {
+                return Err(1);
+            }
+            let ret = bpf_sk_assign(ctx.as_ptr() as *mut _, sk, flags);
+            bpf_sk_release(sk);
+            (ret >= 0).then(|| ()).ok_or(1)
+        }
+    }
 }

+ 25 - 2
bpf/aya-bpf/src/maps/sock_map.rs

@@ -4,9 +4,12 @@ use aya_bpf_cty::c_void;
 
 use crate::{
     bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_SOCKMAP, bpf_sock_ops},
-    helpers::{bpf_msg_redirect_map, bpf_sk_redirect_map, bpf_sock_map_update},
+    helpers::{
+        bpf_map_lookup_elem, bpf_msg_redirect_map, bpf_sk_assign, bpf_sk_redirect_map,
+        bpf_sk_release, bpf_sock_map_update,
+    },
     maps::PinningType,
-    programs::{SkBuffContext, SkMsgContext},
+    programs::{SkBuffContext, SkLookupContext, SkMsgContext},
     BpfContext,
 };
 
@@ -80,4 +83,24 @@ impl SockMap {
             flags,
         )
     }
+
+    pub fn redirect_sk_lookup(
+        &mut self,
+        ctx: &SkLookupContext,
+        index: u32,
+        flags: u64,
+    ) -> Result<(), u32> {
+        unsafe {
+            let sk = bpf_map_lookup_elem(
+                &mut self.def as *mut _ as *mut _,
+                &index as *const _ as *const c_void,
+            );
+            if sk.is_null() {
+                return Err(1);
+            }
+            let ret = bpf_sk_assign(ctx.as_ptr() as *mut _, sk, flags);
+            bpf_sk_release(sk);
+            (ret >= 0).then(|| ()).ok_or(1)
+        }
+    }
 }

+ 2 - 0
bpf/aya-bpf/src/programs/mod.rs

@@ -5,6 +5,7 @@ pub mod perf_event;
 pub mod probe;
 pub mod raw_tracepoint;
 pub mod sk_buff;
+pub mod sk_lookup;
 pub mod sk_msg;
 pub mod sock_addr;
 pub mod sock_ops;
@@ -21,6 +22,7 @@ pub use perf_event::PerfEventContext;
 pub use probe::ProbeContext;
 pub use raw_tracepoint::RawTracePointContext;
 pub use sk_buff::SkBuffContext;
+pub use sk_lookup::SkLookupContext;
 pub use sk_msg::SkMsgContext;
 pub use sock_addr::SockAddrContext;
 pub use sock_ops::SockOpsContext;

+ 19 - 0
bpf/aya-bpf/src/programs/sk_lookup.rs

@@ -0,0 +1,19 @@
+use core::ffi::c_void;
+
+use crate::{bindings::bpf_sk_lookup, BpfContext};
+
+pub struct SkLookupContext {
+    pub lookup: *mut bpf_sk_lookup,
+}
+
+impl SkLookupContext {
+    pub fn new(lookup: *mut bpf_sk_lookup) -> SkLookupContext {
+        SkLookupContext { lookup }
+    }
+}
+
+impl BpfContext for SkLookupContext {
+    fn as_ptr(&self) -> *mut c_void {
+        self.lookup as *mut _
+    }
+}