diff mbox series

[bpf-next,1/6] bpf: Support ->fill_link_info for kprobe_multi

Message ID 20230602085239.91138-2-laoar.shao@gmail.com (mailing list archive)
State Changes Requested
Delegated to: BPF
Headers show
Series bpf: Support ->fill_link_info for kprobe prog | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR fail 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 fail 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 fail Logs for build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-6 fail 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
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 fail Errors and warnings before: 1732 this patch: 1734
netdev/cc_maintainers warning 3 maintainers not CCed: mhiramat@kernel.org linux-trace-kernel@vger.kernel.org rostedt@goodmis.org
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 fail Errors and warnings before: 1731 this patch: 1733
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 55 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Yafang Shao June 2, 2023, 8:52 a.m. UTC
By adding support for ->fill_link_info to the kprobe_multi link, users will
be able to inspect it using `bpftool link show`. This enhancement will
expose both the count of probed functions and their respective addresses to
the user.

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

Comments

Stanislav Fomichev June 2, 2023, 4:45 p.m. UTC | #1
On 06/02, Yafang Shao wrote:
> By adding support for ->fill_link_info to the kprobe_multi link, users will
> be able to inspect it using `bpftool link show`. This enhancement will
> expose both the count of probed functions and their respective addresses to
> the user.
> 
> Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
> ---
>  include/uapi/linux/bpf.h       |  4 ++++
>  kernel/trace/bpf_trace.c       | 26 ++++++++++++++++++++++++++
>  tools/include/uapi/linux/bpf.h |  4 ++++
>  3 files changed, 34 insertions(+)
> 
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index a7b5e91..22c8168 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -6438,6 +6438,10 @@ struct bpf_link_info {
>  			__s32 priority;
>  			__u32 flags;
>  		} netfilter;
> +		struct {
> +			__u64 addrs;
> +			__u32 count;
> +		} kprobe_multi;
>  	};
>  } __attribute__((aligned(8)));
>  
> diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> index 2bc41e6..ec53bc9 100644
> --- a/kernel/trace/bpf_trace.c
> +++ b/kernel/trace/bpf_trace.c
> @@ -2548,9 +2548,35 @@ 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 *uaddrs = (u64 *)u64_to_user_ptr(info->kprobe_multi.addrs);

Maybe tag this as __user as well?

	u64 __user *uaddrs = u64_to_user_ptr(info->kprobe_multi.addrs);

copy_to_user expects __user tagged memory, so most likely sparse tool
will complain on your current approach.

> +	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)
> +		return 0;
> +	if (ucount != kmulti_link->cnt)
> +		return -EINVAL;

[..]

> +	if (copy_to_user(uaddrs, kmulti_link->addrs, ucount * sizeof(u64)))
> +		return -EFAULT;

I'm not super familiar with this part, so maybe stupid question:
do we need to hold any locks during the copy? IOW, can kmulti_link->addrs
be updated concurrently?
kernel test robot June 3, 2023, 6:38 a.m. UTC | #2
Hi Yafang,

kernel test robot noticed the following build warnings:

[auto build test WARNING on bpf-next/master]

