diff mbox series

[v3,bpf-next,01/10] bpf: Support ->fill_link_info for kprobe_multi

Message ID 20230612151608.99661-2-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
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 15 of 15 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 success total: 0 errors, 0 warnings, 0 checks, 65 lines checked
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-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-24 success Logs for test_progs_parallel on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-25 success Logs for test_verifier on aarch64 with gcc
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-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 fail Logs for test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-13 fail Logs for test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-14 fail 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 fail Logs for test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-18 fail Logs for test_progs_no_alu32 on x86_64 with llvm-16
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-23 success Logs for test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-26 success Logs for test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-16 fail Logs for test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-12 fail Logs for test_progs on s390x with gcc
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ${{ matrix.test }} on ${{ matrix.arch }} with ${{ matrix.toolchain_full }}
bpf/vmtest-bpf-next-VM_Test-2 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-3 success Logs for build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-4 fail Logs for build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-5 success Logs for build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-6 success Logs for build for x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-7 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-8 success Logs for veristat

Commit Message

Yafang Shao June 12, 2023, 3:15 p.m. UTC
With the addition of support for fill_link_info to the kprobe_multi link,
users will gain the ability to inspect it conveniently using the
`bpftool link show`. This enhancement provides valuable information to the
user, including the count of probed functions and their respective
addresses. It's important to note that if the kptr_restrict setting is not
permitted, the probed address will not be exposed, ensuring security.

Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
---
 include/uapi/linux/bpf.h       |  5 +++++
 kernel/trace/bpf_trace.c       | 28 ++++++++++++++++++++++++++++
 tools/include/uapi/linux/bpf.h |  5 +++++
 3 files changed, 38 insertions(+)

Comments

Jiri Olsa June 15, 2023, 8:29 a.m. UTC | #1
On Mon, Jun 12, 2023 at 03:15:59PM +0000, Yafang Shao wrote:

SNIP

> diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> index 2bc41e6..742047c 100644
> --- a/kernel/trace/bpf_trace.c
> +++ b/kernel/trace/bpf_trace.c
> @@ -2548,9 +2548,36 @@ static void bpf_kprobe_multi_link_dealloc(struct bpf_link *link)
>  	kfree(kmulti_link);
>  }
>  
> +static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,
> +						struct bpf_link_info *info)
> +{
> +	u64 __user *uaddrs = u64_to_user_ptr(info->kprobe_multi.addrs);
> +	struct bpf_kprobe_multi_link *kmulti_link;
> +	u32 ucount = info->kprobe_multi.count;
> +
> +	if (!uaddrs ^ !ucount)
> +		return -EINVAL;
> +
> +	kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link);
> +	if (!uaddrs) {
> +		info->kprobe_multi.count = kmulti_link->cnt;
> +		return 0;
> +	}
> +
> +	if (ucount < kmulti_link->cnt)
> +		return -EINVAL;
> +	info->kprobe_multi.flags = kmulti_link->fp.flags;
> +	if (!kallsyms_show_value(current_cred()))
> +		return 0;
> +	if (copy_to_user(uaddrs, kmulti_link->addrs, ucount * sizeof(u64)))
> +		return -EFAULT;
> +	return 0;
> +}
> +
>  static const struct bpf_link_ops bpf_kprobe_multi_link_lops = {
>  	.release = bpf_kprobe_multi_link_release,
>  	.dealloc = bpf_kprobe_multi_link_dealloc,
> +	.fill_link_info = bpf_kprobe_multi_link_fill_link_info,
>  };
>  
>  static void bpf_kprobe_multi_cookie_swap(void *a, void *b, int size, const void *priv)
> @@ -2890,6 +2917,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
>  		return err;
>  	}
>  
> +	link->fp.flags = flags;

hum this looks wrong, we can't use fprobe flags to store our flags
you should add flags to bpf_kprobe_multi_link

jirka

