Skip to content

Commit

Permalink
fix: add ebpf-no-rcu-kfuncs feature for kernel < 6.2
Browse files Browse the repository at this point in the history
  • Loading branch information
kxxt committed Oct 27, 2024
1 parent 5e77623 commit 3af4b14
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 11 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ ebpf = ["dep:libbpf-rs", "dep:libbpf-sys"]
# Either cargo doesn't rebuild and run build.rs on feature flag change,
# or some logic is wrong in build.rs
ebpf-debug = ["ebpf"]
ebpf-no-rcu-kfuncs = ["ebpf"] # Avoid using rcu helpers. Necessary for kernel version < 6.2
static = ["libbpf-sys/static"]
vendored = ["libbpf-sys/vendored", "vendored-libbpf"]
vendored-libbpf = ["libbpf-sys/vendored-libbpf", "libbpf-cargo/default"]
Expand Down
3 changes: 3 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ fn main() {
if cfg!(any(feature = "ebpf-debug", debug_assertions)) {
clang_args.push(OsStr::new("-DEBPF_DEBUG"));
}
if cfg!(feature = "ebpf-no-rcu-kfuncs") {
clang_args.push(OsStr::new("-DNO_RCU_KFUNCS"));
}
SkeletonBuilder::new()
.source(bpf_src)
.clang_args(clang_args)
Expand Down
25 changes: 21 additions & 4 deletions src/bpf/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

// KFuncs

extern void bpf_rcu_read_lock(void) __ksym;
extern void bpf_rcu_read_unlock(void) __ksym;

// Macros

Expand Down Expand Up @@ -63,4 +59,25 @@ struct sys_enter_exec_args {
const u8 *const *envp;
};

// Compatibility Shims

#ifndef NO_RCU_KFUNCS
extern void bpf_rcu_read_lock(void) __ksym;
extern void bpf_rcu_read_unlock(void) __ksym;
#endif

int __always_inline rcu_read_lock() {
#ifndef NO_RCU_KFUNCS
bpf_rcu_read_lock();
#endif
return 0;
}

int __always_inline rcu_read_unlock() {
#ifndef NO_RCU_KFUNCS
bpf_rcu_read_unlock();
#endif
return 0;
}

#endif
14 changes: 7 additions & 7 deletions src/bpf/tracexec_system.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ bool should_trace(pid_t old_tgid) {
}
// RCU read lock when accessing the active pid ns,
// ref: https://elixir.bootlin.com/linux/v6.11-rc4/source/kernel/pid.c#L505
bpf_rcu_read_lock();
rcu_read_lock();
ret = bpf_core_read(&pid_struct, sizeof(void *), &task->thread_pid);
if (ret < 0) {
debug("failed to read task->thread_pid: %d", ret);
Expand Down Expand Up @@ -176,7 +176,7 @@ bool should_trace(pid_t old_tgid) {
debug("failed to read pid_ns->ns.inum: %d", ret);
goto err_unlock;
}
bpf_rcu_read_unlock();
rcu_read_unlock();
if (pid_in_ns == tracexec_config.tracee_pid &&
ns_inum == tracexec_config.tracee_pidns_inum) {
debug("TASK %d (%d in pidns %u) is tracee", old_tgid, pid_in_ns, ns_inum);
Expand All @@ -187,7 +187,7 @@ bool should_trace(pid_t old_tgid) {
}
return false;
err_unlock:
bpf_rcu_read_unlock();
rcu_read_unlock();
return false;
}

Expand Down Expand Up @@ -577,13 +577,13 @@ static int read_fds(struct exec_event *event) {
goto probe_failure;
}
// Accessing fdt usually requires RCU. Is it okay to access without it in BPF?
// bpf_rcu_read_lock is a kfunc anyway.
// rcu_read_lock is a kfunc anyway.
// https://docs.kernel.org/filesystems/files.html
// files_fdtable() uses rcu_dereference() macro which takes care of the memory
// barrier requirements for lock-free dereference. The fdtable pointer must be
// read within the read-side critical section.
struct fdtable *fdt;
bpf_rcu_read_lock();
rcu_read_lock();
ret = bpf_core_read(&fdt, sizeof(void *), &files->fdt);
if (ret < 0) {
debug("Failed to read files->fdt! err: %d", ret);
Expand Down Expand Up @@ -618,7 +618,7 @@ static int read_fds(struct exec_event *event) {
debug("Failed to read fdt->max_fds! err: %d", ret);
goto probe_failure_locked_rcu;
}
bpf_rcu_read_unlock();
rcu_read_unlock();
// open_fds is a fd set, which is a bitmap
// Copy it into cache first
// Ref:
Expand All @@ -628,7 +628,7 @@ static int read_fds(struct exec_event *event) {
bpf_loop(ctx.size, read_fds_impl, &ctx, 0);
return 0;
probe_failure_locked_rcu:
bpf_rcu_read_unlock();
rcu_read_unlock();
probe_failure:
event->header.flags |= FDS_PROBE_FAILURE;
return -EFAULT;
Expand Down

0 comments on commit 3af4b14

Please sign in to comment.