diff --git a/bpf/Makefile b/bpf/Makefile index 778053579cf..f13b3da1694 100644 --- a/bpf/Makefile +++ b/bpf/Makefile @@ -75,6 +75,9 @@ PROCESS += bpf_generic_kprobe_v61.o bpf_generic_retkprobe_v61.o \ PROCESS += bpf_generic_lsm_core_v61.o bpf_generic_lsm_output_v61.o \ bpf_generic_lsm_ima_file_v61.o bpf_generic_lsm_ima_bprm_v61.o +# session +PROCESS += bpf_session_kprobe.o + CGROUP = bpf_cgroup_mkdir.o bpf_cgroup_rmdir.o bpf_cgroup_release.o bpf_cgtracker.o BPFTEST = bpf_lseek.o @@ -116,6 +119,7 @@ CFLAGS_bpf_enforcer.o = -D__BPF_OVERRIDE_RETURN CFLAGS_bpf_multi_enforcer.o = -D__BPF_OVERRIDE_RETURN -D__MULTI_KPROBE CFLAGS_bpf_generic_lsm_core.o = -D__LARGE_BPF_PROG CFLAGS_bpf_generic_lsm_output.o = -D__LARGE_BPF_PROG +CFLAGS_bpf_session_kprobe.o = -D__LARGE_BPF_PROG -D__LARGE_MAP_KEYS -D__V61_BPF_PROG -D__MULTI_KPROBE # Rules MTARGET_o = $(patsubst $(DEPSDIR)%.d,$(OBJSDIR)%.o,$@) diff --git a/bpf/include/api.h b/bpf/include/api.h index 82026545cdf..8ba4aecac62 100644 --- a/bpf/include/api.h +++ b/bpf/include/api.h @@ -303,4 +303,9 @@ static int BPF_FUNC(seq_write, struct seq_file *m, const void *data, uint32_t le #endif #endif +#define __ksym __attribute__((section(".ksyms"))) + +extern bool bpf_session_is_return(void) __ksym; +extern __u64 *bpf_session_cookie(void) __ksym; + #endif /* __BPF_API__ */ diff --git a/bpf/process/bpf_session_kprobe.c b/bpf/process/bpf_session_kprobe.c new file mode 100644 index 00000000000..e761bcc5f0b --- /dev/null +++ b/bpf/process/bpf_session_kprobe.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* Copyright Authors of Cilium */ + +#include "vmlinux.h" +#include "api.h" + +#define GENERIC_KPROBE + +#include "compiler.h" +#include "bpf_event.h" +#include "bpf_task.h" +#include "retprobe_map.h" +#include "types/operations.h" +#include "types/basic.h" +#include "pfilter.h" +#include "policy_filter.h" + +char _license[] __attribute__((section("license"), used)) = "Dual BSD/GPL"; + +int generic_kprobe_setup_event(void *ctx); +int generic_kprobe_process_event(void *ctx); +int generic_kprobe_process_filter(void *ctx); +int generic_kprobe_filter_arg(void *ctx); +int generic_kprobe_actions(void *ctx); +int generic_kprobe_output(void *ctx); + +struct { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(max_entries, 13); + __uint(key_size, sizeof(__u32)); + __array(values, int(void *)); +} kprobe_calls SEC(".maps") = { + .values = { + [0] = (void *)&generic_kprobe_setup_event, + [1] = (void *)&generic_kprobe_process_event, + [2] = (void *)&generic_kprobe_process_filter, + [3] = (void *)&generic_kprobe_filter_arg, + [4] = (void *)&generic_kprobe_actions, + [5] = (void *)&generic_kprobe_output, + }, +}; + +int generic_retkprobe_filter_arg(void *ctx); +int generic_retkprobe_actions(void *ctx); +int generic_retkprobe_output(void *ctx); + +struct { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(max_entries, 6); + __uint(key_size, sizeof(__u32)); + __array(values, int(void *)); +} retkprobe_calls SEC(".maps") = { + .values = { + [3] = (void *)&generic_retkprobe_filter_arg, + [4] = (void *)&generic_retkprobe_actions, + [5] = (void *)&generic_retkprobe_output, + }, +}; + +#include "generic_maps.h" +#include "generic_calls.h" + +#define MAIN "kprobe.session/generic_kprobe" + +__attribute__((section((MAIN)), used)) int +generic_kprobe_event(struct pt_regs *ctx) +{ + if (bpf_session_is_return()) { + return generic_retkprobe(ctx, (struct bpf_map_def *)&retkprobe_calls, + PT_REGS_RC(ctx)); + } + + return generic_start_process_filter(ctx, (struct bpf_map_def *)&kprobe_calls); +} + +__attribute__((section("kprobe.session"), used)) int +generic_kprobe_setup_event(void *ctx) +{ + return generic_process_event_and_setup(ctx, (struct bpf_map_def *)&kprobe_calls); +} + +__attribute__((section("kprobe.session"), used)) int +generic_kprobe_process_event(void *ctx) +{ + return generic_process_event(ctx, (struct bpf_map_def *)&kprobe_calls); +} + +__attribute__((section("kprobe.session"), used)) int +generic_kprobe_process_filter(void *ctx) +{ + int ret; + + ret = generic_process_filter(); + if (ret == PFILTER_CONTINUE) + tail_call(ctx, &kprobe_calls, TAIL_CALL_FILTER); + else if (ret == PFILTER_ACCEPT) + tail_call(ctx, &kprobe_calls, 0); + /* If filter does not accept drop it. Ideally we would + * log error codes for later review, TBD. + */ + return ret == PFILTER_REJECT ? 1 : 0; +} + +__attribute__((section("kprobe.session"), used)) int +generic_kprobe_filter_arg(void *ctx) +{ + return generic_filter_arg(ctx, (struct bpf_map_def *)&kprobe_calls, true); +} + +__attribute__((section("kprobe.session"), used)) int +generic_kprobe_actions(void *ctx) +{ + generic_actions(ctx, (struct bpf_map_def *)&kprobe_calls, true); + return 0; +} + +__attribute__((section("kprobe.session"), used)) int +generic_kprobe_output(void *ctx) +{ + return generic_output(ctx, MSG_OP_GENERIC_KPROBE); +} + +__attribute__((section("kprobe.session"), used)) int +generic_retkprobe_filter_arg(void *ctx) +{ + return generic_filter_arg(ctx, (struct bpf_map_def *)&retkprobe_calls, false); +} + +__attribute__((section("kprobe.session"), used)) int +generic_retkprobe_actions(void *ctx) +{ + generic_actions(ctx, (struct bpf_map_def *)&retkprobe_calls, false); + return 0; +} + +__attribute__((section("kprobe.session"), used)) int +generic_retkprobe_output(void *ctx) +{ + return generic_output(ctx, MSG_OP_GENERIC_KPROBE); +}