diff mbox series

[v2,bpf-next,08/11] bpf: Support ->fill_link_info for perf_event

Message ID 20230608103523.102267-9-laoar.shao@gmail.com (mailing list archive)
State Superseded
Delegated to: BPF
Headers show
Series bpf: Support ->fill_link_info for kprobe_multi and perf_event links | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-2 success Logs for build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-4 success Logs for build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-5 success Logs for build for x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-6 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-3 success Logs for build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-7 success Logs for test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-19 success Logs for test_progs_no_alu32_parallel on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-22 success Logs for test_progs_parallel on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for test_maps on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-11 success Logs for test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-13 success Logs for test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-14 success Logs for test_progs on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-15 success Logs for test_progs_no_alu32 on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-17 success Logs for test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-18 success Logs for test_progs_no_alu32 on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-20 success Logs for test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-21 success Logs for test_progs_no_alu32_parallel on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-23 success Logs for test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-24 success Logs for test_progs_parallel on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-27 success Logs for test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-28 success Logs for test_verifier on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-29 success Logs for veristat
bpf/vmtest-bpf-next-VM_Test-26 success Logs for test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-16 success Logs for test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-12 success Logs for test_progs on s390x with gcc
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for bpf-next, async
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1732 this patch: 1732
netdev/cc_maintainers success CCed 12 of 12 maintainers
netdev/build_clang success Errors and warnings before: 182 this patch: 182
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 1731 this patch: 1731
netdev/checkpatch warning WARNING: line length of 81 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-VM_Test-8 success Logs for test_maps on s390x with gcc

Commit Message

Yafang Shao June 8, 2023, 10:35 a.m. UTC
By introducing support for ->fill_link_info to the perf_event link, users
gain the ability to inspect it using `bpftool link show`. While the current
approach involves accessing this information via `bpftool perf show`,
consolidating link information for all link types in one place offers
greater convenience. Additionally, this patch extends support to the
generic perf event, which is not currently accommodated by
`bpftool perf show`. While only the perf type and config are exposed to
userspace, other attributes such as sample_period and sample_freq are
ignored. It's important to note that if kptr_restrict is set to 2, the
probed address will not be exposed, maintaining security measures.

Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
---
 include/uapi/linux/bpf.h       | 22 ++++++++++
 kernel/bpf/syscall.c           | 98 ++++++++++++++++++++++++++++++++++++++++++
 tools/include/uapi/linux/bpf.h | 22 ++++++++++
 3 files changed, 142 insertions(+)

Comments

Andrii Nakryiko June 8, 2023, 11:12 p.m. UTC | #1
On Thu, Jun 8, 2023 at 3:35 AM Yafang Shao <laoar.shao@gmail.com> wrote:
>
> By introducing support for ->fill_link_info to the perf_event link, users
> gain the ability to inspect it using `bpftool link show`. While the current
> approach involves accessing this information via `bpftool perf show`,
> consolidating link information for all link types in one place offers
> greater convenience. Additionally, this patch extends support to the
> generic perf event, which is not currently accommodated by
> `bpftool perf show`. While only the perf type and config are exposed to
> userspace, other attributes such as sample_period and sample_freq are
> ignored. It's important to note that if kptr_restrict is set to 2, the
> probed address will not be exposed, maintaining security measures.
>
> Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
> ---
>  include/uapi/linux/bpf.h       | 22 ++++++++++
>  kernel/bpf/syscall.c           | 98 ++++++++++++++++++++++++++++++++++++++++++
>  tools/include/uapi/linux/bpf.h | 22 ++++++++++
>  3 files changed, 142 insertions(+)
>
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index d99cc16..c3b821d 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -6443,6 +6443,28 @@ struct bpf_link_info {
>                         __u32 count;
>                         __u8  retprobe;
>                 } kprobe_multi;
> +               union {
> +                       struct {
> +                               /* The name is:
> +                                * a) uprobe: file name
> +                                * b) kprobe: kernel function
> +                                */
> +                               __aligned_u64 name; /* in/out: name buffer ptr */
> +                               __u32 name_len;
> +                               __u32 offset;   /* offset from the name */
> +                               __u64 addr;
> +                               __u8 retprobe;
> +                       } probe; /* uprobe, kprobe */
> +                       struct {
> +                               /* in/out: tracepoint name buffer ptr */
> +                               __aligned_u64 tp_name;
> +                               __u32 name_len;
> +                       } tp; /* tracepoint */
> +                       struct {
> +                               __u64 config;
> +                               __u32 type;
> +                       } event; /* generic perf event */

how should the user know which of those structs are relevant? we need
some enum to specify what kind of perf_event link it is?

> +               } perf_event;
>         };
>  } __attribute__((aligned(8)));
>

