Browse Source

Merge pull request #545 from epompeii/lsm_sleepable

Add `BPF_F_SLEEPABLE` flag support to LSM
Alessandro Decina 1 year ago
parent
commit
120b59d
3 changed files with 82 additions and 32 deletions
  1. 27 6
      aya-bpf-macros/src/expand.rs
  2. 44 18
      aya-obj/src/obj.rs
  3. 11 8
      aya/src/bpf.rs

+ 27 - 6
aya-bpf-macros/src/expand.rs

@@ -212,7 +212,7 @@ impl Xdp {
                 frags = m
             } else {
                 return Err(Error::new_spanned(
-                    "mutlibuffer",
+                    s,
                     "invalid value. should be 'true' or 'false'",
                 ));
             }
@@ -613,18 +613,39 @@ impl RawTracePoint {
 
 pub struct Lsm {
     item: ItemFn,
-    name: String,
+    name: Option<String>,
+    sleepable: bool,
 }
 
 impl Lsm {
     pub fn from_syn(mut args: Args, item: ItemFn) -> Result<Lsm> {
-        let name = name_arg(&mut args)?.unwrap_or_else(|| item.sig.ident.to_string());
-
-        Ok(Lsm { item, name })
+        let name = pop_arg(&mut args, "name");
+        let mut sleepable = false;
+        if let Some(s) = pop_arg(&mut args, "sleepable") {
+            if let Ok(m) = s.parse() {
+                sleepable = m
+            } else {
+                return Err(Error::new_spanned(
+                    s,
+                    "invalid value. should be 'true' or 'false'",
+                ));
+            }
+        }
+        err_on_unknown_args(&args)?;
+        Ok(Lsm {
+            item,
+            name,
+            sleepable,
+        })
     }
 
     pub fn expand(&self) -> Result<TokenStream> {
-        let section_name = format!("lsm/{}", self.name);
+        let section_prefix = if self.sleepable { "lsm.s" } else { "lsm" };
+        let section_name = if let Some(name) = &self.name {
+            format!("{section_prefix}/{name}")
+        } else {
+            section_prefix.to_string()
+        };
         let fn_vis = &self.item.vis;
         let fn_name = &self.item.sig.ident;
         let item = &self.item;

+ 44 - 18
aya-obj/src/obj.rs

@@ -161,7 +161,7 @@ pub struct Function {
 /// - `uprobe.s+` or `uretprobe.s+`
 /// - `usdt+`
 /// - `kprobe.multi+` or `kretprobe.multi+`: `BPF_TRACE_KPROBE_MULTI`
-/// - `lsm_cgroup+` or `lsm.s+`
+/// - `lsm_cgroup+`
 /// - `lwt_in`, `lwt_out`, `lwt_seg6local`, `lwt_xmit`
 /// - `raw_tp.w+`, `raw_tracepoint.w+`
 /// - `action`
@@ -196,7 +196,7 @@ pub enum ProgramSection {
     },
     Xdp {
         name: String,
-        frags_supported: bool,
+        frags: bool,
     },
     SkMsg {
         name: String,
@@ -244,6 +244,7 @@ pub enum ProgramSection {
     },
     Lsm {
         name: String,
+        sleepable: bool,
     },
     BtfTracePoint {
         name: String,
@@ -294,7 +295,7 @@ impl ProgramSection {
             ProgramSection::LircMode2 { name } => name,
             ProgramSection::PerfEvent { name } => name,
             ProgramSection::RawTracePoint { name } => name,
-            ProgramSection::Lsm { name } => name,
+            ProgramSection::Lsm { name, .. } => name,
             ProgramSection::BtfTracePoint { name } => name,
             ProgramSection::FEntry { name } => name,
             ProgramSection::FExit { name } => name,
@@ -326,14 +327,8 @@ impl FromStr for ProgramSection {
             "kretprobe" => KRetProbe { name },
             "uprobe" => UProbe { name },
             "uretprobe" => URetProbe { name },
-            "xdp" => Xdp {
-                name,
-                frags_supported: false,
-            },
-            "xdp.frags" => Xdp {
-                name,
-                frags_supported: true,
-            },
+            "xdp" => Xdp { name, frags: false },
+            "xdp.frags" => Xdp { name, frags: true },
             "tp_btf" => BtfTracePoint { name },
             _ if kind.starts_with("tracepoint") || kind.starts_with("tp") => {
                 // tracepoint sections are named `tracepoint/category/event_name`,
@@ -485,7 +480,14 @@ impl FromStr for ProgramSection {
             "lirc_mode2" => LircMode2 { name },
             "perf_event" => PerfEvent { name },
             "raw_tp" | "raw_tracepoint" => RawTracePoint { name },
-            "lsm" => Lsm { name },
+            "lsm" => Lsm {
+                name,
+                sleepable: false,
+            },
+            "lsm.s" => Lsm {
+                name,
+                sleepable: true,
+            },
             "fentry" => FEntry { name },
             "fexit" => FExit { name },
             "freplace" => Extension { name },
@@ -1876,7 +1878,7 @@ mod tests {
         assert_matches!(
             obj.programs.get("foo"),
             Some(Program {
-                section: ProgramSection::Xdp { .. },
+                section: ProgramSection::Xdp { frags: false, .. },
                 ..
             })
         );
@@ -1897,10 +1899,7 @@ mod tests {
         assert_matches!(
             obj.programs.get("foo"),
             Some(Program {
-                section: ProgramSection::Xdp {
-                    frags_supported: true,
-                    ..
-                },
+                section: ProgramSection::Xdp { frags: true, .. },
                 ..
             })
         );
@@ -1958,7 +1957,34 @@ mod tests {
         assert_matches!(
             obj.programs.get("foo"),
             Some(Program {
-                section: ProgramSection::Lsm { .. },
+                section: ProgramSection::Lsm {
+                    sleepable: false,
+                    ..
+                },
+                ..
+            })
+        );
+    }
+
+    #[test]
+    fn test_parse_section_lsm_sleepable() {
+        let mut obj = fake_obj();
+
+        assert_matches!(
+            obj.parse_section(fake_section(
+                BpfSectionKind::Program,
+                "lsm.s/foo",
+                bytes_of(&fake_ins())
+            )),
+            Ok(())
+        );
+        assert_matches!(
+            obj.programs.get("foo"),
+            Some(Program {
+                section: ProgramSection::Lsm {
+                    sleepable: true,
+                    ..
+                },
                 ..
             })
         );

+ 11 - 8
aya/src/bpf.rs

@@ -9,7 +9,7 @@ use std::{
 
 use aya_obj::{
     btf::{BtfFeatures, BtfRelocationError},
-    generated::BPF_F_XDP_HAS_FRAGS,
+    generated::{BPF_F_SLEEPABLE, BPF_F_XDP_HAS_FRAGS},
     relocation::BpfRelocationError,
     BpfSectionKind, Features,
 };
@@ -477,12 +477,10 @@ impl<'a> BpfLoader<'a> {
                                 data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level),
                             })
                         }
-                        ProgramSection::Xdp {
-                            frags_supported, ..
-                        } => {
+                        ProgramSection::Xdp { frags, .. } => {
                             let mut data =
                                 ProgramData::new(prog_name, obj, btf_fd, verifier_log_level);
-                            if *frags_supported {
+                            if *frags {
                                 data.flags = BPF_F_XDP_HAS_FRAGS;
                             }
                             Program::Xdp(Xdp { data })
@@ -550,9 +548,14 @@ impl<'a> BpfLoader<'a> {
                                 data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level),
                             })
                         }
-                        ProgramSection::Lsm { .. } => Program::Lsm(Lsm {
-                            data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level),
-                        }),
+                        ProgramSection::Lsm { sleepable, .. } => {
+                            let mut data =
+                                ProgramData::new(prog_name, obj, btf_fd, verifier_log_level);
+                            if *sleepable {
+                                data.flags = BPF_F_SLEEPABLE;
+                            }
+                            Program::Lsm(Lsm { data })
+                        }
                         ProgramSection::BtfTracePoint { .. } => {
                             Program::BtfTracePoint(BtfTracePoint {
                                 data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level),