All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf-next v2 0/2] libbpf: Add syscall-specific variant of BPF_KPROBE
@ 2022-02-06 13:40 Hengqi Chen
  2022-02-06 13:40 ` [PATCH bpf-next v2 1/2] libbpf: Add BPF_KPROBE_SYSCALL macro Hengqi Chen
  2022-02-06 13:40 ` [PATCH bpf-next v2 2/2] selftests/bpf: Test " Hengqi Chen
  0 siblings, 2 replies; 5+ messages in thread
From: Hengqi Chen @ 2022-02-06 13:40 UTC (permalink / raw)
  To: bpf; +Cc: andrii, hengqi.chen

Add new macro BPF_KPROBE_SYSCALL, which provides easy access to syscall
input arguments. See [0] and [1] for background.

  [0]: https://github.com/libbpf/libbpf-bootstrap/issues/57
  [1]: https://github.com/libbpf/libbpf/issues/425

Hengqi Chen (2):
  libbpf: Add BPF_KPROBE_SYSCALL macro
  selftests/bpf: Test BPF_KPROBE_SYSCALL macro

 tools/lib/bpf/bpf_tracing.h                   | 39 +++++++++++++++++++
 .../selftests/bpf/prog_tests/kprobe_syscall.c | 37 ++++++++++++++++++
 .../selftests/bpf/progs/test_kprobe_syscall.c | 34 ++++++++++++++++
 3 files changed, 110 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/kprobe_syscall.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_kprobe_syscall.c

--
2.30.2

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH bpf-next v2 1/2] libbpf: Add BPF_KPROBE_SYSCALL macro
  2022-02-06 13:40 [PATCH bpf-next v2 0/2] libbpf: Add syscall-specific variant of BPF_KPROBE Hengqi Chen
@ 2022-02-06 13:40 ` Hengqi Chen
  2022-02-06 19:37   ` Andrii Nakryiko
  2022-02-06 13:40 ` [PATCH bpf-next v2 2/2] selftests/bpf: Test " Hengqi Chen
  1 sibling, 1 reply; 5+ messages in thread
From: Hengqi Chen @ 2022-02-06 13:40 UTC (permalink / raw)
  To: bpf; +Cc: andrii, hengqi.chen

Add syscall-specific variant of BPF_KPROBE named BPF_KPROBE_SYSCALL ([0]).
The new macro hides the underlying way of getting syscall input arguments.
With these new macros, the following code:

    SEC("kprobe/__x64_sys_close")
    int BPF_KPROBE(do_sys_close, struct pt_regs *regs)
    {
        int fd;

        fd = PT_REGS_PARM1_CORE(regs);
        /* do something with fd */
    }

can be written as:

    SEC("kprobe/__x64_sys_close")
    int BPF_KPROBE_SYSCALL(do_sys_close, int fd)
    {
        /* do something with fd */
    }

  [0] Closes: https://github.com/libbpf/libbpf/issues/425

Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
---
 tools/lib/bpf/bpf_tracing.h | 39 +++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/tools/lib/bpf/bpf_tracing.h b/tools/lib/bpf/bpf_tracing.h
index cf980e54d331..a0b230320335 100644
--- a/tools/lib/bpf/bpf_tracing.h
+++ b/tools/lib/bpf/bpf_tracing.h
@@ -461,4 +461,43 @@ typeof(name(0)) name(struct pt_regs *ctx)				    \
 }									    \
 static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args)

+#define ___bpf_syscall_args0() ctx
+#define ___bpf_syscall_args1(x) \
+	___bpf_syscall_args0(), (void *)PT_REGS_PARM1_CORE_SYSCALL(regs)
+#define ___bpf_syscall_args2(x, args...) \
+	___bpf_syscall_args1(args), (void *)PT_REGS_PARM2_CORE_SYSCALL(regs)
+#define ___bpf_syscall_args3(x, args...) \
+	___bpf_syscall_args2(args), (void *)PT_REGS_PARM3_CORE_SYSCALL(regs)
+#define ___bpf_syscall_args4(x, args...) \
+	___bpf_syscall_args3(args), (void *)PT_REGS_PARM4_CORE_SYSCALL(regs)
+#define ___bpf_syscall_args5(x, args...) \
+	___bpf_syscall_args4(args), (void *)PT_REGS_PARM5_CORE_SYSCALL(regs)
+#define ___bpf_syscall_args(args...) \
+	___bpf_apply(___bpf_syscall_args, ___bpf_narg(args))(args)
+
+/*
+ * BPF_KPROBE_SYSCALL is a variant of BPF_KPROBE, which is intended for
+ * tracing syscall functions, like __x64_sys_close. It hides the underlying
+ * platform-specific low-level way of getting syscall input arguments from
+ * struct pt_regs, and provides a familiar typed and named function arguments
+ * syntax and semantics of accessing syscall input parameters.
+ *
+ * Original struct pt_regs* context is preserved as 'ctx' argument. This might
+ * be necessary when using BPF helpers like bpf_perf_event_output().
+ */
+#define BPF_KPROBE_SYSCALL(name, args...)				    \
+name(struct pt_regs *ctx);						    \
+static __attribute__((always_inline)) typeof(name(0))			    \
+____##name(struct pt_regs *ctx, ##args);				    \
+typeof(name(0)) name(struct pt_regs *ctx)				    \
+{									    \
+	struct pt_regs *regs = (void *)PT_REGS_PARM1(ctx);		    \
+	_Pragma("GCC diagnostic push")					    \
+	_Pragma("GCC diagnostic ignored \"-Wint-conversion\"")		    \
+	return ____##name(___bpf_syscall_args(args));			    \
+	_Pragma("GCC diagnostic pop")					    \
+}									    \
+static __attribute__((always_inline)) typeof(name(0))			    \
+____##name(struct pt_regs *ctx, ##args)
+
 #endif
--
2.30.2

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH bpf-next v2 2/2] selftests/bpf: Test BPF_KPROBE_SYSCALL macro
  2022-02-06 13:40 [PATCH bpf-next v2 0/2] libbpf: Add syscall-specific variant of BPF_KPROBE Hengqi Chen
  2022-02-06 13:40 ` [PATCH bpf-next v2 1/2] libbpf: Add BPF_KPROBE_SYSCALL macro Hengqi Chen
@ 2022-02-06 13:40 ` Hengqi Chen
  2022-02-06 19:41   ` Andrii Nakryiko
  1 sibling, 1 reply; 5+ messages in thread
From: Hengqi Chen @ 2022-02-06 13:40 UTC (permalink / raw)
  To: bpf; +Cc: andrii, hengqi.chen

Add tests for the newly added BPF_KPROBE_SYSCALL macro.

Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
---
 .../selftests/bpf/prog_tests/kprobe_syscall.c | 37 +++++++++++++++++++
 .../selftests/bpf/progs/test_kprobe_syscall.c | 34 +++++++++++++++++
 2 files changed, 71 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/kprobe_syscall.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_kprobe_syscall.c

diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_syscall.c b/tools/testing/selftests/bpf/prog_tests/kprobe_syscall.c
new file mode 100644
index 000000000000..0ac89c987024
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/kprobe_syscall.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2022 Hengqi Chen */
+
+#include <test_progs.h>
+#include <sys/prctl.h>
+#include "test_kprobe_syscall.skel.h"
+
+void test_kprobe_syscall(void)
+{
+	struct test_kprobe_syscall *skel;
+	int err;
+
+	skel = test_kprobe_syscall__open();
+	if (!ASSERT_OK_PTR(skel, "test_kprobe_syscall__open"))
+		return;
+
+	skel->rodata->my_pid = getpid();
+
+	err = test_kprobe_syscall__load(skel);
+	if (!ASSERT_OK(err, "test_kprobe_syscall__load"))
+		goto cleanup;
+
+	err = test_kprobe_syscall__attach(skel);
+	if (!ASSERT_OK(err, "test_kprobe_syscall__attach"))
+		goto cleanup;
+
+	prctl(1, 2, 3, 4, 5);
+
+	ASSERT_EQ(skel->bss->option, 1, "BPF_KPROBE_SYSCALL failed");
+	ASSERT_EQ(skel->bss->arg2, 2, "BPF_KPROBE_SYSCALL failed");
+	ASSERT_EQ(skel->bss->arg3, 3, "BPF_KPROBE_SYSCALL failed");
+	ASSERT_EQ(skel->bss->arg4, 4, "BPF_KPROBE_SYSCALL failed");
+	ASSERT_EQ(skel->bss->arg5, 5, "BPF_KPROBE_SYSCALL failed");
+
+cleanup:
+	test_kprobe_syscall__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/test_kprobe_syscall.c b/tools/testing/selftests/bpf/progs/test_kprobe_syscall.c
new file mode 100644
index 000000000000..abd59c3d5b59
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_kprobe_syscall.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2022 Hengqi Chen */
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+#include "bpf_misc.h"
+
+const volatile pid_t my_pid = 0;
+int option = 0;
+unsigned long arg2 = 0;
+unsigned long arg3 = 0;
+unsigned long arg4 = 0;
+unsigned long arg5 = 0;
+
+SEC("kprobe/" SYS_PREFIX "sys_prctl")
+int BPF_KPROBE_SYSCALL(prctl_enter, int opt, unsigned long a2,
+		       unsigned long a3, unsigned long a4, unsigned long a5)
+{
+	pid_t pid = bpf_get_current_pid_tgid() >> 32;
+
+	if (pid != my_pid)
+		return 0;
+
+	option = opt;
+	arg2 = a2;
+	arg3 = a3;
+	arg4 = a4;
+	arg5 = a5;
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
--
2.30.2

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH bpf-next v2 1/2] libbpf: Add BPF_KPROBE_SYSCALL macro
  2022-02-06 13:40 ` [PATCH bpf-next v2 1/2] libbpf: Add BPF_KPROBE_SYSCALL macro Hengqi Chen
@ 2022-02-06 19:37   ` Andrii Nakryiko
  0 siblings, 0 replies; 5+ messages in thread
From: Andrii Nakryiko @ 2022-02-06 19:37 UTC (permalink / raw)
  To: Hengqi Chen; +Cc: bpf, Andrii Nakryiko

On Sun, Feb 6, 2022 at 5:41 AM Hengqi Chen <hengqi.chen@gmail.com> wrote:
>
> Add syscall-specific variant of BPF_KPROBE named BPF_KPROBE_SYSCALL ([0]).
> The new macro hides the underlying way of getting syscall input arguments.
> With these new macros, the following code:
>
>     SEC("kprobe/__x64_sys_close")
>     int BPF_KPROBE(do_sys_close, struct pt_regs *regs)
>     {
>         int fd;
>
>         fd = PT_REGS_PARM1_CORE(regs);
>         /* do something with fd */
>     }
>
> can be written as:
>
>     SEC("kprobe/__x64_sys_close")
>     int BPF_KPROBE_SYSCALL(do_sys_close, int fd)
>     {
>         /* do something with fd */
>     }
>
>   [0] Closes: https://github.com/libbpf/libbpf/issues/425
>
> Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
> ---
>  tools/lib/bpf/bpf_tracing.h | 39 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 39 insertions(+)
>
> diff --git a/tools/lib/bpf/bpf_tracing.h b/tools/lib/bpf/bpf_tracing.h
> index cf980e54d331..a0b230320335 100644
> --- a/tools/lib/bpf/bpf_tracing.h
> +++ b/tools/lib/bpf/bpf_tracing.h
> @@ -461,4 +461,43 @@ typeof(name(0)) name(struct pt_regs *ctx)                              \
>  }                                                                          \
>  static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args)
>
> +#define ___bpf_syscall_args0() ctx
> +#define ___bpf_syscall_args1(x) \
> +       ___bpf_syscall_args0(), (void *)PT_REGS_PARM1_CORE_SYSCALL(regs)
> +#define ___bpf_syscall_args2(x, args...) \
> +       ___bpf_syscall_args1(args), (void *)PT_REGS_PARM2_CORE_SYSCALL(regs)
> +#define ___bpf_syscall_args3(x, args...) \
> +       ___bpf_syscall_args2(args), (void *)PT_REGS_PARM3_CORE_SYSCALL(regs)
> +#define ___bpf_syscall_args4(x, args...) \
> +       ___bpf_syscall_args3(args), (void *)PT_REGS_PARM4_CORE_SYSCALL(regs)
> +#define ___bpf_syscall_args5(x, args...) \
> +       ___bpf_syscall_args4(args), (void *)PT_REGS_PARM5_CORE_SYSCALL(regs)
> +#define ___bpf_syscall_args(args...) \
> +       ___bpf_apply(___bpf_syscall_args, ___bpf_narg(args))(args)
> +

please keep each #define on a single line, it's much easier to follow
(and validate) the pattern that way

> +/*
> + * BPF_KPROBE_SYSCALL is a variant of BPF_KPROBE, which is intended for
> + * tracing syscall functions, like __x64_sys_close. It hides the underlying
> + * platform-specific low-level way of getting syscall input arguments from
> + * struct pt_regs, and provides a familiar typed and named function arguments
> + * syntax and semantics of accessing syscall input parameters.
> + *
> + * Original struct pt_regs* context is preserved as 'ctx' argument. This might
> + * be necessary when using BPF helpers like bpf_perf_event_output().
> + */
> +#define BPF_KPROBE_SYSCALL(name, args...)                                  \
> +name(struct pt_regs *ctx);                                                 \
> +static __attribute__((always_inline)) typeof(name(0))                      \
> +____##name(struct pt_regs *ctx, ##args);                                   \
> +typeof(name(0)) name(struct pt_regs *ctx)                                  \
> +{                                                                          \
> +       struct pt_regs *regs = (void *)PT_REGS_PARM1(ctx);                  \

See recent Ilya's patch set ([0]), not all architectures need this
unwrapping. We've abstracted this into PT_REGS_SYSCALL() macro, please
use it here.

  [0] https://patchwork.kernel.org/project/netdevbpf/list/?series=611184&state=*

> +       _Pragma("GCC diagnostic push")                                      \
> +       _Pragma("GCC diagnostic ignored \"-Wint-conversion\"")              \
> +       return ____##name(___bpf_syscall_args(args));                       \
> +       _Pragma("GCC diagnostic pop")                                       \
> +}                                                                          \
> +static __attribute__((always_inline)) typeof(name(0))                      \
> +____##name(struct pt_regs *ctx, ##args)
> +
>  #endif
> --
> 2.30.2

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH bpf-next v2 2/2] selftests/bpf: Test BPF_KPROBE_SYSCALL macro
  2022-02-06 13:40 ` [PATCH bpf-next v2 2/2] selftests/bpf: Test " Hengqi Chen
@ 2022-02-06 19:41   ` Andrii Nakryiko
  0 siblings, 0 replies; 5+ messages in thread
From: Andrii Nakryiko @ 2022-02-06 19:41 UTC (permalink / raw)
  To: Hengqi Chen; +Cc: bpf, Andrii Nakryiko