[...]
Yafang Shao June 9, 2023, 9:53 a.m. UTC | #2
On Fri, Jun 9, 2023 at 7:12 AM Andrii Nakryiko
<andrii.nakryiko@gmail.com> wrote:
>
> On Thu, Jun 8, 2023 at 3:35 AM Yafang Shao <laoar.shao@gmail.com> wrote:
> >
> > By introducing support for ->fill_link_info to the perf_event link, users
> > gain the ability to inspect it using `bpftool link show`. While the current
> > approach involves accessing this information via `bpftool perf show`,
> > consolidating link information for all link types in one place offers
> > greater convenience. Additionally, this patch extends support to the
> > generic perf event, which is not currently accommodated by
> > `bpftool perf show`. While only the perf type and config are exposed to
> > userspace, other attributes such as sample_period and sample_freq are
> > ignored. It's important to note that if kptr_restrict is set to 2, the
> > probed address will not be exposed, maintaining security measures.
> >
> > Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
> > ---
> >  include/uapi/linux/bpf.h       | 22 ++++++++++
> >  kernel/bpf/syscall.c           | 98 ++++++++++++++++++++++++++++++++++++++++++
> >  tools/include/uapi/linux/bpf.h | 22 ++++++++++
> >  3 files changed, 142 insertions(+)
> >
> > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > index d99cc16..c3b821d 100644
> > --- a/include/uapi/linux/bpf.h
> > +++ b/include/uapi/linux/bpf.h
> > @@ -6443,6 +6443,28 @@ struct bpf_link_info {
> >                         __u32 count;
> >                         __u8  retprobe;
> >                 } kprobe_multi;
> > +               union {
> > +                       struct {
> > +                               /* The name is:
> > +                                * a) uprobe: file name
> > +                                * b) kprobe: kernel function
> > +                                */
> > +                               __aligned_u64 name; /* in/out: name buffer ptr */
> > +                               __u32 name_len;
> > +                               __u32 offset;   /* offset from the name */
> > +                               __u64 addr;
> > +                               __u8 retprobe;
> > +                       } probe; /* uprobe, kprobe */
> > +                       struct {
> > +                               /* in/out: tracepoint name buffer ptr */
> > +                               __aligned_u64 tp_name;
> > +                               __u32 name_len;
> > +                       } tp; /* tracepoint */
> > +                       struct {
> > +                               __u64 config;
> > +                               __u32 type;
> > +                       } event; /* generic perf event */
>
> how should the user know which of those structs are relevant? we need
> some enum to specify what kind of perf_event link it is?
>

Do you mean that we add a new field 'type' into the union perf_event,
as follows ?
    union {
        __u32 type;
        struct {} probe;  /* BPF_LINK_TYPE_PERF_EVENT_PROBE */
        struct {} tp; /* BPF_LINK_TYPE_PERF_EVENT_TP */
        struct {} event; /* BPF_LINK_TYPE_PERF_EVENT_EVENT */
    };
Yafang Shao June 9, 2023, 9:56 a.m. UTC | #3
On Fri, Jun 9, 2023 at 5:53 PM Yafang Shao <laoar.shao@gmail.com> wrote:
>
> On Fri, Jun 9, 2023 at 7:12 AM Andrii Nakryiko
> <andrii.nakryiko@gmail.com> wrote:
> >
> > On Thu, Jun 8, 2023 at 3:35 AM Yafang Shao <laoar.shao@gmail.com> wrote:
> > >
> > > By introducing support for ->fill_link_info to the perf_event link, users
> > > gain the ability to inspect it using `bpftool link show`. While the current
> > > approach involves accessing this information via `bpftool perf show`,
> > > consolidating link information for all link types in one place offers
> > > greater convenience. Additionally, this patch extends support to the
> > > generic perf event, which is not currently accommodated by
> > > `bpftool perf show`. While only the perf type and config are exposed to
> > > userspace, other attributes such as sample_period and sample_freq are
> > > ignored. It's important to note that if kptr_restrict is set to 2, the
> > > probed address will not be exposed, maintaining security measures.
> > >
> > > Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
> > > ---
> > >  include/uapi/linux/bpf.h       | 22 ++++++++++
> > >  kernel/bpf/syscall.c           | 98 ++++++++++++++++++++++++++++++++++++++++++
> > >  tools/include/uapi/linux/bpf.h | 22 ++++++++++
> > >  3 files changed, 142 insertions(+)
> > >
> > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > > index d99cc16..c3b821d 100644
> > > --- a/include/uapi/linux/bpf.h
> > > +++ b/include/uapi/linux/bpf.h
> > > @@ -6443,6 +6443,28 @@ struct bpf_link_info {
> > >                         __u32 count;
> > >                         __u8  retprobe;
> > >                 } kprobe_multi;
> > > +               union {
> > > +                       struct {
> > > +                               /* The name is:
> > > +                                * a) uprobe: file name
> > > +                                * b) kprobe: kernel function
> > > +                                */
> > > +                               __aligned_u64 name; /* in/out: name buffer ptr */
> > > +                               __u32 name_len;
> > > +                               __u32 offset;   /* offset from the name */
> > > +                               __u64 addr;
> > > +                               __u8 retprobe;
> > > +                       } probe; /* uprobe, kprobe */
> > > +                       struct {
> > > +                               /* in/out: tracepoint name buffer ptr */
> > > +                               __aligned_u64 tp_name;
> > > +                               __u32 name_len;
> > > +                       } tp; /* tracepoint */
> > > +                       struct {
> > > +                               __u64 config;
> > > +                               __u32 type;
> > > +                       } event; /* generic perf event */
> >
> > how should the user know which of those structs are relevant? we need
> > some enum to specify what kind of perf_event link it is?
> >
>
> Do you mean that we add a new field 'type' into the union perf_event,
> as follows ?
>     union {
>         __u32 type;
>         struct {} probe;  /* BPF_LINK_TYPE_PERF_EVENT_PROBE */
>         struct {} tp; /* BPF_LINK_TYPE_PERF_EVENT_TP */
>         struct {} event; /* BPF_LINK_TYPE_PERF_EVENT_EVENT */
>     };
>

Correct it:

struct {
    __u32 type;
    union {
         struct {} probe;  /* BPF_LINK_TYPE_PERF_EVENT_PROBE */
         struct {} tp; /* BPF_LINK_TYPE_PERF_EVENT_TP */
         struct {} event; /* BPF_LINK_TYPE_PERF_EVENT_EVENT */
     };
} perf_event;
Andrii Nakryiko June 9, 2023, 6:26 p.m. UTC | #4
On Fri, Jun 9, 2023 at 2:57 AM Yafang Shao <laoar.shao@gmail.com> wrote:
>
> On Fri, Jun 9, 2023 at 5:53 PM Yafang Shao <laoar.shao@gmail.com> wrote:
> >
> > On Fri, Jun 9, 2023 at 7:12 AM Andrii Nakryiko
> > <andrii.nakryiko@gmail.com> wrote:
> > >
> > > On Thu, Jun 8, 2023 at 3:35 AM Yafang Shao <laoar.shao@gmail.com> wrote:
> > > >
> > > > By introducing support for ->fill_link_info to the perf_event link, users
> > > > gain the ability to inspect it using `bpftool link show`. While the current
> > > > approach involves accessing this information via `bpftool perf show`,
> > > > consolidating link information for all link types in one place offers
> > > > greater convenience. Additionally, this patch extends support to the
> > > > generic perf event, which is not currently accommodated by
> > > > `bpftool perf show`. While only the perf type and config are exposed to
> > > > userspace, other attributes such as sample_period and sample_freq are
> > > > ignored. It's important to note that if kptr_restrict is set to 2, the
> > > > probed address will not be exposed, maintaining security measures.
> > > >
> > > > Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
> > > > ---
> > > >  include/uapi/linux/bpf.h       | 22 ++++++++++
> > > >  kernel/bpf/syscall.c           | 98 ++++++++++++++++++++++++++++++++++++++++++
> > > >  tools/include/uapi/linux/bpf.h | 22 ++++++++++
> > > >  3 files changed, 142 insertions(+)
> > > >
> > > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > > > index d99cc16..c3b821d 100644
> > > > --- a/include/uapi/linux/bpf.h
> > > > +++ b/include/uapi/linux/bpf.h
> > > > @@ -6443,6 +6443,28 @@ struct bpf_link_info {
> > > >                         __u32 count;
> > > >                         __u8  retprobe;
> > > >                 } kprobe_multi;
> > > > +               union {
> > > > +                       struct {
> > > > +                               /* The name is:
> > > > +                                * a) uprobe: file name
> > > > +                                * b) kprobe: kernel function
> > > > +                                */
> > > > +                               __aligned_u64 name; /* in/out: name buffer ptr */
> > > > +                               __u32 name_len;
> > > > +                               __u32 offset;   /* offset from the name */
> > > > +                               __u64 addr;
> > > > +                               __u8 retprobe;
> > > > +                       } probe; /* uprobe, kprobe */
> > > > +                       struct {
> > > > +                               /* in/out: tracepoint name buffer ptr */
> > > > +                               __aligned_u64 tp_name;
> > > > +                               __u32 name_len;
> > > > +                       } tp; /* tracepoint */
> > > > +                       struct {
> > > > +                               __u64 config;
> > > > +                               __u32 type;
> > > > +                       } event; /* generic perf event */
> > >
> > > how should the user know which of those structs are relevant? we need
> > > some enum to specify what kind of perf_event link it is?
> > >
> >
> > Do you mean that we add a new field 'type' into the union perf_event,
> > as follows ?
> >     union {
> >         __u32 type;
> >         struct {} probe;  /* BPF_LINK_TYPE_PERF_EVENT_PROBE */
> >         struct {} tp; /* BPF_LINK_TYPE_PERF_EVENT_TP */
> >         struct {} event; /* BPF_LINK_TYPE_PERF_EVENT_EVENT */
> >     };
> >
>
> Correct it:
>
> struct {
>     __u32 type;
>     union {
>          struct {} probe;  /* BPF_LINK_TYPE_PERF_EVENT_PROBE */
>          struct {} tp; /* BPF_LINK_TYPE_PERF_EVENT_TP */
>          struct {} event; /* BPF_LINK_TYPE_PERF_EVENT_EVENT */
>      };
> } perf_event;

yes, something like this. Unless we want to leave  perf_event {} to
mean really perf event only, while kprobe/uprobe/tracepoint should be
their own separate sections at the same level of nestedness as
perf_Event and other cases. Not sure.

>
> --
> Regards
> Yafang
Yafang Shao June 10, 2023, 2:21 a.m. UTC | #5
On Sat, Jun 10, 2023 at 2:26 AM Andrii Nakryiko
<andrii.nakryiko@gmail.com> wrote:
>
> On Fri, Jun 9, 2023 at 2:57 AM Yafang Shao <laoar.shao@gmail.com> wrote:
> >
> > On Fri, Jun 9, 2023 at 5:53 PM Yafang Shao <laoar.shao@gmail.com> wrote:
> > >
> > > On Fri, Jun 9, 2023 at 7:12 AM Andrii Nakryiko
> > > <andrii.nakryiko@gmail.com> wrote:
> > > >
> > > > On Thu, Jun 8, 2023 at 3:35 AM Yafang Shao <laoar.shao@gmail.com> wrote:
> > > > >
> > > > > By introducing support for ->fill_link_info to the perf_event link, users
> > > > > gain the ability to inspect it using `bpftool link show`. While the current
> > > > > approach involves accessing this information via `bpftool perf show`,
> > > > > consolidating link information for all link types in one place offers
> > > > > greater convenience. Additionally, this patch extends support to the
> > > > > generic perf event, which is not currently accommodated by
> > > > > `bpftool perf show`. While only the perf type and config are exposed to
> > > > > userspace, other attributes such as sample_period and sample_freq are
> > > > > ignored. It's important to note that if kptr_restrict is set to 2, the
> > > > > probed address will not be exposed, maintaining security measures.
> > > > >
> > > > > Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
> > > > > ---
> > > > >  include/uapi/linux/bpf.h       | 22 ++++++++++
> > > > >  kernel/bpf/syscall.c           | 98 ++++++++++++++++++++++++++++++++++++++++++
> > > > >  tools/include/uapi/linux/bpf.h | 22 ++++++++++
> > > > >  3 files changed, 142 insertions(+)
> > > > >
> > > > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > > > > index d99cc16..c3b821d 100644
> > > > > --- a/include/uapi/linux/bpf.h
> > > > > +++ b/include/uapi/linux/bpf.h
> > > > > @@ -6443,6 +6443,28 @@ struct bpf_link_info {
> > > > >                         __u32 count;
> > > > >                         __u8  retprobe;
> > > > >                 } kprobe_multi;
> > > > > +               union {
> > > > > +                       struct {
> > > > > +                               /* The name is:
> > > > > +                                * a) uprobe: file name
> > > > > +                                * b) kprobe: kernel function
> > > > > +                                */
> > > > > +                               __aligned_u64 name; /* in/out: name buffer ptr */
> > > > > +                               __u32 name_len;
> > > > > +                               __u32 offset;   /* offset from the name */
> > > > > +                               __u64 addr;
> > > > > +                               __u8 retprobe;
> > > > > +                       } probe; /* uprobe, kprobe */
> > > > > +                       struct {
> > > > > +                               /* in/out: tracepoint name buffer ptr */
> > > > > +                               __aligned_u64 tp_name;
> > > > > +                               __u32 name_len;
> > > > > +                       } tp; /* tracepoint */
> > > > > +                       struct {
> > > > > +                               __u64 config;
> > > > > +                               __u32 type;
> > > > > +                       } event; /* generic perf event */
> > > >
> > > > how should the user know which of those structs are relevant? we need
> > > > some enum to specify what kind of perf_event link it is?
> > > >
> > >
> > > Do you mean that we add a new field 'type' into the union perf_event,
> > > as follows ?
> > >     union {
> > >         __u32 type;
> > >         struct {} probe;  /* BPF_LINK_TYPE_PERF_EVENT_PROBE */
> > >         struct {} tp; /* BPF_LINK_TYPE_PERF_EVENT_TP */
> > >         struct {} event; /* BPF_LINK_TYPE_PERF_EVENT_EVENT */
> > >     };
> > >
> >
> > Correct it:
> >
> > struct {
> >     __u32 type;
> >     union {
> >          struct {} probe;  /* BPF_LINK_TYPE_PERF_EVENT_PROBE */
> >          struct {} tp; /* BPF_LINK_TYPE_PERF_EVENT_TP */
> >          struct {} event; /* BPF_LINK_TYPE_PERF_EVENT_EVENT */
> >      };
> > } perf_event;
>
> yes, something like this. Unless we want to leave  perf_event {} to
> mean really perf event only, while kprobe/uprobe/tracepoint should be
> their own separate sections at the same level of nestedness as
> perf_Event and other cases. Not sure.
>

Thanks for your explanation. I will think about it.
diff mbox series

Patch

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index d99cc16..c3b821d 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -6443,6 +6443,28 @@  struct bpf_link_info {
 			__u32 count;
 			__u8  retprobe;
 		} kprobe_multi;
+		union {
+			struct {
+				/* The name is:
+				 * a) uprobe: file name
+				 * b) kprobe: kernel function
+				 */
+				__aligned_u64 name; /* in/out: name buffer ptr */
+				__u32 name_len;
+				__u32 offset;	/* offset from the name */
+				__u64 addr;
+				__u8 retprobe;
+			} probe; /* uprobe, kprobe */
+			struct {
+				/* in/out: tracepoint name buffer ptr */
+				__aligned_u64 tp_name;
+				__u32 name_len;
+			} tp; /* tracepoint */
+			struct {
+				__u64 config;
+				__u32 type;
+			} event; /* generic perf event */
+		} perf_event;
 	};
 } __attribute__((aligned(8)));
 
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 80c9ec0..e349bdb 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -3303,9 +3303,107 @@  static void bpf_perf_link_dealloc(struct bpf_link *link)
 	kfree(perf_link);
 }
 
+static int bpf_perf_link_fill_name(const struct perf_event *event,
+				   char __user *uname, u32 ulen,
+				   u64 *probe_offset, u64 *probe_addr,
+				   u32 *fd_type)
+{
+	const char *buf;
+	u32 prog_id;
+	size_t len;
+	int err;
+
+	if (!ulen ^ !uname)
+		return -EINVAL;
+	if (!uname)
+		return 0;
+
+	err = bpf_get_perf_event_info(event, &prog_id, fd_type, &buf,
+				      probe_offset, probe_addr);
+	if (err)
+		return err;
+
+	len = strlen(buf);
+	if (buf) {
+		err = bpf_copy_to_user(uname, buf, ulen, len);
+		if (err)
+			return err;
+	} else {
+		char zero = '\0';
+
+		if (put_user(zero, uname))
+			return -EFAULT;
+	}
+	return 0;
+}
+
+static int bpf_perf_link_fill_probe(const struct perf_event *event,
+				    struct bpf_link_info *info)
+{
+	char __user *uname = u64_to_user_ptr(info->perf_event.probe.name);
+	u32 ulen = info->perf_event.probe.name_len;
+	u64 addr, off;
+	u32 type;
+	int err;
+
+	err = bpf_perf_link_fill_name(event, uname, ulen, &off, &addr, &type);
+	if (err)
+		return err;
+	info->perf_event.probe.offset = off;
+	if (type == BPF_FD_TYPE_KRETPROBE || type == BPF_FD_TYPE_URETPROBE)
+		info->perf_event.probe.retprobe = 1;
+	else
+		info->perf_event.probe.retprobe = 0;
+
+	if (kptr_restrict == 2)
+		return 0;
+	info->perf_event.probe.addr = addr;
+	return 0;
+}
+
+static int bpf_perf_link_fill_tp(const struct perf_event *event,
+				 struct bpf_link_info *info)
+{
+	char __user *uname = u64_to_user_ptr(info->perf_event.tp.tp_name);
+	u32 ulen = info->perf_event.tp.name_len;
+	u64 addr, off;
+	u32 type;
+
+	return bpf_perf_link_fill_name(event, uname, ulen, &off, &addr, &type);
+}
+
+static int bpf_perf_link_fill_event(const struct perf_event *event,
+				    struct bpf_link_info *info)
+{
+	info->perf_event.event.type = event->attr.type;
+	info->perf_event.event.config = event->attr.config;
+	return 0;
+}
+
+static int bpf_perf_link_fill_link_info(const struct bpf_link *link,
+					struct bpf_link_info *info)
+{
+	struct bpf_perf_link *perf_link;
+	const struct perf_event *event;
+
+	perf_link = container_of(link, struct bpf_perf_link, link);
+	event = perf_get_event(perf_link->perf_file);
+	if (IS_ERR(event))
+		return PTR_ERR(event);
+
+	if (!event->prog)
+		return -EINVAL;
+	if (event->prog->type == BPF_PROG_TYPE_PERF_EVENT)
+		return bpf_perf_link_fill_event(event, info);
+	if (event->prog->type == BPF_PROG_TYPE_TRACEPOINT)
+		return bpf_perf_link_fill_tp(event, info);
+	return bpf_perf_link_fill_probe(event, info);
+}
+
 static const struct bpf_link_ops bpf_perf_link_lops = {
 	.release = bpf_perf_link_release,
 	.dealloc = bpf_perf_link_dealloc,
+	.fill_link_info = bpf_perf_link_fill_link_info,
 };
 
 static int bpf_perf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index d99cc16..c3b821d 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -6443,6 +6443,28 @@  struct bpf_link_info {
 			__u32 count;
 			__u8  retprobe;
 		} kprobe_multi;
+		union {
+			struct {
+				/* The name is:
+				 * a) uprobe: file name
+				 * b) kprobe: kernel function
+				 */
+				__aligned_u64 name; /* in/out: name buffer ptr */
+				__u32 name_len;
+				__u32 offset;	/* offset from the name */
+				__u64 addr;
+				__u8 retprobe;
+			} probe; /* uprobe, kprobe */
+			struct {
+				/* in/out: tracepoint name buffer ptr */
+				__aligned_u64 tp_name;
+				__u32 name_len;
+			} tp; /* tracepoint */
+			struct {
+				__u64 config;
+				__u32 type;
+			} event; /* generic perf event */
+		} perf_event;
 	};
 } __attribute__((aligned(8)));