url:    https://github.com/intel-lab-lkp/linux/commits/Yafang-Shao/bpf-Support-fill_link_info-for-kprobe_multi/20230602-165455
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
patch link:    https://lore.kernel.org/r/20230602085239.91138-2-laoar.shao%40gmail.com
patch subject: [PATCH bpf-next 1/6] bpf: Support ->fill_link_info for kprobe_multi
config: i386-randconfig-s002-20230601 (https://download.01.org/0day-ci/archive/20230603/202306031438.0X2HPFQl-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.4-39-gce1a6720-dirty
        # https://github.com/intel-lab-lkp/linux/commit/270f3eb6c142f1f0ec7d800b8ecaab1b101682a0
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Yafang-Shao/bpf-Support-fill_link_info-for-kprobe_multi/20230602-165455
        git checkout 270f3eb6c142f1f0ec7d800b8ecaab1b101682a0
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 olddefconfig
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 SHELL=/bin/bash kernel/trace/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202306031438.0X2HPFQl-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> kernel/trace/bpf_trace.c:2554:24: sparse: sparse: cast removes address space '__user' of expression
>> kernel/trace/bpf_trace.c:2571:26: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *to @@     got unsigned long long [usertype] *uaddrs @@
   kernel/trace/bpf_trace.c:2571:26: sparse:     expected void [noderef] __user *to
   kernel/trace/bpf_trace.c:2571:26: sparse:     got unsigned long long [usertype] *uaddrs
   kernel/trace/bpf_trace.c:2492:21: sparse: sparse: dereference of noderef expression
   kernel/trace/bpf_trace.c:2496:66: sparse: sparse: dereference of noderef expression

vim +/__user +2554 kernel/trace/bpf_trace.c

  2550	
  2551	static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,
  2552							struct bpf_link_info *info)
  2553	{
> 2554		u64 *uaddrs = (u64 *)u64_to_user_ptr(info->kprobe_multi.addrs);
  2555		struct bpf_kprobe_multi_link *kmulti_link;
  2556		u32 ucount = info->kprobe_multi.count;
  2557	
  2558		if (!uaddrs ^ !ucount)
  2559			return -EINVAL;
  2560	
  2561		kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link);
  2562		if (!uaddrs) {
  2563			info->kprobe_multi.count = kmulti_link->cnt;
  2564			return 0;
  2565		}
  2566	
  2567		if (!ucount)
  2568			return 0;
  2569		if (ucount != kmulti_link->cnt)
  2570			return -EINVAL;
> 2571		if (copy_to_user(uaddrs, kmulti_link->addrs, ucount * sizeof(u64)))
  2572			return -EFAULT;
  2573		return 0;
  2574	}
  2575
Yafang Shao June 4, 2023, 3:21 a.m. UTC | #3
On Sat, Jun 3, 2023 at 12:46 AM Stanislav Fomichev <sdf@google.com> wrote:
>
> On 06/02, Yafang Shao wrote:
> > By adding support for ->fill_link_info to the kprobe_multi link, users will
> > be able to inspect it using `bpftool link show`. This enhancement will
> > expose both the count of probed functions and their respective addresses to
> > the user.
> >
> > Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
> > ---
> >  include/uapi/linux/bpf.h       |  4 ++++
> >  kernel/trace/bpf_trace.c       | 26 ++++++++++++++++++++++++++
> >  tools/include/uapi/linux/bpf.h |  4 ++++
> >  3 files changed, 34 insertions(+)
> >
> > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > index a7b5e91..22c8168 100644
> > --- a/include/uapi/linux/bpf.h
> > +++ b/include/uapi/linux/bpf.h
> > @@ -6438,6 +6438,10 @@ struct bpf_link_info {
> >                       __s32 priority;
> >                       __u32 flags;
> >               } netfilter;
> > +             struct {
> > +                     __u64 addrs;
> > +                     __u32 count;
> > +             } kprobe_multi;
> >       };
> >  } __attribute__((aligned(8)));
> >
> > diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> > index 2bc41e6..ec53bc9 100644
> > --- a/kernel/trace/bpf_trace.c
> > +++ b/kernel/trace/bpf_trace.c
> > @@ -2548,9 +2548,35 @@ 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 *uaddrs = (u64 *)u64_to_user_ptr(info->kprobe_multi.addrs);
>
> Maybe tag this as __user as well?
>
>         u64 __user *uaddrs = u64_to_user_ptr(info->kprobe_multi.addrs);
>
> copy_to_user expects __user tagged memory, so most likely sparse tool
> will complain on your current approach.

Thanks for pointing it out. Will correct it.

>
> > +     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)
> > +             return 0;
> > +     if (ucount != kmulti_link->cnt)
> > +             return -EINVAL;
>
> [..]
>
> > +     if (copy_to_user(uaddrs, kmulti_link->addrs, ucount * sizeof(u64)))
> > +             return -EFAULT;
>
> I'm not super familiar with this part, so maybe stupid question:
> do we need to hold any locks during the copy? IOW, can kmulti_link->addrs
> be updated concurrently?

No, we can't update kmulti_link->addrs concurrently.  Once a fprobe is
registered, we can't update it unless we unregister it. When we reach
the ->fill_link_info, it can't be released, so it is safe.


