]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bpf: support fsession for bpf_session_is_return
authorMenglong Dong <menglong8.dong@gmail.com>
Sat, 24 Jan 2026 06:19:59 +0000 (14:19 +0800)
committerAlexei Starovoitov <ast@kernel.org>
Sun, 25 Jan 2026 02:49:36 +0000 (18:49 -0800)
If fsession exists, we will use the bit (1 << BPF_TRAMP_IS_RETURN_SHIFT)
in ((u64 *)ctx)[-1] to store the "is_return" flag.

The logic of bpf_session_is_return() for fsession is implemented in the
verifier by inline following code:

  bool bpf_session_is_return(void *ctx)
  {
      return (((u64 *)ctx)[-1] >> BPF_TRAMP_IS_RETURN_SHIFT) & 1;
  }

Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
Co-developed-by: Leon Hwang <leon.hwang@linux.dev>
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
Link: https://lore.kernel.org/r/20260124062008.8657-5-dongml2@chinatelecom.cn
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
include/linux/bpf.h
kernel/bpf/verifier.c
kernel/trace/bpf_trace.c

index 41228b0add52ecb985ce32bd8c6bed2d4835021e..29eecd79352e9e2ea489b9bbfa95a721ecbe7b30 100644 (file)
@@ -1229,6 +1229,8 @@ enum {
 #endif
 };
 
+#define BPF_TRAMP_IS_RETURN_SHIFT      63
+
 struct bpf_tramp_links {
        struct bpf_tramp_link *links[BPF_MAX_TRAMP_LINKS];
        int nr_links;
index 0fa73d56cb8ba449ae62fb0a47ce8d2e89451388..d04aea235a128f0e5fb1949617a7240454e3a2a1 100644 (file)
@@ -23011,6 +23011,19 @@ static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
                   desc->func_id == special_kfunc_list[KF_bpf_rdonly_cast]) {
                insn_buf[0] = BPF_MOV64_REG(BPF_REG_0, BPF_REG_1);
                *cnt = 1;
+       } else if (desc->func_id == special_kfunc_list[KF_bpf_session_is_return] &&
+                  env->prog->expected_attach_type == BPF_TRACE_FSESSION) {
+               /*
+                * inline the bpf_session_is_return() for fsession:
+                *   bool bpf_session_is_return(void *ctx)
+                *   {
+                *       return (((u64 *)ctx)[-1] >> BPF_TRAMP_IS_RETURN_SHIFT) & 1;
+                *   }
+                */
+               insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
+               insn_buf[1] = BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, BPF_TRAMP_IS_RETURN_SHIFT);
+               insn_buf[2] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1);
+               *cnt = 3;
        }
 
        if (env->insn_aux_data[insn_idx].arg_prog) {
index 13f0a2de33b72652caab983ef081834c73e91648..f7baeb8278cac8c4f93bfd62469dab26586f4531 100644 (file)
@@ -1286,7 +1286,8 @@ static bool is_kprobe_multi(const struct bpf_prog *prog)
 
 static inline bool is_kprobe_session(const struct bpf_prog *prog)
 {
-       return prog->expected_attach_type == BPF_TRACE_KPROBE_SESSION;
+       return prog->type == BPF_PROG_TYPE_KPROBE &&
+              prog->expected_attach_type == BPF_TRACE_KPROBE_SESSION;
 }
 
 static inline bool is_uprobe_multi(const struct bpf_prog *prog)
@@ -1297,7 +1298,14 @@ static inline bool is_uprobe_multi(const struct bpf_prog *prog)
 
 static inline bool is_uprobe_session(const struct bpf_prog *prog)
 {
-       return prog->expected_attach_type == BPF_TRACE_UPROBE_SESSION;
+       return prog->type == BPF_PROG_TYPE_KPROBE &&
+              prog->expected_attach_type == BPF_TRACE_UPROBE_SESSION;
+}
+
+static inline bool is_trace_fsession(const struct bpf_prog *prog)
+{
+       return prog->type == BPF_PROG_TYPE_TRACING &&
+              prog->expected_attach_type == BPF_TRACE_FSESSION;
 }
 
 static const struct bpf_func_proto *
@@ -3341,34 +3349,39 @@ __bpf_kfunc __u64 *bpf_session_cookie(void *ctx)
 
 __bpf_kfunc_end_defs();
 
-BTF_KFUNCS_START(kprobe_multi_kfunc_set_ids)
+BTF_KFUNCS_START(session_kfunc_set_ids)
 BTF_ID_FLAGS(func, bpf_session_is_return)
 BTF_ID_FLAGS(func, bpf_session_cookie)
-BTF_KFUNCS_END(kprobe_multi_kfunc_set_ids)
+BTF_KFUNCS_END(session_kfunc_set_ids)
 
-static int bpf_kprobe_multi_filter(const struct bpf_prog *prog, u32 kfunc_id)
+static int bpf_session_filter(const struct bpf_prog *prog, u32 kfunc_id)
 {
-       if (!btf_id_set8_contains(&kprobe_multi_kfunc_set_ids, kfunc_id))
+       if (!btf_id_set8_contains(&session_kfunc_set_ids, kfunc_id))
                return 0;
 
-       if (!is_kprobe_session(prog) && !is_uprobe_session(prog))
+       if (!is_kprobe_session(prog) && !is_uprobe_session(prog) && !is_trace_fsession(prog))
                return -EACCES;
 
        return 0;
 }
 
-static const struct btf_kfunc_id_set bpf_kprobe_multi_kfunc_set = {
+static const struct btf_kfunc_id_set bpf_session_kfunc_set = {
        .owner = THIS_MODULE,
-       .set = &kprobe_multi_kfunc_set_ids,
-       .filter = bpf_kprobe_multi_filter,
+       .set = &session_kfunc_set_ids,
+       .filter = bpf_session_filter,
 };
 
-static int __init bpf_kprobe_multi_kfuncs_init(void)
+static int __init bpf_trace_kfuncs_init(void)
 {
-       return register_btf_kfunc_id_set(BPF_PROG_TYPE_KPROBE, &bpf_kprobe_multi_kfunc_set);
+       int err = 0;
+
+       err = err ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_KPROBE, &bpf_session_kfunc_set);
+       err = err ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &bpf_session_kfunc_set);
+
+       return err;
 }
 
-late_initcall(bpf_kprobe_multi_kfuncs_init);
+late_initcall(bpf_trace_kfuncs_init);
 
 typedef int (*copy_fn_t)(void *dst, const void *src, u32 size, struct task_struct *tsk);