>  	return bpf_link_settle(&link_primer);
>  
>  error:
> diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
> index a7b5e91..23691ea 100644
> --- a/tools/include/uapi/linux/bpf.h
> +++ b/tools/include/uapi/linux/bpf.h
> @@ -6438,6 +6438,11 @@ struct bpf_link_info {
>  			__s32 priority;
>  			__u32 flags;
>  		} netfilter;
> +		struct {
> +			__aligned_u64 addrs; /* in/out: addresses buffer ptr */
> +			__u32 count;
> +			__u32 flags;
> +		} kprobe_multi;
>  	};
>  } __attribute__((aligned(8)));
>  
> -- 
> 1.8.3.1
>
Yafang Shao June 15, 2023, 12:09 p.m. UTC | #2
On Thu, Jun 15, 2023 at 4:29 PM Jiri Olsa <olsajiri@gmail.com> wrote:
>
> On Mon, Jun 12, 2023 at 03:15:59PM +0000, Yafang Shao wrote:
>
> SNIP
>
> > diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> > index 2bc41e6..742047c 100644
> > --- a/kernel/trace/bpf_trace.c
> > +++ b/kernel/trace/bpf_trace.c
> > @@ -2548,9 +2548,36 @@ static void bpf_kprobe_multi_link_dealloc(struct bpf_link *link)
> >       kfree(kmulti_link);
> >  }
> >
> > +static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,
> > +                                             struct bpf_link_info *info)
> > +{
> > +     u64 __user *uaddrs = u64_to_user_ptr(info->kprobe_multi.addrs);
> > +     struct bpf_kprobe_multi_link *kmulti_link;
> > +     u32 ucount = info->kprobe_multi.count;
> > +
> > +     if (!uaddrs ^ !ucount)
> > +             return -EINVAL;
> > +
> > +     kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link);
> > +     if (!uaddrs) {
> > +             info->kprobe_multi.count = kmulti_link->cnt;
> > +             return 0;
> > +     }
> > +
> > +     if (ucount < kmulti_link->cnt)
> > +             return -EINVAL;
> > +     info->kprobe_multi.flags = kmulti_link->fp.flags;
> > +     if (!kallsyms_show_value(current_cred()))
> > +             return 0;
> > +     if (copy_to_user(uaddrs, kmulti_link->addrs, ucount * sizeof(u64)))
> > +             return -EFAULT;
> > +     return 0;
> > +}
> > +
> >  static const struct bpf_link_ops bpf_kprobe_multi_link_lops = {
> >       .release = bpf_kprobe_multi_link_release,
> >       .dealloc = bpf_kprobe_multi_link_dealloc,
> > +     .fill_link_info = bpf_kprobe_multi_link_fill_link_info,
> >  };
> >
> >  static void bpf_kprobe_multi_cookie_swap(void *a, void *b, int size, const void *priv)
> > @@ -2890,6 +2917,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
> >               return err;
> >       }
> >
> > +     link->fp.flags = flags;
>
> hum this looks wrong, we can't use fprobe flags to store our flags
> you should add flags to bpf_kprobe_multi_link

Will fix it. Thanks for pointing it out.
Andrii Nakryiko June 16, 2023, 5:24 p.m. UTC | #3
On Mon, Jun 12, 2023 at 8:16 AM Yafang Shao <laoar.shao@gmail.com> wrote:
>
> With the addition of support for fill_link_info to the kprobe_multi link,
> users will gain the ability to inspect it conveniently using the
> `bpftool link show`. This enhancement provides valuable information to the
> user, including the count of probed functions and their respective
> addresses. It's important to note that if the kptr_restrict setting is not
> permitted, the probed address will not be exposed, ensuring security.
>
> Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
> ---
>  include/uapi/linux/bpf.h       |  5 +++++
>  kernel/trace/bpf_trace.c       | 28 ++++++++++++++++++++++++++++
>  tools/include/uapi/linux/bpf.h |  5 +++++
>  3 files changed, 38 insertions(+)
>
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index a7b5e91..23691ea 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -6438,6 +6438,11 @@ struct bpf_link_info {
>                         __s32 priority;
>                         __u32 flags;
>                 } netfilter;
> +               struct {
> +                       __aligned_u64 addrs; /* in/out: addresses buffer ptr */
> +                       __u32 count;
> +                       __u32 flags;
> +               } kprobe_multi;
>         };
>  } __attribute__((aligned(8)));
>
> diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> index 2bc41e6..742047c 100644
> --- a/kernel/trace/bpf_trace.c
> +++ b/kernel/trace/bpf_trace.c
> @@ -2548,9 +2548,36 @@ static void bpf_kprobe_multi_link_dealloc(struct bpf_link *link)
>         kfree(kmulti_link);
>  }
>
> +static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,
> +                                               struct bpf_link_info *info)
> +{
> +       u64 __user *uaddrs = u64_to_user_ptr(info->kprobe_multi.addrs);
> +       struct bpf_kprobe_multi_link *kmulti_link;
> +       u32 ucount = info->kprobe_multi.count;
> +
> +       if (!uaddrs ^ !ucount)
> +               return -EINVAL;
> +
> +       kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link);
> +       if (!uaddrs) {
> +               info->kprobe_multi.count = kmulti_link->cnt;
> +               return 0;
> +       }
> +
> +       if (ucount < kmulti_link->cnt)
> +               return -EINVAL;
> +       info->kprobe_multi.flags = kmulti_link->fp.flags;

