diff mbox series

[RFC,bpf-next] bpf: Add two new bpf helpers bpf_perf_type_[uk]probe()

Message ID 20230621120042.3903-3-laoar.shao@gmail.com (mailing list archive)
State RFC
Delegated to: BPF
Headers show
Series [RFC,bpf-next] bpf: Add two new bpf helpers bpf_perf_type_[uk]probe() | 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 Single patches do not need cover letters
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: 1733 this patch: 1659
netdev/cc_maintainers warning 5 maintainers not CCed: linux-trace-kernel@vger.kernel.org mhiramat@kernel.org martin.lau@linux.dev song@kernel.org rostedt@goodmis.org
netdev/build_clang fail Errors and warnings before: 182 this patch: 176
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: 1732 this patch: 1658
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 121 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 21, 2023, noon UTC
We are utilizing BPF LSM to monitor BPF operations within our container
environment. Our goal is to examine the program type and perform the 
respective audits in our LSM program.

When it comes to the perf_event BPF program, there are no specific
definitions for the perf types of kprobe or uprobe. In other words, there
is no PERF_TYPE_[UK]PROBE. It appears that defining them as UAPI at this
stage would be impractical.

Therefore, if we wish to determine whether a new BPF program created via 
perf_event_open() is a kprobe or an uprobe, we need to retrieve the type in
userspace by reading /sys/bus/event_source/devices/[uk]probe/type and 
subsequently store it in global variables within the LSM program. This
approach proves to be inconvenient.

Two new BPF helpers have been introduced to enhance the functionality.
These helpers allow us to directly obtain the perf type of a kprobe or
uprobe within a BPF program.

Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
---
 include/linux/bpf.h            |  2 ++
 include/uapi/linux/bpf.h       | 18 ++++++++++++++++++
 kernel/bpf/core.c              |  2 ++
 kernel/bpf/helpers.c           | 23 +++++++++++++++++++++++
 kernel/trace/bpf_trace.c       |  4 ++++
 tools/include/uapi/linux/bpf.h | 18 ++++++++++++++++++
 6 files changed, 67 insertions(+)

Comments

Alexei Starovoitov June 22, 2023, 11:37 p.m. UTC | #1
On Wed, Jun 21, 2023 at 5:01 AM Yafang Shao <laoar.shao@gmail.com> wrote:
>
> We are utilizing BPF LSM to monitor BPF operations within our container
> environment. Our goal is to examine the program type and perform the
> respective audits in our LSM program.
>
> When it comes to the perf_event BPF program, there are no specific
> definitions for the perf types of kprobe or uprobe. In other words, there
> is no PERF_TYPE_[UK]PROBE. It appears that defining them as UAPI at this
> stage would be impractical.

and yet that's what your patch does.
New helpers are uapi too.
So no-go.

Just do in your filtering bpf prog:
        is_kprobe = event->tp_event->flags & TRACE_EVENT_FL_KPROBE;
        is_uprobe = event->tp_event->flags & TRACE_EVENT_FL_UPROBE;
when it's checking perf_ioctl.
Yafang Shao June 23, 2023, 10:17 a.m. UTC | #2
On Fri, Jun 23, 2023 at 7:37 AM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Wed, Jun 21, 2023 at 5:01 AM Yafang Shao <laoar.shao@gmail.com> wrote:
> >
> > We are utilizing BPF LSM to monitor BPF operations within our container
> > environment. Our goal is to examine the program type and perform the
> > respective audits in our LSM program.
> >
> > When it comes to the perf_event BPF program, there are no specific
> > definitions for the perf types of kprobe or uprobe. In other words, there
> > is no PERF_TYPE_[UK]PROBE. It appears that defining them as UAPI at this
> > stage would be impractical.
>
> and yet that's what your patch does.
> New helpers are uapi too.
> So no-go.
>
> Just do in your filtering bpf prog:
>         is_kprobe = event->tp_event->flags & TRACE_EVENT_FL_KPROBE;
>         is_uprobe = event->tp_event->flags & TRACE_EVENT_FL_UPROBE;
> when it's checking perf_ioctl.

Right. We can hook security_perf_event_write.
Thanks for your suggestion.
diff mbox series

