Skip to content

Commit

Permalink
feat: Improved bpf_loop probe
Browse files Browse the repository at this point in the history
The previously used ASM probe didn't work reliably on new kernels, which
were rejecting the program, because of lack of valid function pointer
being used as a callback.

Introduce a small C probe which has a minimal, but valid `bpf_loop`
call.

Fixes #300
  • Loading branch information
vadorovsky authored and banditopazzo committed Jun 26, 2024
1 parent 2516bca commit 2e175fe
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 8 deletions.
4 changes: 3 additions & 1 deletion crates/bpf-feature-autodetect/build.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
fn main() -> Result<(), Box<dyn std::error::Error>> {
bpf_builder::build("test_lsm", "src/test_lsm.bpf.c")
bpf_builder::build("test_bpf_loop", "src/test_bpf_loop.bpf.c")?;
bpf_builder::build("test_lsm", "src/test_lsm.bpf.c")?;
Ok(())
}
29 changes: 29 additions & 0 deletions crates/bpf-feature-autodetect/src/bpf_loop.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use aya::{include_bytes_aligned, programs::TracePoint, Bpf, BpfError};
use log::warn;

fn load_probe() -> Result<(), BpfError> {
let mut bpf = Bpf::load(include_bytes_aligned!(concat!(
env!("OUT_DIR"),
"/test_bpf_loop.none.bpf.o"
)))?;
let program: &mut TracePoint = bpf.program_mut("probe_bpf_loop").unwrap().try_into()?;
program.load()?;
Ok(())
}

pub fn bpf_loop_supported() -> bool {
match load_probe() {
Ok(_) => true,
Err(e) => {
let err_msg = "`bpf_loop` helper is not supported by the kernel";

if let Ok(true) = std::env::var("RUST_BACKTRACE").map(|s| s == "1") {
warn!("{err_msg}: {e}");
} else {
warn!("{err_msg}");
}

false
}
}
}
13 changes: 6 additions & 7 deletions crates/bpf-feature-autodetect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@ use libc::SYS_bpf;
use thiserror::Error;

pub mod atomic;
pub mod bpf_loop;
pub mod func;
pub mod insn;
pub mod kernel_version;
pub mod lsm;

use crate::{atomic::atomics_supported, func::func_id_supported, lsm::lsm_supported};
use crate::{
atomic::atomics_supported, bpf_loop::bpf_loop_supported, func::func_id_supported,
lsm::lsm_supported,
};

/// Size of the eBPF verifier log.
const LOG_SIZE: usize = 4096;
Expand All @@ -34,12 +38,7 @@ pub fn autodetect_features() -> BpfFeatures {
bpf_func_id::BPF_FUNC_get_current_task_btf,
BpfProgType::BPF_PROG_TYPE_CGROUP_SKB,
),
bpf_loop: func_id_supported(
"bpf_loop",
bpf_func_id::BPF_FUNC_loop,
// Program type doesn't matter here.
BpfProgType::BPF_PROG_TYPE_KPROBE,
),
bpf_loop: bpf_loop_supported(),
lsm: lsm_supported(),
}
}
Expand Down
12 changes: 12 additions & 0 deletions crates/bpf-feature-autodetect/src/test_bpf_loop.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

static int callback(void *ctx, u32 index) {
return 0;
}

SEC("tracepoint")
int probe_bpf_loop(void *ctx) {
bpf_loop(5, callback, NULL, 0);
return 0;
}

0 comments on commit 2e175fe

Please sign in to comment.