besides what Jiri said, flags should always be returned, just like
cnt. So structure code instead around uaddrs being optional, that will
everything more straightforward (i.e., fill out everything but uaddrs
and then at the end fill out addrs if uaddrs is not zero)

> +       if (!kallsyms_show_value(current_cred()))
> +               return 0;
> +       if (copy_to_user(uaddrs, kmulti_link->addrs, ucount * sizeof(u64)))
> +               return -EFAULT;
> +       return 0;
> +}
> +
>  static const struct bpf_link_ops bpf_kprobe_multi_link_lops = {
>         .release = bpf_kprobe_multi_link_release,
>         .dealloc = bpf_kprobe_multi_link_dealloc,
> +       .fill_link_info = bpf_kprobe_multi_link_fill_link_info,
>  };
>
>  static void bpf_kprobe_multi_cookie_swap(void *a, void *b, int size, const void *priv)
> @@ -2890,6 +2917,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
>                 return err;
>         }
>
> +       link->fp.flags = flags;
>         return bpf_link_settle(&link_primer);
>
>  error:
> diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
> index a7b5e91..23691ea 100644
> --- a/tools/include/uapi/linux/bpf.h
> +++ b/tools/include/uapi/linux/bpf.h
> @@ -6438,6 +6438,11 @@ struct bpf_link_info {
>                         __s32 priority;
>                         __u32 flags;
>                 } netfilter;
> +               struct {
> +                       __aligned_u64 addrs; /* in/out: addresses buffer ptr */
> +                       __u32 count;
> +                       __u32 flags;
> +               } kprobe_multi;
>         };
>  } __attribute__((aligned(8)));
>
> --
> 1.8.3.1
>
Yafang Shao June 17, 2023, 2:48 a.m. UTC | #4
On Sat, Jun 17, 2023 at 1:24 AM Andrii Nakryiko
<andrii.nakryiko@gmail.com> wrote:
>
> On Mon, Jun 12, 2023 at 8:16 AM Yafang Shao <laoar.shao@gmail.com> wrote:
> >
> > With the addition of support for fill_link_info to the kprobe_multi link,
> > users will gain the ability to inspect it conveniently using the
> > `bpftool link show`. This enhancement provides valuable information to the
> > user, including the count of probed functions and their respective
> > addresses. It's important to note that if the kptr_restrict setting is not
> > permitted, the probed address will not be exposed, ensuring security.
> >
> > Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
> > ---
> >  include/uapi/linux/bpf.h       |  5 +++++
> >  kernel/trace/bpf_trace.c       | 28 ++++++++++++++++++++++++++++
> >  tools/include/uapi/linux/bpf.h |  5 +++++
> >  3 files changed, 38 insertions(+)
> >
> > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > index a7b5e91..23691ea 100644
> > --- a/include/uapi/linux/bpf.h
> > +++ b/include/uapi/linux/bpf.h
> > @@ -6438,6 +6438,11 @@ struct bpf_link_info {
> >                         __s32 priority;
> >                         __u32 flags;
> >                 } netfilter;
> > +               struct {
> > +                       __aligned_u64 addrs; /* in/out: addresses buffer ptr */
> > +                       __u32 count;
> > +                       __u32 flags;
> > +               } kprobe_multi;
> >         };
> >  } __attribute__((aligned(8)));
> >
> > diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> > index 2bc41e6..742047c 100644
> > --- a/kernel/trace/bpf_trace.c
> > +++ b/kernel/trace/bpf_trace.c
> > @@ -2548,9 +2548,36 @@ static void bpf_kprobe_multi_link_dealloc(struct bpf_link *link)
> >         kfree(kmulti_link);
> >  }
> >
> > +static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,
> > +                                               struct bpf_link_info *info)
> > +{
> > +       u64 __user *uaddrs = u64_to_user_ptr(info->kprobe_multi.addrs);
> > +       struct bpf_kprobe_multi_link *kmulti_link;
> > +       u32 ucount = info->kprobe_multi.count;
> > +
> > +       if (!uaddrs ^ !ucount)
> > +               return -EINVAL;
> > +
> > +       kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link);
> > +       if (!uaddrs) {
> > +               info->kprobe_multi.count = kmulti_link->cnt;
> > +               return 0;
> > +       }
> > +
> > +       if (ucount < kmulti_link->cnt)
> > +               return -EINVAL;
> > +       info->kprobe_multi.flags = kmulti_link->fp.flags;
>
> besides what Jiri said, flags should always be returned, just like
> cnt. So structure code instead around uaddrs being optional, that will
> everything more straightforward (i.e., fill out everything but uaddrs
> and then at the end fill out addrs if uaddrs is not zero)