--
Regards
Yafang
Yafang Shao June 4, 2023, 3:22 a.m. UTC | #4
On Sat, Jun 3, 2023 at 2:38 PM kernel test robot <lkp@intel.com> wrote:
>
> Hi Yafang,
>
> kernel test robot noticed the following build warnings:
>
> [auto build test WARNING on bpf-next/master]
>
> url:    https://github.com/intel-lab-lkp/linux/commits/Yafang-Shao/bpf-Support-fill_link_info-for-kprobe_multi/20230602-165455
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
> patch link:    https://lore.kernel.org/r/20230602085239.91138-2-laoar.shao%40gmail.com
> patch subject: [PATCH bpf-next 1/6] bpf: Support ->fill_link_info for kprobe_multi
> config: i386-randconfig-s002-20230601 (https://download.01.org/0day-ci/archive/20230603/202306031438.0X2HPFQl-lkp@intel.com/config)
> compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
> reproduce:
>         # apt-get install sparse
>         # sparse version: v0.6.4-39-gce1a6720-dirty
>         # https://github.com/intel-lab-lkp/linux/commit/270f3eb6c142f1f0ec7d800b8ecaab1b101682a0
>         git remote add linux-review https://github.com/intel-lab-lkp/linux
>         git fetch --no-tags linux-review Yafang-Shao/bpf-Support-fill_link_info-for-kprobe_multi/20230602-165455
>         git checkout 270f3eb6c142f1f0ec7d800b8ecaab1b101682a0
>         # save the config file
>         mkdir build_dir && cp config build_dir/.config
>         make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 olddefconfig
>         make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 SHELL=/bin/bash kernel/trace/
>
> If you fix the issue, kindly add following tag where applicable
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202306031438.0X2HPFQl-lkp@intel.com/
>
> sparse warnings: (new ones prefixed by >>)
> >> kernel/trace/bpf_trace.c:2554:24: sparse: sparse: cast removes address space '__user' of expression
> >> kernel/trace/bpf_trace.c:2571:26: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __user *to @@     got unsigned long long [usertype] *uaddrs @@
>    kernel/trace/bpf_trace.c:2571:26: sparse:     expected void [noderef] __user *to
>    kernel/trace/bpf_trace.c:2571:26: sparse:     got unsigned long long [usertype] *uaddrs
>    kernel/trace/bpf_trace.c:2492:21: sparse: sparse: dereference of noderef expression
>    kernel/trace/bpf_trace.c:2496:66: sparse: sparse: dereference of noderef expression
>
> vim +/__user +2554 kernel/trace/bpf_trace.c
>
>   2550
>   2551  static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,
>   2552                                                  struct bpf_link_info *info)
>   2553  {
> > 2554          u64 *uaddrs = (u64 *)u64_to_user_ptr(info->kprobe_multi.addrs);

Thanks for the report. Will fix it.

>   2555          struct bpf_kprobe_multi_link *kmulti_link;
>   2556          u32 ucount = info->kprobe_multi.count;
>   2557
>   2558          if (!uaddrs ^ !ucount)
>   2559                  return -EINVAL;
>   2560
>   2561          kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link);
>   2562          if (!uaddrs) {
>   2563                  info->kprobe_multi.count = kmulti_link->cnt;
>   2564                  return 0;
>   2565          }
>   2566
>   2567          if (!ucount)
>   2568                  return 0;
>   2569          if (ucount != kmulti_link->cnt)
>   2570                  return -EINVAL;
> > 2571          if (copy_to_user(uaddrs, kmulti_link->addrs, ucount * sizeof(u64)))
>   2572                  return -EFAULT;
>   2573          return 0;
>   2574  }
>   2575
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki
diff mbox series

Patch

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index a7b5e91..22c8168 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -6438,6 +6438,10 @@  struct bpf_link_info {
 			__s32 priority;
 			__u32 flags;
 		} netfilter;
+		struct {
+			__u64 addrs;
+			__u32 count;
+		} kprobe_multi;
 	};
 } __attribute__((aligned(8)));
 
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 2bc41e6..ec53bc9 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -2548,9 +2548,35 @@  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 *uaddrs = (u64 *)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)
+		return 0;
+	if (ucount != kmulti_link->cnt)
+		return -EINVAL;
+	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)
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index a7b5e91..22c8168 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -6438,6 +6438,10 @@  struct bpf_link_info {
 			__s32 priority;
 			__u32 flags;
 		} netfilter;
+		struct {
+			__u64 addrs;
+			__u32 count;
+		} kprobe_multi;
 	};
 } __attribute__((aligned(8)));