Patch

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index f588958..27135d1 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -2909,6 +2909,8 @@  static inline int bpf_fd_reuseport_array_update_elem(struct bpf_map *map,
 extern const struct bpf_func_proto bpf_user_ringbuf_drain_proto;
 extern const struct bpf_func_proto bpf_cgrp_storage_get_proto;
 extern const struct bpf_func_proto bpf_cgrp_storage_delete_proto;
+extern const struct bpf_func_proto bpf_perf_type_kprobe_proto;
+extern const struct bpf_func_proto bpf_perf_type_uprobe_proto;
 
 const struct bpf_func_proto *tracing_prog_func_proto(
   enum bpf_func_id func_id, const struct bpf_prog *prog);
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index a7b5e91..1ddb1dc 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -5572,6 +5572,22 @@  struct bpf_stack_build_id {
  *		0 on success.
  *
  *		**-ENOENT** if the bpf_local_storage cannot be found.
+ *
+ * int bpf_perf_type_kprobe(void)
+ *	Description
+ *		Get perf_kprobe.type
+ *	Return
+ *		perf_kprobe.type on success.
+ *
+ *		**-EOPNOTSUPP** if CONFIG_KPROBE_EVENTS is not set.
+ *
+ * int bpf_perf_type_uprobe(void)
+ *	Description
+ *		Get perf_uprobe.type
+ *	Return
+ *		perf_uprobe.type on success.
+ *
+ *		**-EOPNOTSUPP** if CONFIG_UPROBE_EVENTS is not set.
  */
 #define ___BPF_FUNC_MAPPER(FN, ctx...)			\
 	FN(unspec, 0, ##ctx)				\
@@ -5786,6 +5802,8 @@  struct bpf_stack_build_id {
 	FN(user_ringbuf_drain, 209, ##ctx)		\
 	FN(cgrp_storage_get, 210, ##ctx)		\
 	FN(cgrp_storage_delete, 211, ##ctx)		\
+	FN(perf_type_kprobe, 212, ##ctx)		\
+	FN(perf_type_uprobe, 213, ##ctx)		\
 	/* */
 
 /* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 599136c..ab5fc7e 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2666,6 +2666,8 @@  void bpf_user_rnd_init_once(void)
 const struct bpf_func_proto bpf_seq_printf_btf_proto __weak;
 const struct bpf_func_proto bpf_set_retval_proto __weak;
 const struct bpf_func_proto bpf_get_retval_proto __weak;
+const struct bpf_func_proto bpf_perf_type_kprobe__weak;
+const struct bpf_func_proto bpf_perf_type_uprobe__weak;
 
 const struct bpf_func_proto * __weak bpf_get_trace_printk_proto(void)
 {
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 9e80efa..f139fe3 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -22,6 +22,7 @@ 
 #include <linux/security.h>
 #include <linux/btf_ids.h>
 #include <linux/bpf_mem_alloc.h>
+#include <linux/perf_event.h>
 
 #include "../../lib/kstrtox.h"
 
@@ -1654,6 +1655,28 @@  static int bpf_dynptr_check_off_len(const struct bpf_dynptr_kern *ptr, u32 offse
 	.arg3_type	= ARG_CONST_ALLOC_SIZE_OR_ZERO,
 };
 
+BPF_CALL_0(bpf_perf_type_kprobe)
+{
+	return perf_type_kprobe();
+}
+
+const struct bpf_func_proto bpf_perf_type_kprobe_proto = {
+	.func		= bpf_perf_type_kprobe,
+	.gpl_only	= false,
+	.ret_type	= RET_INTEGER,
+};
+
+BPF_CALL_0(bpf_perf_type_uprobe)
+{
+	return perf_type_uprobe();
+}
+
+const struct bpf_func_proto bpf_perf_type_uprobe_proto = {
+	.func		= bpf_perf_type_uprobe,
+	.gpl_only	= false,
+	.ret_type	= RET_INTEGER,
+};
+
 const struct bpf_func_proto bpf_get_current_task_proto __weak;
 const struct bpf_func_proto bpf_get_current_task_btf_proto __weak;
 const struct bpf_func_proto bpf_probe_read_user_proto __weak;
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 2bc41e6..59c66ad 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1510,6 +1510,10 @@  static int __init bpf_key_sig_kfuncs_init(void)
 		return &bpf_find_vma_proto;
 	case BPF_FUNC_trace_vprintk:
 		return bpf_get_trace_vprintk_proto();
+	case BPF_FUNC_perf_type_kprobe:
+		return &bpf_perf_type_kprobe_proto;
+	case BPF_FUNC_perf_type_uprobe:
+		return &bpf_perf_type_uprobe_proto;
 	default:
 		return bpf_base_func_proto(func_id);
 	}
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index a7b5e91..1ddb1dc 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -5572,6 +5572,22 @@  struct bpf_stack_build_id {
  *		0 on success.
  *
  *		**-ENOENT** if the bpf_local_storage cannot be found.
+ *
+ * int bpf_perf_type_kprobe(void)
+ *	Description
+ *		Get perf_kprobe.type
+ *	Return
+ *		perf_kprobe.type on success.
+ *
+ *		**-EOPNOTSUPP** if CONFIG_KPROBE_EVENTS is not set.
+ *
+ * int bpf_perf_type_uprobe(void)
+ *	Description
+ *		Get perf_uprobe.type
+ *	Return
+ *		perf_uprobe.type on success.
+ *
+ *		**-EOPNOTSUPP** if CONFIG_UPROBE_EVENTS is not set.
  */
 #define ___BPF_FUNC_MAPPER(FN, ctx...)			\
 	FN(unspec, 0, ##ctx)				\
@@ -5786,6 +5802,8 @@  struct bpf_stack_build_id {
 	FN(user_ringbuf_drain, 209, ##ctx)		\
 	FN(cgrp_storage_get, 210, ##ctx)		\
 	FN(cgrp_storage_delete, 211, ##ctx)		\
+	FN(perf_type_kprobe, 212, ##ctx)		\
+	FN(perf_type_uprobe, 213, ##ctx)		\
 	/* */
 
 /* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't