Agree. That will be more straightforward. Will change it.
diff mbox series

Patch

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index a7b5e91..23691ea 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -6438,6 +6438,11 @@  struct bpf_link_info {
 			__s32 priority;
 			__u32 flags;
 		} netfilter;
+		struct {
+			__aligned_u64 addrs; /* in/out: addresses buffer ptr */
+			__u32 count;
+			__u32 flags;
+		} kprobe_multi;
 	};
 } __attribute__((aligned(8)));
 
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 2bc41e6..742047c 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -2548,9 +2548,36 @@  static void bpf_kprobe_multi_link_dealloc(struct bpf_link *link)
 	kfree(kmulti_link);
 }
 
+static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,
+						struct bpf_link_info *info)
+{
+	u64 __user *uaddrs = u64_to_user_ptr(info->kprobe_multi.addrs);
+	struct bpf_kprobe_multi_link *kmulti_link;
+	u32 ucount = info->kprobe_multi.count;
+
+	if (!uaddrs ^ !ucount)
+		return -EINVAL;
+
+	kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link);
+	if (!uaddrs) {
+		info->kprobe_multi.count = kmulti_link->cnt;
+		return 0;
+	}
+
+	if (ucount < kmulti_link->cnt)
+		return -EINVAL;
+	info->kprobe_multi.flags = kmulti_link->fp.flags;
+	if (!kallsyms_show_value(current_cred()))
+		return 0;
+	if (copy_to_user(uaddrs, kmulti_link->addrs, ucount * sizeof(u64)))
+		return -EFAULT;
+	return 0;
+}
+
 static const struct bpf_link_ops bpf_kprobe_multi_link_lops = {
 	.release = bpf_kprobe_multi_link_release,
 	.dealloc = bpf_kprobe_multi_link_dealloc,
+	.fill_link_info = bpf_kprobe_multi_link_fill_link_info,
 };
 
 static void bpf_kprobe_multi_cookie_swap(void *a, void *b, int size, const void *priv)
@@ -2890,6 +2917,7 @@  int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
 		return err;
 	}
 
+	link->fp.flags = flags;
 	return bpf_link_settle(&link_primer);
 
 error:
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index a7b5e91..23691ea 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -6438,6 +6438,11 @@  struct bpf_link_info {
 			__s32 priority;
 			__u32 flags;
 		} netfilter;
+		struct {
+			__aligned_u64 addrs; /* in/out: addresses buffer ptr */
+			__u32 count;
+			__u32 flags;
+		} kprobe_multi;
 	};
 } __attribute__((aligned(8)));