From: Dave Marchevsky <davemarchevsky@fb.com>
To: <bpf@vger.kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Martin KaFai Lau <martin.lau@kernel.org>,
Kernel Team <kernel-team@fb.com>, <yonghong.song@linux.dev>,
<sdf@google.com>, Dave Marchevsky <davemarchevsky@fb.com>
Subject: [PATCH v3 bpf-next 3/3] selftests/bpf: Add tests for open-coded task_vma iter
Date: Mon, 21 Aug 2023 22:05:58 -0700 [thread overview]
Message-ID: <20230822050558.2937659-4-davemarchevsky@fb.com> (raw)
In-Reply-To: <20230822050558.2937659-1-davemarchevsky@fb.com>
The open-coded task_vma iter added earlier in this series allows for
natural iteration over a task's vmas using existing open-coded iter
infrastructure, specifically bpf_for_each.
This patch adds a test demonstrating this pattern and validating
correctness. The vma->vm_start and vma->vm_end addresses of the first
1000 vmas are recorded and compared to /proc/PID/maps output. As
expected, both see the same vmas and addresses - with the exception of
the [vsyscall] vma - which is explained in a comment in the prog_tests
program.
Signed-off-by: Dave Marchevsky <davemarchevsky@fb.com>
---
.../testing/selftests/bpf/prog_tests/iters.c | 71 +++++++++++++++++++
.../selftests/bpf/progs/iters_task_vma.c | 56 +++++++++++++++
2 files changed, 127 insertions(+)
create mode 100644 tools/testing/selftests/bpf/progs/iters_task_vma.c
diff --git a/tools/testing/selftests/bpf/prog_tests/iters.c b/tools/testing/selftests/bpf/prog_tests/iters.c
index 10804ae5ae97..f91f4a49066a 100644
--- a/tools/testing/selftests/bpf/prog_tests/iters.c
+++ b/tools/testing/selftests/bpf/prog_tests/iters.c
@@ -8,6 +8,7 @@
#include "iters_looping.skel.h"
#include "iters_num.skel.h"
#include "iters_testmod_seq.skel.h"
+#include "iters_task_vma.skel.h"
static void subtest_num_iters(void)
{
@@ -90,6 +91,74 @@ static void subtest_testmod_seq_iters(void)
iters_testmod_seq__destroy(skel);
}
+static void subtest_task_vma_iters(void)
+{
+ unsigned long start, end, bpf_iter_start, bpf_iter_end;
+ struct iters_task_vma *skel;
+ char rest_of_line[1000];
+ unsigned int seen;
+ int err;
+ FILE *f;
+
+ skel = iters_task_vma__open();
+ if (!ASSERT_OK_PTR(skel, "skel_open"))
+ return;
+
+ bpf_program__set_autoload(skel->progs.iter_task_vma_for_each, true);
+
+ err = iters_task_vma__load(skel);
+ if (!ASSERT_OK(err, "skel_load"))
+ goto cleanup;
+
+ skel->bss->target_pid = getpid();
+
+ err = iters_task_vma__attach(skel);
+ if (!ASSERT_OK(err, "skel_attach"))
+ goto cleanup;
+
+ iters_task_vma__detach(skel);
+ getpgid(skel->bss->target_pid);
+
+ if (!ASSERT_GT(skel->bss->vmas_seen, 0, "vmas_seen_gt_zero"))
+ goto cleanup;
+
+ f = fopen("/proc/self/maps", "r");
+ if (!ASSERT_OK_PTR(f, "proc_maps_fopen"))
+ goto cleanup;
+
+ seen = 0;
+ while (fscanf(f, "%lx-%lx %[^\n]\n", &start, &end, rest_of_line) == 3) {
+ /* [vsyscall] vma isn't _really_ part of task->mm vmas.
+ * /proc/PID/maps returns it when out of vmas - see get_gate_vma
+ * calls in fs/proc/task_mmu.c
+ */
+ if (strstr(rest_of_line, "[vsyscall]"))
+ continue;
+
+ err = bpf_map_lookup_elem(bpf_map__fd(skel->maps.vm_start),
+ &seen, &bpf_iter_start);
+ if (!ASSERT_OK(err, "vm_start map_lookup_elem"))
+ goto cleanup;
+
+ err = bpf_map_lookup_elem(bpf_map__fd(skel->maps.vm_end),
+ &seen, &bpf_iter_end);
+ if (!ASSERT_OK(err, "vm_end map_lookup_elem"))
+ goto cleanup;
+
+ ASSERT_EQ(bpf_iter_start, start, "vma->vm_start match");
+ ASSERT_EQ(bpf_iter_end, end, "vma->vm_end match");
+ seen++;
+ }
+
+ fclose(f);
+
+ if (!ASSERT_EQ(skel->bss->vmas_seen, seen, "vmas_seen_eq"))
+ goto cleanup;
+
+cleanup:
+ iters_task_vma__destroy(skel);
+}
+
void test_iters(void)
{
RUN_TESTS(iters_state_safety);
@@ -103,4 +172,6 @@ void test_iters(void)
subtest_num_iters();
if (test__start_subtest("testmod_seq"))
subtest_testmod_seq_iters();
+ if (test__start_subtest("task_vma"))
+ subtest_task_vma_iters();
}
diff --git a/tools/testing/selftests/bpf/progs/iters_task_vma.c b/tools/testing/selftests/bpf/progs/iters_task_vma.c
new file mode 100644
index 000000000000..b961d0a12223
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/iters_task_vma.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
+
+#include <limits.h>
+#include <linux/errno.h>
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
+
+pid_t target_pid = 0;
+unsigned int vmas_seen = 0;
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __uint(max_entries, 1000);
+ __type(key, int);
+ __type(value, unsigned long);
+} vm_start SEC(".maps");
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __uint(max_entries, 1000);
+ __type(key, int);
+ __type(value, unsigned long);
+} vm_end SEC(".maps");
+
+SEC("?raw_tp/sys_enter")
+int iter_task_vma_for_each(const void *ctx)
+{
+ struct task_struct *task = bpf_get_current_task_btf();
+ struct vm_area_struct *vma;
+ unsigned long *start, *end;
+
+ if (task->pid != target_pid)
+ return 0;
+
+ bpf_for_each(task_vma, vma, task, 0) {
+ if (vmas_seen >= 1000)
+ break;
+
+ start = bpf_map_lookup_elem(&vm_start, &vmas_seen);
+ if (!start)
+ break;
+ *start = vma->vm_start;
+
+ end = bpf_map_lookup_elem(&vm_end, &vmas_seen);
+ if (!end)
+ break;
+ *end = vma->vm_end;
+
+ vmas_seen++;
+ }
+ return 0;
+}
+
+char _license[] SEC("license") = "GPL";
--
2.34.1
next prev parent reply other threads:[~2023-08-22 5:06 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-22 5:05 [PATCH v3 bpf-next 0/3] Open-coded task_vma iter Dave Marchevsky
2023-08-22 5:05 ` [PATCH v3 bpf-next 1/3] bpf: Don't explicitly emit BTF for struct btf_iter_num Dave Marchevsky
2023-08-22 23:37 ` Andrii Nakryiko
2023-08-22 5:05 ` [PATCH v3 bpf-next 2/3] bpf: Introduce task_vma open-coded iterator kfuncs Dave Marchevsky
2023-08-22 17:42 ` Yonghong Song
2023-08-22 19:19 ` David Marchevsky
2023-08-22 20:14 ` Yonghong Song
2023-08-22 22:36 ` Alexei Starovoitov
2023-08-22 23:57 ` Andrii Nakryiko
2023-08-23 0:11 ` Yonghong Song
2023-08-23 0:04 ` Andrii Nakryiko
2023-08-23 5:42 ` David Marchevsky
2023-08-23 14:57 ` Alexei Starovoitov
2023-08-23 16:55 ` Andrii Nakryiko
2023-08-22 23:52 ` Andrii Nakryiko
2023-08-23 7:26 ` David Marchevsky
2023-08-23 15:03 ` Alexei Starovoitov
2023-08-23 17:14 ` Andrii Nakryiko
2023-08-23 17:53 ` Alexei Starovoitov
2023-08-23 18:13 ` Andrii Nakryiko
2023-08-23 17:07 ` Andrii Nakryiko
2023-08-23 17:26 ` Alexei Starovoitov
2023-08-23 17:43 ` Andrii Nakryiko
2023-08-22 5:05 ` Dave Marchevsky [this message]
2023-08-23 0:13 ` [PATCH v3 bpf-next 3/3] selftests/bpf: Add tests for open-coded task_vma iter Andrii Nakryiko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230822050558.2937659-4-davemarchevsky@fb.com \
--to=davemarchevsky@fb.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=kernel-team@fb.com \
--cc=martin.lau@kernel.org \
--cc=sdf@google.com \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.