Commit 27d89baa authored by Menglong Dong's avatar Menglong Dong Committed by Alexei Starovoitov
Browse files

bpf: support fsession for bpf_session_is_return



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: default avatarMenglong Dong <dongml2@chinatelecom.cn>
Co-developed-by: default avatarLeon Hwang <leon.hwang@linux.dev>
Signed-off-by: default avatarLeon Hwang <leon.hwang@linux.dev>
Link: https://lore.kernel.org/r/20260124062008.8657-5-dongml2@chinatelecom.cn


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 8fe4dc4f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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;
+13 −0
Original line number Diff line number Diff line
@@ -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) {
+26 −13
Original line number Diff line number Diff line
@@ -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);