Re: [PATCH RFCv2 bpf-next 2/4] bpf: Add bpf_kprobe_multi_is_return kfunc

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Feb 28, 2024 at 1:03 AM Jiri Olsa <jolsa@xxxxxxxxxx> wrote:
>
> Adding bpf_kprobe_multi_is_return kfunc that returns true if the
> bpf program is executed from the exit probe of the kprobe multi
> link attached in wrapper mode. It returns false otherwise.
>
> Adding new kprobe hook for kprobe program type.
>
> Signed-off-by: Jiri Olsa <jolsa@xxxxxxxxxx>
> ---
>  kernel/bpf/btf.c         |  3 +++
>  kernel/trace/bpf_trace.c | 49 +++++++++++++++++++++++++++++++++++++---
>  2 files changed, 49 insertions(+), 3 deletions(-)
>
> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> index 6ff0bd1a91d5..5ab55720e881 100644
> --- a/kernel/bpf/btf.c
> +++ b/kernel/bpf/btf.c
> @@ -218,6 +218,7 @@ enum btf_kfunc_hook {
>         BTF_KFUNC_HOOK_SOCKET_FILTER,
>         BTF_KFUNC_HOOK_LWT,
>         BTF_KFUNC_HOOK_NETFILTER,
> +       BTF_KFUNC_HOOK_KPROBE,
>         BTF_KFUNC_HOOK_MAX,
>  };
>
> @@ -8112,6 +8113,8 @@ static int bpf_prog_type_to_kfunc_hook(enum bpf_prog_type prog_type)
>                 return BTF_KFUNC_HOOK_LWT;
>         case BPF_PROG_TYPE_NETFILTER:
>                 return BTF_KFUNC_HOOK_NETFILTER;
> +       case BPF_PROG_TYPE_KPROBE:
> +               return BTF_KFUNC_HOOK_KPROBE;
>         default:
>                 return BTF_KFUNC_HOOK_MAX;
>         }
> diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> index 726a8c71f0da..cb801c94b8fa 100644
> --- a/kernel/trace/bpf_trace.c
> +++ b/kernel/trace/bpf_trace.c
> @@ -2594,6 +2594,7 @@ struct bpf_kprobe_multi_run_ctx {
>         struct bpf_run_ctx run_ctx;
>         struct bpf_kprobe_multi_link *link;
>         unsigned long entry_ip;
> +       bool is_return;
>  };
>
>  struct user_syms {
> @@ -2793,11 +2794,13 @@ static u64 bpf_kprobe_multi_entry_ip(struct bpf_run_ctx *ctx)
>
>  static int
>  kprobe_multi_link_prog_run(struct bpf_kprobe_multi_link *link,
> -                          unsigned long entry_ip, struct pt_regs *regs)
> +                          unsigned long entry_ip, struct pt_regs *regs,
> +                          bool is_return)
>  {
>         struct bpf_kprobe_multi_run_ctx run_ctx = {
>                 .link = link,
>                 .entry_ip = entry_ip,
> +               .is_return = is_return,
>         };
>         struct bpf_run_ctx *old_run_ctx;
>         int err;
> @@ -2830,7 +2833,7 @@ kprobe_multi_link_handler(struct fprobe *fp, unsigned long fentry_ip,
>         int err;
>
>         link = container_of(fp, struct bpf_kprobe_multi_link, fp);
> -       err = kprobe_multi_link_prog_run(link, get_entry_ip(fentry_ip), regs);
> +       err = kprobe_multi_link_prog_run(link, get_entry_ip(fentry_ip), regs, false);
>         return link->is_wrapper ? err : 0;
>  }
>
> @@ -2842,7 +2845,7 @@ kprobe_multi_link_exit_handler(struct fprobe *fp, unsigned long fentry_ip,
>         struct bpf_kprobe_multi_link *link;
>
>         link = container_of(fp, struct bpf_kprobe_multi_link, fp);
> -       kprobe_multi_link_prog_run(link, get_entry_ip(fentry_ip), regs);
> +       kprobe_multi_link_prog_run(link, get_entry_ip(fentry_ip), regs, true);
>  }
>
>  static int symbols_cmp_r(const void *a, const void *b, const void *priv)
> @@ -3111,6 +3114,46 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
>         kvfree(cookies);
>         return err;
>  }
> +
> +__bpf_kfunc_start_defs();
> +
> +__bpf_kfunc bool bpf_kprobe_multi_is_return(void)

and for uprobes we'll have bpf_uprobe_multi_is_return?...

BTW, have you tried implementing a "session cookie" idea?


> +{
> +       struct bpf_kprobe_multi_run_ctx *run_ctx;
> +
> +       run_ctx = container_of(current->bpf_ctx, struct bpf_kprobe_multi_run_ctx, run_ctx);
> +       return run_ctx->is_return;
> +}
> +
> +__bpf_kfunc_end_defs();
> +
> +BTF_KFUNCS_START(kprobe_multi_kfunc_set_ids)
> +BTF_ID_FLAGS(func, bpf_kprobe_multi_is_return)
> +BTF_KFUNCS_END(kprobe_multi_kfunc_set_ids)
> +
> +static int bpf_kprobe_multi_filter(const struct bpf_prog *prog, u32 kfunc_id)
> +{
> +       if (!btf_id_set8_contains(&kprobe_multi_kfunc_set_ids, kfunc_id))
> +               return 0;
> +
> +       if (prog->expected_attach_type != BPF_TRACE_KPROBE_MULTI)
> +               return -EACCES;
> +
> +       return 0;
> +}
> +
> +static const struct btf_kfunc_id_set bpf_kprobe_multi_kfunc_set = {
> +       .owner = THIS_MODULE,
> +       .set = &kprobe_multi_kfunc_set_ids,
> +       .filter = bpf_kprobe_multi_filter,
> +};
> +
> +static int __init bpf_kprobe_multi_kfuncs_init(void)
> +{
> +       return register_btf_kfunc_id_set(BPF_PROG_TYPE_KPROBE, &bpf_kprobe_multi_kfunc_set);
> +}
> +
> +late_initcall(bpf_kprobe_multi_kfuncs_init);
>  #else /* !CONFIG_FPROBE */
>  int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
>  {
> --
> 2.43.2
>





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux