All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf-next 0/3] bpf: Add bpf_vma_build_id_parse helper
@ 2022-11-08 22:20 Jiri Olsa
  2022-11-08 22:20 ` [PATCH bpf-next 1/3] bpf: Split btf_id/size union in struct bpf_func_proto Jiri Olsa
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Jiri Olsa @ 2022-11-08 22:20 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: bpf, Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
	KP Singh, Stanislav Fomichev, Hao Luo

hi,
adding bpf_vma_build_id_parse helper that parses build ID of ELF file
mapped vma struct passed as an argument.

I originally wanted to add this as kfunc, but we need to be sure the
receiving buffer is big enough and we can't check for that on kfunc
side.

The use case for this helper is to provide the build id for executed
binaries on kernel side, when the monitoring user side does not have
access to the actual binaries.

thanks,
jirka


---
Jiri Olsa (3):
      bpf: Split btf_id/size union in struct bpf_func_proto
      bpf: Add bpf_vma_build_id_parse helper
      selftests/bpf: Add build_id_parse kfunc test

 include/linux/bpf.h                                         |  2 ++
 include/uapi/linux/bpf.h                                    |  9 +++++++++
 kernel/trace/bpf_trace.c                                    | 22 ++++++++++++++++++++++
 scripts/bpf_doc.py                                          |  2 ++
 tools/include/uapi/linux/bpf.h                              |  9 +++++++++
 tools/testing/selftests/bpf/prog_tests/vma_build_id_parse.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/testing/selftests/bpf/progs/vma_build_id_parse.c      | 34 ++++++++++++++++++++++++++++++++++
 7 files changed, 162 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/vma_build_id_parse.c
 create mode 100644 tools/testing/selftests/bpf/progs/vma_build_id_parse.c

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

* [PATCH bpf-next 1/3] bpf: Split btf_id/size union in struct bpf_func_proto
  2022-11-08 22:20 [PATCH bpf-next 0/3] bpf: Add bpf_vma_build_id_parse helper Jiri Olsa
@ 2022-11-08 22:20 ` Jiri Olsa
  2022-11-08 22:20 ` [PATCH bpf-next 2/3] bpf: Add bpf_vma_build_id_parse helper Jiri Olsa
  2022-11-08 22:20 ` [PATCH bpf-next 3/3] selftests/bpf: Add build_id_parse kfunc test Jiri Olsa
  2 siblings, 0 replies; 6+ messages in thread
From: Jiri Olsa @ 2022-11-08 22:20 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: bpf, Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
	KP Singh, Stanislav Fomichev, Hao Luo

When having helper that defines both arg*_btf_id and arg*_size fields,
one of those fields will end up with zero value.

With helper definition like:

  .arg1_type      = ARG_PTR_TO_BTF_ID,
  .arg1_btf_id    = &btf_tracing_ids[BTF_TRACING_TYPE_VMA],
  .arg2_type      = ARG_PTR_TO_FIXED_SIZE_MEM,
  .arg2_size      = BUILD_ID_SIZE_MAX,

The arg2_size field initializer zeros out the rest of the arg*_size
fields of its parent annon struct, so it effectively zeros also
arg1_btf_id field.

Moving arg*_btf_id and arg*_size fields into separate unions.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 include/linux/bpf.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 798aec816970..21a1d42b5d4c 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -640,6 +640,8 @@ struct bpf_func_proto {
 			u32 *arg5_btf_id;
 		};
 		u32 *arg_btf_id[5];
+	};
+	union {
 		struct {
 			size_t arg1_size;
 			size_t arg2_size;
-- 
2.38.1


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

* [PATCH bpf-next 2/3] bpf: Add bpf_vma_build_id_parse helper
  2022-11-08 22:20 [PATCH bpf-next 0/3] bpf: Add bpf_vma_build_id_parse helper Jiri Olsa
  2022-11-08 22:20 ` [PATCH bpf-next 1/3] bpf: Split btf_id/size union in struct bpf_func_proto Jiri Olsa
@ 2022-11-08 22:20 ` Jiri Olsa
  2022-11-09  0:42   ` Alexei Starovoitov
  2022-11-08 22:20 ` [PATCH bpf-next 3/3] selftests/bpf: Add build_id_parse kfunc test Jiri Olsa
  2 siblings, 1 reply; 6+ messages in thread
From: Jiri Olsa @ 2022-11-08 22:20 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: bpf, Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
	KP Singh, Stanislav Fomichev, Hao Luo

Adding bpf_vma_build_id_parse helper that parses build ID of ELF file
mapped vma struct passed as an argument.

I originally wanted to add this as kfunc, but we need to be sure the
receiving buffer is big enough and we can't check for that on kfunc
side.

The use case for this helper is to provide the build id for executed
binaries on kernel side, when the monitoring user side does not have
access to the actual binaries.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 include/uapi/linux/bpf.h       |  9 +++++++++
 kernel/trace/bpf_trace.c       | 22 ++++++++++++++++++++++
 scripts/bpf_doc.py             |  2 ++
 tools/include/uapi/linux/bpf.h |  9 +++++++++
 4 files changed, 42 insertions(+)

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 94659f6b3395..00559c40617e 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -5481,6 +5481,14 @@ union bpf_attr {
  *		0 on success.
  *
  *		**-ENOENT** if the bpf_local_storage cannot be found.
+ *
+ * long bpf_vma_build_id_parse(struct vm_area_struct *vma, char *build_id)
+ *	Description
+ *		Parse build ID of ELF file mapped to @vma.
+ *
+ *	Return
+ *		Size of parsed build id on success.
+ *		Negative errno in case of failure.
  */
 #define ___BPF_FUNC_MAPPER(FN, ctx...)			\
 	FN(unspec, 0, ##ctx)				\
@@ -5695,6 +5703,7 @@ union bpf_attr {
 	FN(user_ringbuf_drain, 209, ##ctx)		\
 	FN(cgrp_storage_get, 210, ##ctx)		\
 	FN(cgrp_storage_delete, 211, ##ctx)		\
+	FN(vma_build_id_parse, 212, ##ctx)		\
 	/* */
 
 /* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index f2d8d070d024..b52d0f1b3c7a 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -23,6 +23,7 @@
 #include <linux/sort.h>
 #include <linux/key.h>
 #include <linux/verification.h>
+#include <linux/buildid.h>
 
 #include <net/bpf_sk_storage.h>
 
@@ -1205,6 +1206,25 @@ static const struct bpf_func_proto bpf_get_func_arg_cnt_proto = {
 	.arg1_type	= ARG_PTR_TO_CTX,
 };
 
+BPF_CALL_2(vma_build_id_parse, struct vm_area_struct *, vma, char *, build_id)
+{
+	__u32 size;
+	int err;
+
+	err = build_id_parse(vma, build_id, &size);
+	return err < 0 ? (long) err : (long) size;
+}
+
+static const struct bpf_func_proto bpf_vma_build_id_parse_proto = {
+	.func		= vma_build_id_parse,
+	.gpl_only	= false,
+	.ret_type	= RET_INTEGER,
+	.arg1_type	= ARG_PTR_TO_BTF_ID,
+	.arg1_btf_id	= &btf_tracing_ids[BTF_TRACING_TYPE_VMA],
+	.arg2_type	= ARG_PTR_TO_FIXED_SIZE_MEM,
+	.arg2_size	= BUILD_ID_SIZE_MAX,
+};
+
 #ifdef CONFIG_KEYS
 __diag_push();
 __diag_ignore_all("-Wmissing-prototypes",
@@ -1953,6 +1973,8 @@ tracing_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 		return bpf_prog_has_trampoline(prog) ? &bpf_get_func_arg_cnt_proto : NULL;
 	case BPF_FUNC_get_attach_cookie:
 		return bpf_prog_has_trampoline(prog) ? &bpf_get_attach_cookie_proto_tracing : NULL;
+	case BPF_FUNC_vma_build_id_parse:
+		return &bpf_vma_build_id_parse_proto;
 	default:
 		fn = raw_tp_prog_func_proto(func_id, prog);
 		if (!fn && prog->expected_attach_type == BPF_TRACE_ITER)
diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py
index fdb0aff8cb5a..a55c3d0327db 100755
--- a/scripts/bpf_doc.py
+++ b/scripts/bpf_doc.py
@@ -700,6 +700,7 @@ class PrinterHelpers(Printer):
             'struct bpf_dynptr',
             'struct iphdr',
             'struct ipv6hdr',
+            'struct vm_area_struct',
     ]
     known_types = {
             '...',
@@ -754,6 +755,7 @@ class PrinterHelpers(Printer):
             'struct bpf_dynptr',
             'struct iphdr',
             'struct ipv6hdr',
+            'struct vm_area_struct',
     }
     mapped_types = {
             'u8': '__u8',
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 94659f6b3395..00559c40617e 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -5481,6 +5481,14 @@ union bpf_attr {
  *		0 on success.
  *
  *		**-ENOENT** if the bpf_local_storage cannot be found.
+ *
+ * long bpf_vma_build_id_parse(struct vm_area_struct *vma, char *build_id)
+ *	Description
+ *		Parse build ID of ELF file mapped to @vma.
+ *
+ *	Return
+ *		Size of parsed build id on success.
+ *		Negative errno in case of failure.
  */
 #define ___BPF_FUNC_MAPPER(FN, ctx...)			\
 	FN(unspec, 0, ##ctx)				\
@@ -5695,6 +5703,7 @@ union bpf_attr {
 	FN(user_ringbuf_drain, 209, ##ctx)		\
 	FN(cgrp_storage_get, 210, ##ctx)		\
 	FN(cgrp_storage_delete, 211, ##ctx)		\
+	FN(vma_build_id_parse, 212, ##ctx)		\
 	/* */
 
 /* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't
-- 
2.38.1


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

* [PATCH bpf-next 3/3] selftests/bpf: Add build_id_parse kfunc test
  2022-11-08 22:20 [PATCH bpf-next 0/3] bpf: Add bpf_vma_build_id_parse helper Jiri Olsa
  2022-11-08 22:20 ` [PATCH bpf-next 1/3] bpf: Split btf_id/size union in struct bpf_func_proto Jiri Olsa
  2022-11-08 22:20 ` [PATCH bpf-next 2/3] bpf: Add bpf_vma_build_id_parse helper Jiri Olsa
@ 2022-11-08 22:20 ` Jiri Olsa
  2 siblings, 0 replies; 6+ messages in thread
From: Jiri Olsa @ 2022-11-08 22:20 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
  Cc: bpf, Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
	KP Singh, Stanislav Fomichev, Hao Luo

Adding test for build_id_parse kfunc.

On bpf side it finds the vma of the test_progs text through
the test function pointer and reads its build id. On user
side we use readelf to get test_progs build id and compare
it with the one from bpf side.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 .../bpf/prog_tests/vma_build_id_parse.c       | 84 +++++++++++++++++++
 .../selftests/bpf/progs/vma_build_id_parse.c  | 34 ++++++++
 2 files changed, 118 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/vma_build_id_parse.c
 create mode 100644 tools/testing/selftests/bpf/progs/vma_build_id_parse.c

diff --git a/tools/testing/selftests/bpf/prog_tests/vma_build_id_parse.c b/tools/testing/selftests/bpf/prog_tests/vma_build_id_parse.c
new file mode 100644
index 000000000000..21c6f7771251
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/vma_build_id_parse.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <test_progs.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "vma_build_id_parse.skel.h"
+
+static int read_buildid(char **build_id)
+{
+	char tmp[] = "/tmp/dataXXXXXX";
+	char buf[200];
+	int err, fd;
+	FILE *f;
+
+	fd = mkstemp(tmp);
+	if (fd == -1)
+		return -1;
+	close(fd);
+
+	snprintf(buf, sizeof(buf),
+		"readelf -n ./test_progs 2>/dev/null | grep 'Build ID' | awk '{print $3}' > %s",
+		tmp);
+	err = system(buf);
+	if (!ASSERT_OK(err, "system"))
+		goto out;
+
+	f = fopen(tmp, "r");
+	if (!ASSERT_OK_PTR(f, "fopen")) {
+		err = -1;
+		goto out;
+	}
+	if (fscanf(f, "%ms$*\n", build_id) != 1) {
+		*build_id = NULL;
+		err = -1;
+	}
+	fclose(f);
+out:
+	unlink(tmp);
+	return err;
+}
+
+void test_vma_build_id_parse(void)
+{
+	char bpf_build_id[BPF_BUILD_ID_SIZE*2 + 1] = {}, *build_id;
+	LIBBPF_OPTS(bpf_test_run_opts, topts);
+	struct vma_build_id_parse *skel;
+	int i, err, prog_fd, size;
+
+	skel = vma_build_id_parse__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "vma_build_id_parse__open_and_load"))
+		return;
+
+	skel->bss->target_pid = getpid();
+	skel->bss->addr = (__u64)(uintptr_t)test_vma_build_id_parse;
+
+	err = vma_build_id_parse__attach(skel);
+	if (!ASSERT_OK(err, "vma_build_id_parse__attach"))
+		goto out;
+
+	prog_fd = bpf_program__fd(skel->progs.test1);
+	err = bpf_prog_test_run_opts(prog_fd, &topts);
+	ASSERT_OK(err, "test_run");
+	ASSERT_EQ(topts.retval, 0, "test_run");
+
+	ASSERT_EQ(skel->data->find_addr_ret, 0, "find_addr_ret");
+	ASSERT_GT(skel->data->vma_build_id_parse_ret, 0, "vma_build_id_parse_ret");
+
+	if (!ASSERT_OK(read_buildid(&build_id), "read_buildid"))
+		goto out;
+
+	size = skel->data->vma_build_id_parse_ret;
+	ASSERT_EQ(size, strlen(build_id)/2, "build_id_size");
+
+	/* Convert bpf build id to string, so we can compare it. */
+	for (i = 0; i < size; i++) {
+		sprintf(bpf_build_id + i*2, "%02x",
+			(unsigned char) skel->bss->build_id[i]);
+	}
+	ASSERT_STREQ(bpf_build_id, build_id, "build_ids_match");
+
+	free(build_id);
+out:
+	vma_build_id_parse__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/vma_build_id_parse.c b/tools/testing/selftests/bpf/progs/vma_build_id_parse.c
new file mode 100644
index 000000000000..bc5bc9e1808c
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/vma_build_id_parse.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+char _license[] SEC("license") = "GPL";
+
+#define BPF_BUILD_ID_SIZE 20
+
+__u64 addr = 0;
+pid_t target_pid = 0;
+int find_addr_ret = -1;
+int vma_build_id_parse_ret = -1;
+
+unsigned char build_id[BPF_BUILD_ID_SIZE];
+
+static long check_vma(struct task_struct *task, struct vm_area_struct *vma,
+		      void *data)
+{
+	vma_build_id_parse_ret = bpf_vma_build_id_parse(vma, (char *) build_id);
+	return 0;
+}
+
+SEC("fentry/bpf_fentry_test1")
+int BPF_PROG(test1, int a)
+{
+	struct task_struct *task = bpf_get_current_task_btf();
+
+	if (task->pid != target_pid)
+		return 0;
+
+	find_addr_ret = bpf_find_vma(task, addr, check_vma, NULL, 0);
+	return 0;
+}
-- 
2.38.1


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

* Re: [PATCH bpf-next 2/3] bpf: Add bpf_vma_build_id_parse helper
  2022-11-08 22:20 ` [PATCH bpf-next 2/3] bpf: Add bpf_vma_build_id_parse helper Jiri Olsa
@ 2022-11-09  0:42   ` Alexei Starovoitov
  2022-11-09 13:35     ` Jiri Olsa
  0 siblings, 1 reply; 6+ messages in thread
From: Alexei Starovoitov @ 2022-11-09  0:42 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, bpf,
	Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
	KP Singh, Stanislav Fomichev, Hao Luo

On Tue, Nov 8, 2022 at 2:20 PM Jiri Olsa <jolsa@kernel.org> wrote:
>
> Adding bpf_vma_build_id_parse helper that parses build ID of ELF file
> mapped vma struct passed as an argument.
>
> I originally wanted to add this as kfunc, but we need to be sure the
> receiving buffer is big enough and we can't check for that on kfunc
> side.

Let's figure out how to do that with kfunc.

Sorry, but I'm going to insist on everything being kfuncs
from now on.
200+ stable helpers. That's large enough uapi exposure already.

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

* Re: [PATCH bpf-next 2/3] bpf: Add bpf_vma_build_id_parse helper
  2022-11-09  0:42   ` Alexei Starovoitov
@ 2022-11-09 13:35     ` Jiri Olsa
  0 siblings, 0 replies; 6+ messages in thread
From: Jiri Olsa @ 2022-11-09 13:35 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, bpf,
	Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
	KP Singh, Stanislav Fomichev, Hao Luo

On Tue, Nov 08, 2022 at 04:42:20PM -0800, Alexei Starovoitov wrote:
> On Tue, Nov 8, 2022 at 2:20 PM Jiri Olsa <jolsa@kernel.org> wrote:
> >
> > Adding bpf_vma_build_id_parse helper that parses build ID of ELF file
> > mapped vma struct passed as an argument.
> >
> > I originally wanted to add this as kfunc, but we need to be sure the
> > receiving buffer is big enough and we can't check for that on kfunc
> > side.
> 
> Let's figure out how to do that with kfunc.
> 
> Sorry, but I'm going to insist on everything being kfuncs
> from now on.
> 200+ stable helpers. That's large enough uapi exposure already.

ok, I wasn't sure how the kfunc argument check would work.. I'll take
a look and send some rfc or questions ;-)

jirka

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

end of thread, other threads:[~2022-11-09 13:36 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-08 22:20 [PATCH bpf-next 0/3] bpf: Add bpf_vma_build_id_parse helper Jiri Olsa
2022-11-08 22:20 ` [PATCH bpf-next 1/3] bpf: Split btf_id/size union in struct bpf_func_proto Jiri Olsa
2022-11-08 22:20 ` [PATCH bpf-next 2/3] bpf: Add bpf_vma_build_id_parse helper Jiri Olsa
2022-11-09  0:42   ` Alexei Starovoitov
2022-11-09 13:35     ` Jiri Olsa
2022-11-08 22:20 ` [PATCH bpf-next 3/3] selftests/bpf: Add build_id_parse kfunc test Jiri Olsa

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.