瀏覽代碼

aya: Add probe for bpf_link_create for perf programs

Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
Dave Tucker 2 年之前
父節點
當前提交
763b92a
共有 2 個文件被更改,包括 38 次插入3 次删除
  1. 7 3
      aya/src/bpf.rs
  2. 31 0
      aya/src/sys/bpf.rs

+ 7 - 3
aya/src/bpf.rs

@@ -35,8 +35,8 @@ use crate::{
     sys::{
         bpf_load_btf, bpf_map_freeze, bpf_map_update_elem_ptr, is_btf_datasec_supported,
         is_btf_decl_tag_supported, is_btf_float_supported, is_btf_func_global_supported,
-        is_btf_func_supported, is_btf_supported, is_btf_type_tag_supported, is_prog_name_supported,
-        retry_with_verifier_logs,
+        is_btf_func_supported, is_btf_supported, is_btf_type_tag_supported, is_perf_link_supported,
+        is_prog_name_supported, retry_with_verifier_logs,
     },
     util::{bytes_of, possible_cpus, VerifierLog, POSSIBLE_CPUS},
 };
@@ -73,6 +73,7 @@ lazy_static! {
 #[derive(Default, Debug)]
 pub(crate) struct Features {
     pub bpf_name: bool,
+    pub bpf_perf_link: bool,
     pub btf: Option<BtfFeatures>,
 }
 
@@ -92,6 +93,7 @@ impl Features {
         };
         let f = Features {
             bpf_name: is_prog_name_supported(),
+            bpf_perf_link: is_perf_link_supported(),
             btf,
         };
 
@@ -107,8 +109,10 @@ impl std::fmt::Display for Features {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         f.write_fmt(format_args!(
             "[FEAT PROBE] BPF program name support: {}\n\
+             [FEAT PROBE] bpf_link support for kprobe/uprobe/tracepoint: {}\n\
              [FEAT PROBE] BTF support: {}",
             self.bpf_name,
+            self.bpf_perf_link,
             self.btf.is_some()
         ))
     }
@@ -358,7 +362,7 @@ impl<'a> BpfLoader<'a> {
         let mut obj = Object::parse(data)?;
         obj.patch_map_data(self.globals.clone())?;
 
-        let btf_fd = if let Some(ref features) = FEATURES.btf {
+        let btf_fd = if let Some(features) = &FEATURES.btf {
             if let Some(btf) = obj.fixup_and_sanitize_btf(features)? {
                 // load btf to the kernel
                 Some(load_btf(btf.to_bytes())?)

+ 31 - 0
aya/src/sys/bpf.rs

@@ -599,6 +599,37 @@ pub(crate) fn is_prog_name_supported() -> bool {
     }
 }
 
+pub(crate) fn is_perf_link_supported() -> bool {
+    let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
+    let u = unsafe { &mut attr.__bindgen_anon_3 };
+
+    let prog: &[u8] = &[
+        0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov64 r0 = 0
+        0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit
+    ];
+
+    let gpl = b"GPL\0";
+    u.license = gpl.as_ptr() as u64;
+
+    let insns = copy_instructions(prog).unwrap();
+    u.insn_cnt = insns.len() as u32;
+    u.insns = insns.as_ptr() as u64;
+    u.prog_type = bpf_prog_type::BPF_PROG_TYPE_TRACEPOINT as u32;
+
+    if let Ok(fd) = sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr) {
+        if let Err((code, _)) =
+            // Uses an invalid target FD so we get EBADF if supported.
+            bpf_link_create(fd as i32, -1, bpf_attach_type::BPF_PERF_EVENT, None, 0)
+        {
+            // Returns EINVAL if unsupported. EBADF if supported.
+            let res = code == (-libc::EBADF).into();
+            unsafe { libc::close(fd as i32) };
+            return res;
+        }
+    }
+    false
+}
+
 pub(crate) fn is_btf_supported() -> bool {
     let mut btf = Btf::new();
     let name_offset = btf.add_string("int".to_string());