On Sun, Feb 6, 2022 at 5:41 AM Hengqi Chen <hengqi.chen@gmail.com> wrote:
>
> Add tests for the newly added BPF_KPROBE_SYSCALL macro.
>
> Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
> ---
>  .../selftests/bpf/prog_tests/kprobe_syscall.c | 37 +++++++++++++++++++
>  .../selftests/bpf/progs/test_kprobe_syscall.c | 34 +++++++++++++++++
>  2 files changed, 71 insertions(+)
>  create mode 100644 tools/testing/selftests/bpf/prog_tests/kprobe_syscall.c
>  create mode 100644 tools/testing/selftests/bpf/progs/test_kprobe_syscall.c
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_syscall.c b/tools/testing/selftests/bpf/prog_tests/kprobe_syscall.c
> new file mode 100644
> index 000000000000..0ac89c987024
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/prog_tests/kprobe_syscall.c
> @@ -0,0 +1,37 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2022 Hengqi Chen */
> +
> +#include <test_progs.h>
> +#include <sys/prctl.h>
> +#include "test_kprobe_syscall.skel.h"
> +
> +void test_kprobe_syscall(void)
> +{
> +       struct test_kprobe_syscall *skel;
> +       int err;
> +
> +       skel = test_kprobe_syscall__open();
> +       if (!ASSERT_OK_PTR(skel, "test_kprobe_syscall__open"))
> +               return;
> +
> +       skel->rodata->my_pid = getpid();
> +
> +       err = test_kprobe_syscall__load(skel);
> +       if (!ASSERT_OK(err, "test_kprobe_syscall__load"))
> +               goto cleanup;
> +
> +       err = test_kprobe_syscall__attach(skel);
> +       if (!ASSERT_OK(err, "test_kprobe_syscall__attach"))
> +               goto cleanup;
> +
> +       prctl(1, 2, 3, 4, 5);
> +
> +       ASSERT_EQ(skel->bss->option, 1, "BPF_KPROBE_SYSCALL failed");
> +       ASSERT_EQ(skel->bss->arg2, 2, "BPF_KPROBE_SYSCALL failed");
> +       ASSERT_EQ(skel->bss->arg3, 3, "BPF_KPROBE_SYSCALL failed");
> +       ASSERT_EQ(skel->bss->arg4, 4, "BPF_KPROBE_SYSCALL failed");
> +       ASSERT_EQ(skel->bss->arg5, 5, "BPF_KPROBE_SYSCALL failed");
> +
> +cleanup:
> +       test_kprobe_syscall__destroy(skel);
> +}
> diff --git a/tools/testing/selftests/bpf/progs/test_kprobe_syscall.c b/tools/testing/selftests/bpf/progs/test_kprobe_syscall.c
> new file mode 100644
> index 000000000000..abd59c3d5b59
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/progs/test_kprobe_syscall.c
> @@ -0,0 +1,34 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2022 Hengqi Chen */
> +
> +#include "vmlinux.h"
> +#include <bpf/bpf_helpers.h>
> +#include <bpf/bpf_tracing.h>
> +#include <bpf/bpf_core_read.h>
> +#include "bpf_misc.h"
> +
> +const volatile pid_t my_pid = 0;
> +int option = 0;
> +unsigned long arg2 = 0;
> +unsigned long arg3 = 0;
> +unsigned long arg4 = 0;
> +unsigned long arg5 = 0;
> +
> +SEC("kprobe/" SYS_PREFIX "sys_prctl")
> +int BPF_KPROBE_SYSCALL(prctl_enter, int opt, unsigned long a2,
> +                      unsigned long a3, unsigned long a4, unsigned long a5)
> +{
> +       pid_t pid = bpf_get_current_pid_tgid() >> 32;
> +
> +       if (pid != my_pid)
> +               return 0;
> +
> +       option = opt;
> +       arg2 = a2;
> +       arg3 = a3;
> +       arg4 = a4;
> +       arg5 = a5;
> +       return 0;
> +}
> +

Let's add all this into progs/bpf_syscall_macro.c and
prog_tests/test_bpf_syscall_macro.c, instead of adding a new selftest.
They are closely related anyways.

> +char _license[] SEC("license") = "GPL";
> --
> 2.30.2

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-02-06 19:41 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-06 13:40 [PATCH bpf-next v2 0/2] libbpf: Add syscall-specific variant of BPF_KPROBE Hengqi Chen
2022-02-06 13:40 ` [PATCH bpf-next v2 1/2] libbpf: Add BPF_KPROBE_SYSCALL macro Hengqi Chen
2022-02-06 19:37   ` Andrii Nakryiko
2022-02-06 13:40 ` [PATCH bpf-next v2 2/2] selftests/bpf: Test " Hengqi Chen
2022-02-06 19:41   ` Andrii Nakryiko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.