diff --git a/bpf/Makefile b/bpf/Makefile index bbf324c7f84..cdcd801d4c7 100644 --- a/bpf/Makefile +++ b/bpf/Makefile @@ -44,7 +44,8 @@ PROCESS += bpf_execve_event_v310.o bpf_exit_v310.o bpf_fork_v310.o PROCESS += bpf_execve_event.o bpf_fork.o bpf_exit.o bpf_execve_bprm_commit_creds.o # generic probes PROCESS += bpf_generic_kprobe.o bpf_generic_retkprobe.o bpf_generic_tracepoint.o \ - bpf_generic_uprobe.o bpf_generic_rawtp.o bpf_generic_usdt.o + bpf_generic_uprobe.o bpf_generic_rawtp.o bpf_generic_usdt.o \ + bpf_generic_fentry.o bpf_generic_fexit.o # lsm PROCESS += bpf_generic_lsm_core.o bpf_generic_lsm_output.o @@ -57,7 +58,9 @@ PROCESS += bpf_generic_kprobe_v53.o bpf_generic_retkprobe_v53.o \ bpf_multi_kprobe_v53.o bpf_multi_retkprobe_v53.o \ bpf_generic_tracepoint_v53.o bpf_generic_uprobe_v53.o \ bpf_generic_rawtp_v53.o \ - bpf_generic_usdt_v53.o + bpf_generic_usdt_v53.o \ + bpf_generic_fentry_v53.o \ + bpf_generic_fexit_v53.o # v5.11 # base sensor @@ -67,7 +70,9 @@ PROCESS += bpf_generic_kprobe_v511.o bpf_generic_retkprobe_v511.o \ bpf_multi_kprobe_v511.o bpf_multi_retkprobe_v511.o \ bpf_generic_tracepoint_v511.o bpf_generic_uprobe_v511.o \ bpf_generic_rawtp_v511.o \ - bpf_generic_usdt_v511.o + bpf_generic_usdt_v511.o \ + bpf_generic_fentry_v511.o \ + bpf_generic_fexit_v511.o # lsm PROCESS += bpf_generic_lsm_core_v511.o bpf_generic_lsm_output_v511.o \ @@ -83,7 +88,9 @@ PROCESS += bpf_generic_kprobe_v61.o bpf_generic_retkprobe_v61.o \ bpf_multi_uprobe_v61.o \ bpf_generic_rawtp_v61.o \ bpf_generic_usdt_v61.o \ - bpf_multi_usdt_v61.o + bpf_multi_usdt_v61.o \ + bpf_generic_fentry_v61.o \ + bpf_generic_fexit_v61.o # v6.12 # base sensor @@ -95,7 +102,9 @@ PROCESS += bpf_generic_kprobe_v612.o bpf_generic_retkprobe_v612.o \ bpf_multi_uprobe_v612.o \ bpf_generic_rawtp_v612.o \ bpf_generic_usdt_v612.o \ - bpf_multi_usdt_v612.o + bpf_multi_usdt_v612.o \ + bpf_generic_fentry_v612.o \ + bpf_generic_fexit_v612.o # lsm PROCESS += bpf_generic_lsm_core_v61.o bpf_generic_lsm_output_v61.o \ diff --git a/bpf/include/api.h b/bpf/include/api.h index 1fc6562f6e8..750dd9e0ee5 100644 --- a/bpf/include/api.h +++ b/bpf/include/api.h @@ -277,6 +277,10 @@ static long BPF_FUNC(ima_inode_hash, struct inode *inode, void *dst, uint32_t si static int BPF_FUNC(seq_write, struct seq_file *m, const void *data, uint32_t len); +/* Tracing */ +static int BPF_FUNC(get_func_arg, void *ctx, __u32 n, __u64 *value); +static int BPF_FUNC(get_func_ret, void *ctx, __u64 *value); + /** LLVM built-ins, mem*() routines work for constant size */ #ifndef memset diff --git a/bpf/process/bpf_generic_fentry.c b/bpf/process/bpf_generic_fentry.c new file mode 100644 index 00000000000..66834a62aa9 --- /dev/null +++ b/bpf/process/bpf_generic_fentry.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* Copyright Authors of Cilium */ + +#include "vmlinux.h" +#include "api.h" + +#define GENERIC_FENTRY + +#include "compiler.h" +#include "bpf_event.h" +#include "bpf_task.h" +#include "retprobe_map.h" +#include "types/operations.h" +#include "types/basic.h" +#include "policy_filter.h" + +char _license[] __attribute__((section("license"), used)) = "Dual BSD/GPL"; + +int generic_fentry_setup_event(void *ctx); +int generic_fentry_process_event(void *ctx); +int generic_fentry_process_filter(void *ctx); +int generic_fentry_filter_arg(void *ctx); +int generic_fentry_actions(void *ctx); +int generic_fentry_output(void *ctx); +int generic_fentry_path(void *ctx); + +struct { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(max_entries, 13); + __type(key, __u32); + __array(values, int(void *)); +} fentry_calls SEC(".maps") = { + .values = { + [TAIL_CALL_SETUP] = (void *)&generic_fentry_setup_event, + [TAIL_CALL_PROCESS] = (void *)&generic_fentry_process_event, + [TAIL_CALL_FILTER] = (void *)&generic_fentry_process_filter, + [TAIL_CALL_ARGS] = (void *)&generic_fentry_filter_arg, + [TAIL_CALL_ACTIONS] = (void *)&generic_fentry_actions, + [TAIL_CALL_SEND] = (void *)&generic_fentry_output, +#ifndef __V61_BPF_PROG + [TAIL_CALL_PATH] = (void *)&generic_fentry_path, +#endif + }, +}; + +#include "generic_maps.h" +#include "generic_calls.h" + +#define SECTION_ENTRY "fentry/generic_fentry" +#define SECTION_TAIL "fentry/generic_fentry_tail" + +__attribute__((section((SECTION_ENTRY)), used)) int +generic_fentry_event(struct pt_regs *ctx) +{ + return generic_start_process_filter(ctx, (struct bpf_map_def *)&fentry_calls); +} + +__attribute__((section(SECTION_TAIL), used)) int +generic_fentry_setup_event(void *ctx) +{ + return generic_process_event_and_setup(ctx, (struct bpf_map_def *)&fentry_calls); +} + +__attribute__((section(SECTION_TAIL), used)) int +generic_fentry_process_event(void *ctx) +{ + return generic_process_event(ctx, (struct bpf_map_def *)&fentry_calls); +} + +__attribute__((section(SECTION_TAIL), used)) int +generic_fentry_process_filter(void *ctx) +{ + int ret; + + ret = generic_process_filter(); + if (ret == PFILTER_CONTINUE) + tail_call(ctx, &fentry_calls, TAIL_CALL_FILTER); + else if (ret == PFILTER_ACCEPT) + tail_call(ctx, &fentry_calls, TAIL_CALL_SETUP); + /* If filter does not accept drop it. Ideally we would + * log error codes for later review, TBD. + */ + return PFILTER_REJECT; +} + +__attribute__((section(SECTION_TAIL), used)) int +generic_fentry_filter_arg(void *ctx) +{ + return generic_filter_arg(ctx, (struct bpf_map_def *)&fentry_calls, true); +} + +__attribute__((section(SECTION_TAIL), used)) int +generic_fentry_actions(void *ctx) +{ + generic_actions(ctx, (struct bpf_map_def *)&fentry_calls); + return 0; +} + +__attribute__((section(SECTION_TAIL), used)) int +generic_fentry_output(void *ctx) +{ + return generic_output(ctx, MSG_OP_GENERIC_KPROBE); +} + +#ifndef __V61_BPF_PROG +__attribute__((section(SECTION_TAIL), used)) int +generic_fentry_path(void *ctx) +{ + return generic_path(ctx, (struct bpf_map_def *)&fentry_calls); +} +#endif diff --git a/bpf/process/bpf_generic_fexit.c b/bpf/process/bpf_generic_fexit.c new file mode 100644 index 00000000000..ab91163ef7f --- /dev/null +++ b/bpf/process/bpf_generic_fexit.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* Copyright Authors of Cilium */ + +#include "vmlinux.h" +#include "api.h" + +#define GENERIC_FEXIT + +#include "compiler.h" +#include "bpf_tracing.h" +#include "bpf_event.h" +#include "bpf_task.h" +#include "retprobe_map.h" +#include "types/basic.h" + +#define MAX_FILENAME 8096 + +char _license[] __attribute__((section("license"), used)) = "Dual BSD/GPL"; + +int generic_fexit_filter_arg(void *ctx); +int generic_fexit_actions(void *ctx); +int generic_fexit_output(void *ctx); + +struct { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(max_entries, 6); + __type(key, __u32); + __array(values, int(struct pt_regs *)); +} fexit_calls SEC(".maps") = { + .values = { + [TAIL_CALL_ARGS] = (void *)&generic_fexit_filter_arg, + [TAIL_CALL_ACTIONS] = (void *)&generic_fexit_actions, + [TAIL_CALL_SEND] = (void *)&generic_fexit_output, + }, +}; + +#include "generic_maps.h" +#include "generic_calls.h" + +#define SECTION_ENTRY "fexit/generic_fexit" +#define SECTION_TAIL "fexit/generic_fexit_tail" + +__attribute__((section(SECTION_ENTRY), used)) int +generic_fexit_event(void *ctx) +{ + __u64 ret; + + get_func_ret(ctx, &ret); + generic_retkprobe(ctx, (struct bpf_map_def *)&fexit_calls, ret); + return 0; +} + +__attribute__((section(SECTION_TAIL), used)) int +generic_fexit_filter_arg(void *ctx) +{ + generic_filter_arg(ctx, (struct bpf_map_def *)&fexit_calls, false); + return 0; +} + +__attribute__((section(SECTION_TAIL), used)) int +generic_fexit_actions(void *ctx) +{ + generic_actions(ctx, (struct bpf_map_def *)&fexit_calls); + return 0; +} + +__attribute__((section(SECTION_TAIL), used)) int +generic_fexit_output(void *ctx) +{ + generic_output(ctx, MSG_OP_GENERIC_KPROBE); + return 0; +} diff --git a/bpf/process/generic_calls.h b/bpf/process/generic_calls.h index 8e322ecc347..24280a9bc56 100644 --- a/bpf/process/generic_calls.h +++ b/bpf/process/generic_calls.h @@ -664,6 +664,37 @@ generic_process_event_and_setup(struct pt_regs *ctx, struct bpf_map_def *tailcal retprobe_map_set(e->func_id, e->retprobe_id, e->common.ktime, 1); #endif +#ifdef GENERIC_FENTRY + struct bpf_raw_tracepoint_args *raw_args = (struct bpf_raw_tracepoint_args *)ctx; + + if (config->syscall) { + struct pt_regs *_ctx = (struct pt_regs *)BPF_CORE_READ(raw_args, args[0]); + + if (!_ctx) + return 0; + e->a0 = PT_REGS_PARM1_CORE_SYSCALL(_ctx); + e->a1 = PT_REGS_PARM2_CORE_SYSCALL(_ctx); + e->a2 = PT_REGS_PARM3_CORE_SYSCALL(_ctx); + e->a3 = PT_REGS_PARM4_CORE_SYSCALL(_ctx); + e->a4 = PT_REGS_PARM5_CORE_SYSCALL(_ctx); + } else { + e->a0 = BPF_CORE_READ(raw_args, args[0]); + e->a1 = BPF_CORE_READ(raw_args, args[1]); + e->a2 = BPF_CORE_READ(raw_args, args[2]); + e->a3 = BPF_CORE_READ(raw_args, args[3]); + e->a4 = BPF_CORE_READ(raw_args, args[4]); + } + + generic_process_init(e, MSG_OP_GENERIC_KPROBE, config); + + e->retprobe_id = retprobe_map_get_key(ctx); + + /* If return arg is needed mark retprobe */ + ty = config->argreturn; + if (ty > 0) + retprobe_map_set(e->func_id, e->retprobe_id, e->common.ktime, 1); +#endif + #ifdef GENERIC_LSM struct bpf_raw_tracepoint_args *raw_args = (struct bpf_raw_tracepoint_args *)ctx; diff --git a/contrib/verify/verify_test.go b/contrib/verify/verify_test.go index e5e4d3f9dbd..63b0e2a8839 100644 --- a/contrib/verify/verify_test.go +++ b/contrib/verify/verify_test.go @@ -64,6 +64,12 @@ func TestVerifyTetragonPrograms(t *testing.T) { continue } + // Can't load fentry/fext objects without loader setup + if strings.HasPrefix(fileName, "bpf_generic_fentry") || + strings.HasPrefix(fileName, "bpf_generic_fexit") { + continue + } + // Skip v6.1 objects check for kernel < 6.1 if strings.HasSuffix(fileName, "61.o") && !kernels.MinKernelVersion("6.1") { continue diff --git a/pkg/bpf/detect_linux.go b/pkg/bpf/detect_linux.go index e6489b74f17..f62c7cf9003 100644 --- a/pkg/bpf/detect_linux.go +++ b/pkg/bpf/detect_linux.go @@ -47,6 +47,7 @@ var ( missedStatsKprobeMulti Feature batchUpdate Feature uprobeRefCtrOffset Feature + getFuncRetHelper Feature ) func HasOverrideHelper() bool { @@ -57,6 +58,10 @@ func HasSignalHelper() bool { return features.HaveProgramHelper(ebpf.Kprobe, asm.FnSendSignal) == nil } +func HasFentryProgram() bool { + return features.HaveProgramType(ebpf.Tracing) == nil +} + func detectKprobeMulti() bool { prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ Name: "probe_bpf_kprobe_multi_link", @@ -508,14 +513,51 @@ func HasUprobeRefCtrOffset() bool { return uprobeRefCtrOffset.detected } +func detectGetFuncRetHelper() bool { + sysGetcpu, err := arch.AddSyscallPrefix("sys_getcpu") + if err != nil { + return false + } + prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{ + Name: "probe_get_func_ret", + Type: ebpf.Tracing, + AttachType: ebpf.AttachTraceFExit, + Instructions: asm.Instructions{ + asm.Mov.Reg(asm.R2, asm.R10), + asm.Add.Imm(asm.R2, -8), + asm.FnGetFuncRet.Call(), + asm.Mov.Imm(asm.R0, 0), + asm.Return(), + }, + License: "GPL", + AttachTo: sysGetcpu, + }) + if err != nil { + return false + } + prog.Close() + return true +} + +func detectGetFuncRetHelperOnce() { + getFuncRetHelper.init.Do(func() { + getFuncRetHelper.detected = detectGetFuncRetHelper() + }) +} + +func HasGetFuncRetHelper() bool { + detectGetFuncRetHelperOnce() + return getFuncRetHelper.detected +} + func LogFeatures() string { // once we have detected all features, flush the BTF spec // we cache all values so calling again a Has* function will // not load the BTF again defer ebtf.FlushKernelSpec() - return fmt.Sprintf("override_return: %t, buildid: %t, kprobe_multi: %t, uprobe_multi %t, fmodret: %t, fmodret_syscall: %t, signal: %t, large: %t, link_pin: %t, lsm: %t, missed_stats_kprobe_multi: %t, missed_stats_kprobe: %t, batch_update: %t, uprobe_refctroff: %t", + return fmt.Sprintf("override_return: %t, buildid: %t, kprobe_multi: %t, uprobe_multi %t, fmodret: %t, fmodret_syscall: %t, signal: %t, large: %t, link_pin: %t, lsm: %t, missed_stats_kprobe_multi: %t, missed_stats_kprobe: %t, batch_update: %t, uprobe_refctroff: %t, fentry %t, get_func_ret %t", HasOverrideHelper(), HasBuildId(), HasKprobeMulti(), HasUprobeMulti(), HasModifyReturn(), HasModifyReturnSyscall(), HasSignalHelper(), HasProgramLargeSize(), HasLinkPin(), HasLSMPrograms(), HasMissedStatsKprobeMulti(), HasMissedStatsPerfEvent(), - HasBatchAPI(), HasUprobeRefCtrOffset()) + HasBatchAPI(), HasUprobeRefCtrOffset(), HasFentryProgram(), HasGetFuncRetHelper()) } diff --git a/pkg/config/config_linux.go b/pkg/config/config_linux.go index c0ff79c0d5d..aa467369106 100644 --- a/pkg/config/config_linux.go +++ b/pkg/config/config_linux.go @@ -74,6 +74,19 @@ func GenericKprobeObjs(multi bool) (string, string) { return "bpf_generic_kprobe.o", "bpf_generic_retkprobe.o" } +func GenericTracingObjs() (string, string) { + if EnableV612Progs() { + return "bpf_generic_fentry_v612.o", "bpf_generic_fexit_v612.o" + } else if EnableV61Progs() { + return "bpf_generic_fentry_v61.o", "bpf_generic_fexit_v61.o" + } else if kernels.MinKernelVersion("5.11") { + return "bpf_generic_fentry_v511.o", "bpf_generic_fexit_v511.o" + } else if EnableLargeProgs() { + return "bpf_generic_fentry_v53.o", "bpf_generic_fexit_v53.o" + } + return "bpf_generic_fentry.o", "bpf_generic_fexit.o" +} + func GenericUprobeObjs(multi bool) string { if multi { if EnableV612Progs() { diff --git a/pkg/sensors/program/loader_linux.go b/pkg/sensors/program/loader_linux.go index 01d76c239ed..081288811df 100644 --- a/pkg/sensors/program/loader_linux.go +++ b/pkg/sensors/program/loader_linux.go @@ -378,6 +378,19 @@ func MultiUprobeAttach(load *Program, bpfDir string) AttachFunc { } } +func TracingOpen(load *Program) OpenFunc { + return func(coll *ebpf.CollectionSpec) error { + data, ok := load.AttachData.(*TracingAttachData) + if !ok { + return nil + } + for _, spec := range coll.Programs { + spec.AttachTo = data.AttachTo + } + return nil + } +} + func TracingAttach(load *Program, bpfDir string) AttachFunc { return func(_ *ebpf.Collection, _ *ebpf.CollectionSpec, prog *ebpf.Program, spec *ebpf.ProgramSpec) (unloader.Unloader, error) { @@ -632,6 +645,7 @@ func LoadFmodRetProgram(bpfDir string, load *Program, maps []*Map, progName stri func LoadTracingProgram(bpfDir string, load *Program, maps []*Map, verbose int) error { opts := &LoadOpts{ Attach: TracingAttach(load, bpfDir), + Open: TracingOpen(load), Maps: maps, } return loadProgram(bpfDir, load, opts, verbose) diff --git a/pkg/sensors/program/program.go b/pkg/sensors/program/program.go index ec2bb07a1c2..bca5482d1ac 100644 --- a/pkg/sensors/program/program.go +++ b/pkg/sensors/program/program.go @@ -73,6 +73,10 @@ type MapLoad struct { Load func(m *ebpf.Map, pinPathPrefix string) error } +type TracingAttachData struct { + AttachTo string +} + type MultiKprobeAttachData struct { Symbols []string Cookies []uint64 diff --git a/pkg/sensors/tracing/generickprobe.go b/pkg/sensors/tracing/generickprobe.go index 61f7f4afd74..5d4e3a112b6 100644 --- a/pkg/sensors/tracing/generickprobe.go +++ b/pkg/sensors/tracing/generickprobe.go @@ -643,7 +643,7 @@ func createGenericKprobeSensor( } dups[sym] = instance - id, err := addKprobe(sym, instance, &kprobes[i], &in) + id, err := addKprobe(sym, instance, &kprobes[i], &in, has) if err != nil { return nil, err } @@ -703,7 +703,7 @@ func initEventConfig() *api.EventConfig { // addKprobe will, amongst other things, create a generic kprobe entry and add // it to the genericKprobeTable. The caller should make sure that this entry is // properly removed on kprobe removal. -func addKprobe(funcName string, instance int, f *v1alpha1.KProbeSpec, in *addKprobeIn) (id idtable.EntryID, err error) { +func addKprobe(funcName string, instance int, f *v1alpha1.KProbeSpec, in *addKprobeIn, has hasMaps) (id idtable.EntryID, err error) { var argSigPrinters []argPrinter var argReturnPrinters []argPrinter var setRetprobe bool @@ -920,7 +920,8 @@ func addKprobe(funcName string, instance int, f *v1alpha1.KProbeSpec, in *addKpr eventConfig.FuncId = uint32(kprobeEntry.tableId.ID) logger.GetLogger(). - Info("Added kprobe", "return", setRetprobe, "function", kprobeEntry.funcName, "override", kprobeEntry.hasOverride) + Info("Added kprobe", "return", setRetprobe, "function", kprobeEntry.funcName, + "override", kprobeEntry.hasOverride, "enforcer", has.enforcer) return kprobeEntry.tableId, nil } @@ -931,20 +932,56 @@ func createKprobeSensorFromEntry(polInfo *policyInfo, kprobeEntry *genericKprobe loadProgName, loadProgRetName := config.GenericKprobeObjs(false) isSecurityFunc := strings.HasPrefix(kprobeEntry.funcName, "security_") + // We can use trampoline (fentry/fexit) in case: + // 1) it's not disabled (disable-kprobe-fentry option) + // 2) we do not do override or enforcer (FIXME) + // 3) we have fentry program support + // 4) fexit needs bpf_get_func_ret helper + useFentry := !polInfo.specOpts.DisableKprobeFentry && // 1 + !kprobeEntry.hasOverride && !has.enforcer && // 2 + bpf.HasFentryProgram() && // 3 + bpf.HasGetFuncRetHelper() // 4 + pinProg := kprobeEntry.funcName if kprobeEntry.instance != 0 { pinProg = fmt.Sprintf("%s:%d", kprobeEntry.funcName, kprobeEntry.instance) } - load := program.Builder( - path.Join(option.Config.HubbleLib, loadProgName), - kprobeEntry.funcName, - "kprobe/generic_kprobe", - pinProg, - "generic_kprobe"). - SetLoaderData(kprobeEntry.tableId). - SetPolicy(kprobeEntry.policyName) + var load *program.Program + + if useFentry { + data := &program.TracingAttachData{ + AttachTo: kprobeEntry.funcName, + } + + loadProgName, loadProgRetName = config.GenericTracingObjs() + + load = program.Builder( + path.Join(option.Config.HubbleLib, loadProgName), + kprobeEntry.funcName, + "fentry/generic_fentry", + pinProg, + "generic_kprobe"). + SetAttachData(data) + + tailCalls := program.MapBuilderProgram("fentry_calls", load) + maps = append(maps, tailCalls) + } else { + load = program.Builder( + path.Join(option.Config.HubbleLib, loadProgName), + kprobeEntry.funcName, + "kprobe/generic_kprobe", + pinProg, + "generic_kprobe") + + tailCalls := program.MapBuilderProgram("kprobe_calls", load) + maps = append(maps, tailCalls) + } + + load.SetPolicy(kprobeEntry.policyName) + load.SetLoaderData(kprobeEntry.tableId) load.Override = kprobeEntry.hasOverride + if load.Override { load.OverrideFmodRet = isSecurityFunc && bpf.HasModifyReturn() } @@ -959,9 +996,6 @@ func createKprobeSensorFromEntry(polInfo *policyInfo, kprobeEntry *genericKprobe configMap := program.MapBuilderProgram("config_map", load) maps = append(maps, configMap) - tailCalls := program.MapBuilderProgram("kprobe_calls", load) - maps = append(maps, tailCalls) - filterMap := program.MapBuilderProgram("filter_map", load) maps = append(maps, filterMap) @@ -1032,15 +1066,40 @@ func createKprobeSensorFromEntry(polInfo *policyInfo, kprobeEntry *genericKprobe if kprobeEntry.instance != 0 { pinRetProg = sensors.PathJoin(fmt.Sprintf("%s_return:%d", kprobeEntry.funcName, kprobeEntry.instance)) } - loadret := program.Builder( - path.Join(option.Config.HubbleLib, loadProgRetName), - kprobeEntry.funcName, - "kprobe/generic_retkprobe", - pinRetProg, - "generic_kprobe"). - SetRetProbe(true). - SetLoaderData(kprobeEntry.tableId). - SetPolicy(kprobeEntry.policyName) + + var loadret *program.Program + + if useFentry { + data := &program.TracingAttachData{ + AttachTo: kprobeEntry.funcName, + } + + loadret = program.Builder( + path.Join(option.Config.HubbleLib, loadProgRetName), + kprobeEntry.funcName, + "fexit/generic_fexit", + pinRetProg, + "generic_kprobe"). + SetAttachData(data) + + tailCalls := program.MapBuilderProgram("fexit_calls", loadret) + maps = append(maps, tailCalls) + } else { + loadret = program.Builder( + path.Join(option.Config.HubbleLib, loadProgRetName), + kprobeEntry.funcName, + "kprobe/generic_retkprobe", + pinRetProg, + "generic_kprobe") + + tailCalls := program.MapBuilderProgram("retkprobe_calls", loadret) + maps = append(maps, tailCalls) + } + + loadret.SetRetProbe(true) + loadret.SetLoaderData(kprobeEntry.tableId) + loadret.SetPolicy(kprobeEntry.policyName) + progs = append(progs, loadret) retProbe := program.MapBuilderSensor("retprobe_map", loadret) @@ -1049,9 +1108,6 @@ func createKprobeSensorFromEntry(polInfo *policyInfo, kprobeEntry *genericKprobe retConfigMap := program.MapBuilderProgram("config_map", loadret) maps = append(maps, retConfigMap) - tailCalls := program.MapBuilderProgram("retkprobe_calls", loadret) - maps = append(maps, tailCalls) - filterMap := program.MapBuilderProgram("filter_map", loadret) maps = append(maps, filterMap) @@ -1125,10 +1181,14 @@ func loadSingleKprobeSensor(id idtable.EntryID, bpfDir string, load *program.Pro } load.MapLoad = append(load.MapLoad, config) - if err := program.LoadKprobeProgram(bpfDir, load, maps, verbose); err == nil { - logger.GetLogger().Info(fmt.Sprintf("Loaded generic kprobe program: %s -> %s", load.Name, load.Attach)) + if load.Label == "fentry/generic_fentry" || load.Label == "fexit/generic_fexit" { + if err = program.LoadTracingProgram(bpfDir, load, maps, verbose); err == nil { + logger.GetLogger().Info(fmt.Sprintf("Loaded generic fentry program: %s -> %s", load.Name, load.Attach)) + } } else { - return err + if err = program.LoadKprobeProgram(bpfDir, load, maps, verbose); err == nil { + logger.GetLogger().Info(fmt.Sprintf("Loaded generic kprobe program: %s -> %s", load.Name, load.Attach)) + } } return err diff --git a/pkg/sensors/tracing/kprobe_test.go b/pkg/sensors/tracing/kprobe_test.go index 5f0ec05cca8..17027825726 100644 --- a/pkg/sensors/tracing/kprobe_test.go +++ b/pkg/sensors/tracing/kprobe_test.go @@ -4323,8 +4323,8 @@ spec: WithArgs(ec.NewKprobeArgumentListMatcher(). WithValues( ec.NewKprobeArgumentChecker().WithBpfAttrArg(ec.NewKprobeBpfAttrChecker(). - WithProgName(sm.Full("generic_kprobe_")). - WithProgType(sm.Full("BPF_PROG_TYPE_KPROBE")), + WithProgName(sm.Regex("generic_kprobe_|generic_fentry_")). + WithProgType(sm.Regex("BPF_PROG_TYPE_KPROBE|BPF_PROG_TYPE_TRACING")), ), )) @@ -4459,6 +4459,9 @@ kind: TracingPolicy metadata: name: "sys-read" spec: + options: + - name: "disable-kprobe-fentry" + value: "1" kprobes: - call: "sys_read" syscall: true diff --git a/pkg/sensors/tracing/options.go b/pkg/sensors/tracing/options.go index 677918bcd44..f4d2aca7315 100644 --- a/pkg/sensors/tracing/options.go +++ b/pkg/sensors/tracing/options.go @@ -41,10 +41,11 @@ func overrideMethodParse(s string) OverrideMethod { } type specOptions struct { - DisableKprobeMulti bool - DisableUprobeMulti bool - OverrideMethod OverrideMethod - policyMode policyconf.Mode + DisableKprobeFentry bool + DisableKprobeMulti bool + DisableUprobeMulti bool + OverrideMethod OverrideMethod + policyMode policyconf.Mode } type opt struct { @@ -92,6 +93,12 @@ var opts = map[string]opt{ return nil }, }, + "disable-kprobe-fentry": { + set: func(str string, options *specOptions) (err error) { + options.DisableKprobeFentry, err = strconv.ParseBool(str) + return err + }, + }, } func getSpecOptions(specs []v1alpha1.OptionSpec) (*specOptions, error) {