* [PATCH bpf-next 0/4] introduce bpf_iter for task_vma
@ 2020-12-12 2:48 Song Liu
2020-12-12 2:48 ` [PATCH bpf-next 1/4] bpf: introduce task_vma bpf_iter Song Liu
` (3 more replies)
0 siblings, 4 replies; 10+ messages in thread
From: Song Liu @ 2020-12-12 2:48 UTC (permalink / raw)
To: bpf, netdev
Cc: ast, daniel, andrii, john.fastabend, kpsingh, kernel-team, Song Liu
This set introduces bpf_iter for task_vma, which can be used to generate
information similar to /proc/pid/maps or /proc/pid/smaps. Patch 4/4 adds
an example that mimics /proc/pid/maps.
Song Liu (4):
bpf: introduce task_vma bpf_iter
bpf: allow bpf_d_path in sleepable bpf_iter program
libbpf: introduce section "iter.s/" for sleepable bpf_iter program
selftests/bpf: add test for bpf_iter_task_vma
include/linux/bpf.h | 2 +-
include/uapi/linux/bpf.h | 7 +
kernel/bpf/task_iter.c | 193 +++++++++++++++++-
kernel/trace/bpf_trace.c | 5 +
tools/lib/bpf/libbpf.c | 5 +
.../selftests/bpf/prog_tests/bpf_iter.c | 106 +++++++++-
tools/testing/selftests/bpf/progs/bpf_iter.h | 9 +
.../selftests/bpf/progs/bpf_iter_task_vma.c | 55 +++++
8 files changed, 370 insertions(+), 12 deletions(-)
create mode 100644 tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c
--
2.24.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH bpf-next 1/4] bpf: introduce task_vma bpf_iter
2020-12-12 2:48 [PATCH bpf-next 0/4] introduce bpf_iter for task_vma Song Liu
@ 2020-12-12 2:48 ` Song Liu
2020-12-14 7:13 ` Yonghong Song
2020-12-15 19:46 ` Yonghong Song
2020-12-12 2:48 ` [PATCH bpf-next 2/4] bpf: allow bpf_d_path in sleepable bpf_iter program Song Liu
` (2 subsequent siblings)
3 siblings, 2 replies; 10+ messages in thread
From: Song Liu @ 2020-12-12 2:48 UTC (permalink / raw)
To: bpf, netdev
Cc: ast, daniel, andrii, john.fastabend, kpsingh, kernel-team, Song Liu
Introduce task_vma bpf_iter to print memory information of a process. It
can be used to print customized information similar to /proc/<pid>/maps.
task_vma iterator releases mmap_lock before calling the BPF program.
Therefore, we cannot pass vm_area_struct directly to the BPF program. A
new __vm_area_struct is introduced to keep key information of a vma. On
each iteration, task_vma gathers information in __vm_area_struct and
passes it to the BPF program.
If the vma maps to a file, task_vma also holds a reference to the file
while calling the BPF program.
Signed-off-by: Song Liu <songliubraving@fb.com>
---
include/linux/bpf.h | 2 +-
include/uapi/linux/bpf.h | 7 ++
kernel/bpf/task_iter.c | 193 ++++++++++++++++++++++++++++++++++++++-
3 files changed, 200 insertions(+), 2 deletions(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 07cb5d15e7439..49dd1e29c8118 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1325,7 +1325,7 @@ enum bpf_iter_feature {
BPF_ITER_RESCHED = BIT(0),
};
-#define BPF_ITER_CTX_ARG_MAX 2
+#define BPF_ITER_CTX_ARG_MAX 3
struct bpf_iter_reg {
const char *target;
bpf_iter_attach_target_t attach_target;
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 30b477a264827..c2db8a1d0cbd2 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -5151,4 +5151,11 @@ enum {
BTF_F_ZERO = (1ULL << 3),
};
+struct __vm_area_struct {
+ __u64 start;
+ __u64 end;
+ __u64 flags;
+ __u64 pgoff;
+};
+
#endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/kernel/bpf/task_iter.c b/kernel/bpf/task_iter.c
index 0458a40edf10a..30e5475d0831e 100644
--- a/kernel/bpf/task_iter.c
+++ b/kernel/bpf/task_iter.c
@@ -304,9 +304,171 @@ static const struct seq_operations task_file_seq_ops = {
.show = task_file_seq_show,
};
+struct bpf_iter_seq_task_vma_info {
+ /* The first field must be struct bpf_iter_seq_task_common.
+ * this is assumed by {init, fini}_seq_pidns() callback functions.
+ */
+ struct bpf_iter_seq_task_common common;
+ struct task_struct *task;
+ struct __vm_area_struct vma;
+ struct file *file;
+ u32 tid;
+};
+
+static struct __vm_area_struct *
+task_vma_seq_get_next(struct bpf_iter_seq_task_vma_info *info)
+{
+ struct pid_namespace *ns = info->common.ns;
+ struct task_struct *curr_task;
+ struct vm_area_struct *vma;
+ u32 curr_tid = info->tid;
+ bool new_task = false;
+
+ /* If this function returns a non-NULL vma, it held a reference to
+ * the task_struct. If info->file is non-NULL, it also holds a
+ * reference to the file. Otherwise, it does not hold any
+ * reference.
+ */
+again:
+ if (info->task) {
+ curr_task = info->task;
+ } else {
+ curr_task = task_seq_get_next(ns, &curr_tid, true);
+ if (!curr_task) {
+ info->task = NULL;
+ return NULL;
+ }
+
+ if (curr_tid != info->tid) {
+ info->tid = curr_tid;
+ new_task = true;
+ }
+
+ if (!curr_task->mm)
+ goto next_task;
+ info->task = curr_task;
+ }
+
+ mmap_read_lock(curr_task->mm);
+ if (new_task) {
+ vma = curr_task->mm->mmap;
+ } else {
+ /* We drop the lock between each iteration, so it is
+ * necessary to use find_vma() to find the next vma. This
+ * is similar to the mechanism in show_smaps_rollup().
+ */
+ vma = find_vma(curr_task->mm, info->vma.end - 1);
+ /* same vma as previous iteration, use vma->next */
+ if (vma && (vma->vm_start == info->vma.start))
+ vma = vma->vm_next;
+ }
+ if (!vma) {
+ mmap_read_unlock(curr_task->mm);
+ goto next_task;
+ }
+ info->task = curr_task;
+ info->vma.start = vma->vm_start;
+ info->vma.end = vma->vm_end;
+ info->vma.pgoff = vma->vm_pgoff;
+ info->vma.flags = vma->vm_flags;
+ if (vma->vm_file)
+ info->file = get_file(vma->vm_file);
+ mmap_read_unlock(curr_task->mm);
+ return &info->vma;
+
+next_task:
+ put_task_struct(curr_task);
+ info->task = NULL;
+ curr_tid = ++(info->tid);
+ goto again;
+}
+
+static void *task_vma_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ struct bpf_iter_seq_task_vma_info *info = seq->private;
+ struct __vm_area_struct *vma;
+
+ info->task = NULL;
+ vma = task_vma_seq_get_next(info);
+ if (vma && *pos == 0)
+ ++*pos;
+
+ return vma;
+}
+
+static void *task_vma_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct bpf_iter_seq_task_vma_info *info = seq->private;
+
+ ++*pos;
+ if (info->file) {
+ fput(info->file);
+ info->file = NULL;
+ }
+ return task_vma_seq_get_next(info);
+}
+
+struct bpf_iter__task_vma {
+ __bpf_md_ptr(struct bpf_iter_meta *, meta);
+ __bpf_md_ptr(struct task_struct *, task);
+ __bpf_md_ptr(struct __vm_area_struct *, vma);
+ __bpf_md_ptr(struct file *, file);
+};
+
+DEFINE_BPF_ITER_FUNC(task_vma, struct bpf_iter_meta *meta,
+ struct task_struct *task, struct __vm_area_struct *vma,
+ struct file *file)
+
+static int __task_vma_seq_show(struct seq_file *seq, bool in_stop)
+{
+ struct bpf_iter_seq_task_vma_info *info = seq->private;
+ struct bpf_iter__task_vma ctx;
+ struct bpf_iter_meta meta;
+ struct bpf_prog *prog;
+
+ meta.seq = seq;
+ prog = bpf_iter_get_info(&meta, in_stop);
+ if (!prog)
+ return 0;
+
+ ctx.meta = &meta;
+ ctx.task = info->task;
+ ctx.vma = &info->vma;
+ ctx.file = info->file;
+ return bpf_iter_run_prog(prog, &ctx);
+}
+
+static int task_vma_seq_show(struct seq_file *seq, void *v)
+{
+ return __task_vma_seq_show(seq, false);
+}
+
+static void task_vma_seq_stop(struct seq_file *seq, void *v)
+{
+ struct bpf_iter_seq_task_vma_info *info = seq->private;
+
+ if (!v) {
+ (void)__task_vma_seq_show(seq, true);
+ } else {
+ put_task_struct(info->task);
+ if (info->file) {
+ fput(info->file);
+ info->file = NULL;
+ }
+ }
+}
+
+static const struct seq_operations task_vma_seq_ops = {
+ .start = task_vma_seq_start,
+ .next = task_vma_seq_next,
+ .stop = task_vma_seq_stop,
+ .show = task_vma_seq_show,
+};
+
BTF_ID_LIST(btf_task_file_ids)
BTF_ID(struct, task_struct)
BTF_ID(struct, file)
+BTF_ID(struct, __vm_area_struct)
static const struct bpf_iter_seq_info task_seq_info = {
.seq_ops = &task_seq_ops,
@@ -346,6 +508,28 @@ static struct bpf_iter_reg task_file_reg_info = {
.seq_info = &task_file_seq_info,
};
+static const struct bpf_iter_seq_info task_vma_seq_info = {
+ .seq_ops = &task_vma_seq_ops,
+ .init_seq_private = init_seq_pidns,
+ .fini_seq_private = fini_seq_pidns,
+ .seq_priv_size = sizeof(struct bpf_iter_seq_task_vma_info),
+};
+
+static struct bpf_iter_reg task_vma_reg_info = {
+ .target = "task_vma",
+ .feature = BPF_ITER_RESCHED,
+ .ctx_arg_info_size = 3,
+ .ctx_arg_info = {
+ { offsetof(struct bpf_iter__task_vma, task),
+ PTR_TO_BTF_ID_OR_NULL },
+ { offsetof(struct bpf_iter__task_vma, vma),
+ PTR_TO_BTF_ID_OR_NULL },
+ { offsetof(struct bpf_iter__task_vma, file),
+ PTR_TO_BTF_ID_OR_NULL },
+ },
+ .seq_info = &task_vma_seq_info,
+};
+
static int __init task_iter_init(void)
{
int ret;
@@ -357,6 +541,13 @@ static int __init task_iter_init(void)
task_file_reg_info.ctx_arg_info[0].btf_id = btf_task_file_ids[0];
task_file_reg_info.ctx_arg_info[1].btf_id = btf_task_file_ids[1];
- return bpf_iter_reg_target(&task_file_reg_info);
+ ret = bpf_iter_reg_target(&task_file_reg_info);
+ if (ret)
+ return ret;
+
+ task_vma_reg_info.ctx_arg_info[0].btf_id = btf_task_file_ids[0];
+ task_vma_reg_info.ctx_arg_info[1].btf_id = btf_task_file_ids[2];
+ task_vma_reg_info.ctx_arg_info[2].btf_id = btf_task_file_ids[1];
+ return bpf_iter_reg_target(&task_vma_reg_info);
}
late_initcall(task_iter_init);
--
2.24.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH bpf-next 2/4] bpf: allow bpf_d_path in sleepable bpf_iter program
2020-12-12 2:48 [PATCH bpf-next 0/4] introduce bpf_iter for task_vma Song Liu
2020-12-12 2:48 ` [PATCH bpf-next 1/4] bpf: introduce task_vma bpf_iter Song Liu
@ 2020-12-12 2:48 ` Song Liu
2020-12-12 2:48 ` [PATCH bpf-next 3/4] libbpf: introduce section "iter.s/" for " Song Liu
2020-12-12 2:48 ` [PATCH bpf-next 4/4] selftests/bpf: add test for bpf_iter_task_vma Song Liu
3 siblings, 0 replies; 10+ messages in thread
From: Song Liu @ 2020-12-12 2:48 UTC (permalink / raw)
To: bpf, netdev
Cc: ast, daniel, andrii, john.fastabend, kpsingh, kernel-team, Song Liu
task_file and task_vma iter programs have access to file->f_path. Enable
bpf_d_path to print paths of these file.
bpf_iter programs are generally called in sleepable context. However, it
is still necessary to diffientiate sleepable and non-sleepable bpf_iter
programs: sleepable programs have access to bpf_d_path; non-sleepable
programs have access to bpf_spin_lock.
Signed-off-by: Song Liu <songliubraving@fb.com>
---
kernel/trace/bpf_trace.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 52ddd217d6a19..839c654160d1b 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1191,6 +1191,11 @@ BTF_SET_END(btf_allowlist_d_path)
static bool bpf_d_path_allowed(const struct bpf_prog *prog)
{
+ if (prog->type == BPF_PROG_TYPE_TRACING &&
+ prog->expected_attach_type == BPF_TRACE_ITER &&
+ prog->aux->sleepable)
+ return true;
+
if (prog->type == BPF_PROG_TYPE_LSM)
return bpf_lsm_is_sleepable_hook(prog->aux->attach_btf_id);
--
2.24.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH bpf-next 3/4] libbpf: introduce section "iter.s/" for sleepable bpf_iter program
2020-12-12 2:48 [PATCH bpf-next 0/4] introduce bpf_iter for task_vma Song Liu
2020-12-12 2:48 ` [PATCH bpf-next 1/4] bpf: introduce task_vma bpf_iter Song Liu
2020-12-12 2:48 ` [PATCH bpf-next 2/4] bpf: allow bpf_d_path in sleepable bpf_iter program Song Liu
@ 2020-12-12 2:48 ` Song Liu
2020-12-12 2:48 ` [PATCH bpf-next 4/4] selftests/bpf: add test for bpf_iter_task_vma Song Liu
3 siblings, 0 replies; 10+ messages in thread
From: Song Liu @ 2020-12-12 2:48 UTC (permalink / raw)
To: bpf, netdev
Cc: ast, daniel, andrii, john.fastabend, kpsingh, kernel-team, Song Liu
Sleepable iterator program have access to helper functions like bpf_d_path.
Signed-off-by: Song Liu <songliubraving@fb.com>
---
tools/lib/bpf/libbpf.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 9be88a90a4aad..9204d12d04bf8 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -8535,6 +8535,11 @@ static const struct bpf_sec_def section_defs[] = {
.expected_attach_type = BPF_TRACE_ITER,
.is_attach_btf = true,
.attach_fn = attach_iter),
+ SEC_DEF("iter.s/", TRACING,
+ .expected_attach_type = BPF_TRACE_ITER,
+ .is_attach_btf = true,
+ .is_sleepable = true,
+ .attach_fn = attach_iter),
BPF_EAPROG_SEC("xdp_devmap/", BPF_PROG_TYPE_XDP,
BPF_XDP_DEVMAP),
BPF_EAPROG_SEC("xdp_cpumap/", BPF_PROG_TYPE_XDP,
--
2.24.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH bpf-next 4/4] selftests/bpf: add test for bpf_iter_task_vma
2020-12-12 2:48 [PATCH bpf-next 0/4] introduce bpf_iter for task_vma Song Liu
` (2 preceding siblings ...)
2020-12-12 2:48 ` [PATCH bpf-next 3/4] libbpf: introduce section "iter.s/" for " Song Liu
@ 2020-12-12 2:48 ` Song Liu
2020-12-15 20:21 ` Yonghong Song
3 siblings, 1 reply; 10+ messages in thread
From: Song Liu @ 2020-12-12 2:48 UTC (permalink / raw)
To: bpf, netdev
Cc: ast, daniel, andrii, john.fastabend, kpsingh, kernel-team, Song Liu
The test dumps information similar to /proc/pid/maps. The first line of
the output is compared against the /proc file to make sure they match.
Signed-off-by: Song Liu <songliubraving@fb.com>
---
.../selftests/bpf/prog_tests/bpf_iter.c | 106 ++++++++++++++++--
tools/testing/selftests/bpf/progs/bpf_iter.h | 9 ++
.../selftests/bpf/progs/bpf_iter_task_vma.c | 55 +++++++++
3 files changed, 160 insertions(+), 10 deletions(-)
create mode 100644 tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c
diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
index 0e586368948dd..7afd3abae1899 100644
--- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
+++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
@@ -7,6 +7,7 @@
#include "bpf_iter_task.skel.h"
#include "bpf_iter_task_stack.skel.h"
#include "bpf_iter_task_file.skel.h"
+#include "bpf_iter_task_vma.skel.h"
#include "bpf_iter_task_btf.skel.h"
#include "bpf_iter_tcp4.skel.h"
#include "bpf_iter_tcp6.skel.h"
@@ -64,6 +65,22 @@ static void do_dummy_read(struct bpf_program *prog)
bpf_link__destroy(link);
}
+static int read_fd_into_buffer(int fd, char *buf, int size)
+{
+ int bufleft = size;
+ int len;
+
+ do {
+ len = read(fd, buf, bufleft);
+ if (len > 0) {
+ buf += len;
+ bufleft -= len;
+ }
+ } while (len > 0);
+
+ return len;
+}
+
static void test_ipv6_route(void)
{
struct bpf_iter_ipv6_route *skel;
@@ -177,7 +194,7 @@ static int do_btf_read(struct bpf_iter_task_btf *skel)
{
struct bpf_program *prog = skel->progs.dump_task_struct;
struct bpf_iter_task_btf__bss *bss = skel->bss;
- int iter_fd = -1, len = 0, bufleft = TASKBUFSZ;
+ int iter_fd = -1, err;
struct bpf_link *link;
char *buf = taskbuf;
int ret = 0;
@@ -190,14 +207,7 @@ static int do_btf_read(struct bpf_iter_task_btf *skel)
if (CHECK(iter_fd < 0, "create_iter", "create_iter failed\n"))
goto free_link;
- do {
- len = read(iter_fd, buf, bufleft);
- if (len > 0) {
- buf += len;
- bufleft -= len;
- }
- } while (len > 0);
-
+ err = read_fd_into_buffer(iter_fd, buf, TASKBUFSZ);
if (bss->skip) {
printf("%s:SKIP:no __builtin_btf_type_id\n", __func__);
ret = 1;
@@ -205,7 +215,7 @@ static int do_btf_read(struct bpf_iter_task_btf *skel)
goto free_link;
}
- if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno)))
+ if (CHECK(err < 0, "read", "read failed: %s\n", strerror(errno)))
goto free_link;
CHECK(strstr(taskbuf, "(struct task_struct)") == NULL,
@@ -1133,6 +1143,80 @@ static void test_buf_neg_offset(void)
bpf_iter_test_kern6__destroy(skel);
}
+#define CMP_BUFFER_SIZE 1024
+char task_vma_output[CMP_BUFFER_SIZE];
+char proc_maps_output[CMP_BUFFER_SIZE];
+
+/* remove \0 and \t from str, and only keep the first line */
+static void str_strip_first_line(char *str)
+{
+ char *dst = str, *src = str;
+
+ do {
+ if (*src == ' ' || *src == '\t')
+ src++;
+ else
+ *(dst++) = *(src++);
+
+ } while (*src != '\0' && *src != '\n');
+
+ *dst = '\0';
+}
+
+static void test_task_vma(void)
+{
+ int err, iter_fd = -1, proc_maps_fd = -1;
+ struct bpf_iter_task_vma *skel;
+ char maps_path[64];
+
+ skel = bpf_iter_task_vma__open();
+ if (CHECK(!skel, "bpf_iter_task_vma__open", "skeleton open failed\n"))
+ return;
+
+ skel->bss->pid = getpid();
+
+ err = bpf_iter_task_vma__load(skel);
+ if (CHECK(err, "bpf_iter_task_vma__load", "skeleton load failed\n"))
+ goto out;
+
+ do_dummy_read(skel->progs.proc_maps);
+
+ skel->links.proc_maps = bpf_program__attach_iter(
+ skel->progs.proc_maps, NULL);
+
+ if (CHECK(IS_ERR(skel->links.proc_maps), "bpf_program__attach_iter",
+ "attach iterator failed\n"))
+ goto out;
+
+ /* read 1kB from bpf_iter */
+ iter_fd = bpf_iter_create(bpf_link__fd(skel->links.proc_maps));
+ if (CHECK(iter_fd < 0, "create_iter", "create_iter failed\n"))
+ goto out;
+ err = read_fd_into_buffer(iter_fd, task_vma_output, CMP_BUFFER_SIZE);
+ if (CHECK(err < 0, "read_iter_fd", "read_iter_fd failed\n"))
+ goto out;
+
+ /* read 1kB from /proc/pid/maps */
+ snprintf(maps_path, 64, "/proc/%u/maps", skel->bss->pid);
+ proc_maps_fd = open(maps_path, O_RDONLY);
+ if (CHECK(proc_maps_fd < 0, "open_proc_maps", "open_proc_maps failed\n"))
+ goto out;
+ err = read_fd_into_buffer(proc_maps_fd, proc_maps_output, CMP_BUFFER_SIZE);
+ if (CHECK(err < 0, "read_prog_maps_fd", "read_prog_maps_fd failed\n"))
+ goto out;
+
+ /* strip and compare the first line of the two files */
+ str_strip_first_line(task_vma_output);
+ str_strip_first_line(proc_maps_output);
+
+ CHECK(strcmp(task_vma_output, proc_maps_output), "compare_output",
+ "found mismatch\n");
+out:
+ close(proc_maps_fd);
+ close(iter_fd);
+ bpf_iter_task_vma__destroy(skel);
+}
+
void test_bpf_iter(void)
{
if (test__start_subtest("btf_id_or_null"))
@@ -1149,6 +1233,8 @@ void test_bpf_iter(void)
test_task_stack();
if (test__start_subtest("task_file"))
test_task_file();
+ if (test__start_subtest("task_vma"))
+ test_task_vma();
if (test__start_subtest("task_btf"))
test_task_btf();
if (test__start_subtest("tcp4"))
diff --git a/tools/testing/selftests/bpf/progs/bpf_iter.h b/tools/testing/selftests/bpf/progs/bpf_iter.h
index 6a1255465fd6d..4dab0869c4fcb 100644
--- a/tools/testing/selftests/bpf/progs/bpf_iter.h
+++ b/tools/testing/selftests/bpf/progs/bpf_iter.h
@@ -7,6 +7,7 @@
#define bpf_iter__netlink bpf_iter__netlink___not_used
#define bpf_iter__task bpf_iter__task___not_used
#define bpf_iter__task_file bpf_iter__task_file___not_used
+#define bpf_iter__task_vma bpf_iter__task_vma___not_used
#define bpf_iter__tcp bpf_iter__tcp___not_used
#define tcp6_sock tcp6_sock___not_used
#define bpf_iter__udp bpf_iter__udp___not_used
@@ -26,6 +27,7 @@
#undef bpf_iter__netlink
#undef bpf_iter__task
#undef bpf_iter__task_file
+#undef bpf_iter__task_vma
#undef bpf_iter__tcp
#undef tcp6_sock
#undef bpf_iter__udp
@@ -67,6 +69,13 @@ struct bpf_iter__task_file {
struct file *file;
} __attribute__((preserve_access_index));
+struct bpf_iter__task_vma {
+ struct bpf_iter_meta *meta;
+ struct task_struct *task;
+ struct __vm_area_struct *vma;
+ struct file *file;
+} __attribute__((preserve_access_index));
+
struct bpf_iter__bpf_map {
struct bpf_iter_meta *meta;
struct bpf_map *map;
diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c b/tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c
new file mode 100644
index 0000000000000..d60b5b38cb396
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2020 Facebook */
+#include "bpf_iter.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+char _license[] SEC("license") = "GPL";
+
+/* Copied from mm.h */
+#define VM_READ 0x00000001
+#define VM_WRITE 0x00000002
+#define VM_EXEC 0x00000004
+#define VM_MAYSHARE 0x00000080
+
+/* Copied from kdev_t.h */
+#define MINORBITS 20
+#define MINORMASK ((1U << MINORBITS) - 1)
+#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
+#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
+
+#define D_PATH_BUF_SIZE 1024
+char d_path_buf[D_PATH_BUF_SIZE];
+__u32 pid;
+
+SEC("iter.s/task_vma") int proc_maps(struct bpf_iter__task_vma *ctx)
+{
+ struct __vm_area_struct *vma = ctx->vma;
+ struct seq_file *seq = ctx->meta->seq;
+ struct task_struct *task = ctx->task;
+ struct file *file = ctx->file;
+ char perm_str[] = "----";
+
+ if (task == (void *)0 || vma == (void *)0 || task->pid != pid)
+ return 0;
+
+ perm_str[0] = (vma->flags & VM_READ) ? 'r' : '-';
+ perm_str[1] = (vma->flags & VM_WRITE) ? 'w' : '-';
+ perm_str[1] = (vma->flags & VM_EXEC) ? 'x' : '-';
+ perm_str[3] = (vma->flags & VM_MAYSHARE) ? 's' : 'p';
+ BPF_SEQ_PRINTF(seq, "%08llx-%08llx %s ", vma->start, vma->end, perm_str);
+
+ if (file) {
+ __u32 dev = file->f_inode->i_sb->s_dev;
+
+ bpf_d_path(&file->f_path, d_path_buf, D_PATH_BUF_SIZE);
+
+ BPF_SEQ_PRINTF(seq, "%08llx ", vma->pgoff << 12);
+ BPF_SEQ_PRINTF(seq, "%02x:%02x %u", MAJOR(dev), MINOR(dev),
+ file->f_inode->i_ino);
+ BPF_SEQ_PRINTF(seq, "\t%s\n", d_path_buf);
+ } else {
+ BPF_SEQ_PRINTF(seq, "%08llx 00:00 0\n", 0ULL);
+ }
+ return 0;
+}
--
2.24.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH bpf-next 1/4] bpf: introduce task_vma bpf_iter
2020-12-12 2:48 ` [PATCH bpf-next 1/4] bpf: introduce task_vma bpf_iter Song Liu
@ 2020-12-14 7:13 ` Yonghong Song
2020-12-14 22:31 ` Song Liu
2020-12-15 19:46 ` Yonghong Song
1 sibling, 1 reply; 10+ messages in thread
From: Yonghong Song @ 2020-12-14 7:13 UTC (permalink / raw)
To: Song Liu, bpf, netdev
Cc: ast, daniel, andrii, john.fastabend, kpsingh, kernel-team
On 12/11/20 6:48 PM, Song Liu wrote:
> Introduce task_vma bpf_iter to print memory information of a process. It
> can be used to print customized information similar to /proc/<pid>/maps.
>
> task_vma iterator releases mmap_lock before calling the BPF program.
> Therefore, we cannot pass vm_area_struct directly to the BPF program. A
> new __vm_area_struct is introduced to keep key information of a vma. On
> each iteration, task_vma gathers information in __vm_area_struct and
> passes it to the BPF program.
>
> If the vma maps to a file, task_vma also holds a reference to the file
> while calling the BPF program.
>
> Signed-off-by: Song Liu <songliubraving@fb.com>
> ---
> include/linux/bpf.h | 2 +-
> include/uapi/linux/bpf.h | 7 ++
> kernel/bpf/task_iter.c | 193 ++++++++++++++++++++++++++++++++++++++-
> 3 files changed, 200 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index 07cb5d15e7439..49dd1e29c8118 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -1325,7 +1325,7 @@ enum bpf_iter_feature {
> BPF_ITER_RESCHED = BIT(0),
> };
>
> -#define BPF_ITER_CTX_ARG_MAX 2
> +#define BPF_ITER_CTX_ARG_MAX 3
> struct bpf_iter_reg {
> const char *target;
> bpf_iter_attach_target_t attach_target;
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index 30b477a264827..c2db8a1d0cbd2 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -5151,4 +5151,11 @@ enum {
> BTF_F_ZERO = (1ULL << 3),
> };
>
> +struct __vm_area_struct {
> + __u64 start;
> + __u64 end;
> + __u64 flags;
> + __u64 pgoff;
> +};
Probably we should not expose the above structure as uapi.
All other bpf_iter ctx argument layouts are btf based
and consider unstable. btf_iter itself is considered
as an unstable interface to dump kernel internal
data structures.
> +
> #endif /* _UAPI__LINUX_BPF_H__ */
> diff --git a/kernel/bpf/task_iter.c b/kernel/bpf/task_iter.c
> index 0458a40edf10a..30e5475d0831e 100644
> --- a/kernel/bpf/task_iter.c
> +++ b/kernel/bpf/task_iter.c
> @@ -304,9 +304,171 @@ static const struct seq_operations task_file_seq_ops = {
> .show = task_file_seq_show,
> };
>
> +struct bpf_iter_seq_task_vma_info {
> + /* The first field must be struct bpf_iter_seq_task_common.
> + * this is assumed by {init, fini}_seq_pidns() callback functions.
> + */
> + struct bpf_iter_seq_task_common common;
> + struct task_struct *task;
> + struct __vm_area_struct vma;
> + struct file *file;
> + u32 tid;
> +};
> +
[...]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH bpf-next 1/4] bpf: introduce task_vma bpf_iter
2020-12-14 7:13 ` Yonghong Song
@ 2020-12-14 22:31 ` Song Liu
0 siblings, 0 replies; 10+ messages in thread
From: Song Liu @ 2020-12-14 22:31 UTC (permalink / raw)
To: Yonghong Song
Cc: bpf, netdev, ast, daniel, andrii, john.fastabend, kpsingh, Kernel Team
> On Dec 13, 2020, at 11:13 PM, Yonghong Song <yhs@fb.com> wrote:
>
>
>
> On 12/11/20 6:48 PM, Song Liu wrote:
>> Introduce task_vma bpf_iter to print memory information of a process. It
>> can be used to print customized information similar to /proc/<pid>/maps.
>> task_vma iterator releases mmap_lock before calling the BPF program.
>> Therefore, we cannot pass vm_area_struct directly to the BPF program. A
>> new __vm_area_struct is introduced to keep key information of a vma. On
>> each iteration, task_vma gathers information in __vm_area_struct and
>> passes it to the BPF program.
>> If the vma maps to a file, task_vma also holds a reference to the file
>> while calling the BPF program.
>> Signed-off-by: Song Liu <songliubraving@fb.com>
>> ---
>> include/linux/bpf.h | 2 +-
>> include/uapi/linux/bpf.h | 7 ++
>> kernel/bpf/task_iter.c | 193 ++++++++++++++++++++++++++++++++++++++-
>> 3 files changed, 200 insertions(+), 2 deletions(-)
>> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
>> index 07cb5d15e7439..49dd1e29c8118 100644
>> --- a/include/linux/bpf.h
>> +++ b/include/linux/bpf.h
>> @@ -1325,7 +1325,7 @@ enum bpf_iter_feature {
>> BPF_ITER_RESCHED = BIT(0),
>> };
>> -#define BPF_ITER_CTX_ARG_MAX 2
>> +#define BPF_ITER_CTX_ARG_MAX 3
>> struct bpf_iter_reg {
>> const char *target;
>> bpf_iter_attach_target_t attach_target;
>> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
>> index 30b477a264827..c2db8a1d0cbd2 100644
>> --- a/include/uapi/linux/bpf.h
>> +++ b/include/uapi/linux/bpf.h
>> @@ -5151,4 +5151,11 @@ enum {
>> BTF_F_ZERO = (1ULL << 3),
>> };
>> +struct __vm_area_struct {
>> + __u64 start;
>> + __u64 end;
>> + __u64 flags;
>> + __u64 pgoff;
>> +};
>
> Probably we should not expose the above structure as uapi.
> All other bpf_iter ctx argument layouts are btf based
> and consider unstable. btf_iter itself is considered
> as an unstable interface to dump kernel internal
> data structures.
Yes, we can keep it in task_iter.c. I moved it to uapi to follow __sk_buff
pattern. It works fine in task_iter.c
Thanks,
Song
>
>> +
>> #endif /* _UAPI__LINUX_BPF_H__ */
>> diff --git a/kernel/bpf/task_iter.c b/kernel/bpf/task_iter.c
>> index 0458a40edf10a..30e5475d0831e 100644
>> --- a/kernel/bpf/task_iter.c
>> +++ b/kernel/bpf/task_iter.c
>> @@ -304,9 +304,171 @@ static const struct seq_operations task_file_seq_ops = {
>> .show = task_file_seq_show,
>> };
>> +struct bpf_iter_seq_task_vma_info {
>> + /* The first field must be struct bpf_iter_seq_task_common.
>> + * this is assumed by {init, fini}_seq_pidns() callback functions.
>> + */
>> + struct bpf_iter_seq_task_common common;
>> + struct task_struct *task;
>> + struct __vm_area_struct vma;
>> + struct file *file;
>> + u32 tid;
>> +};
>> +
> [...]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH bpf-next 1/4] bpf: introduce task_vma bpf_iter
2020-12-12 2:48 ` [PATCH bpf-next 1/4] bpf: introduce task_vma bpf_iter Song Liu
2020-12-14 7:13 ` Yonghong Song
@ 2020-12-15 19:46 ` Yonghong Song
1 sibling, 0 replies; 10+ messages in thread
From: Yonghong Song @ 2020-12-15 19:46 UTC (permalink / raw)
To: Song Liu, bpf, netdev
Cc: ast, daniel, andrii, john.fastabend, kpsingh, kernel-team
On 12/11/20 6:48 PM, Song Liu wrote:
> Introduce task_vma bpf_iter to print memory information of a process. It
> can be used to print customized information similar to /proc/<pid>/maps.
>
> task_vma iterator releases mmap_lock before calling the BPF program.
> Therefore, we cannot pass vm_area_struct directly to the BPF program. A
> new __vm_area_struct is introduced to keep key information of a vma. On
> each iteration, task_vma gathers information in __vm_area_struct and
> passes it to the BPF program.
>
> If the vma maps to a file, task_vma also holds a reference to the file
> while calling the BPF program.
>
> Signed-off-by: Song Liu <songliubraving@fb.com>
> ---
> include/linux/bpf.h | 2 +-
> include/uapi/linux/bpf.h | 7 ++
> kernel/bpf/task_iter.c | 193 ++++++++++++++++++++++++++++++++++++++-
> 3 files changed, 200 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index 07cb5d15e7439..49dd1e29c8118 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -1325,7 +1325,7 @@ enum bpf_iter_feature {
> BPF_ITER_RESCHED = BIT(0),
> };
>
> -#define BPF_ITER_CTX_ARG_MAX 2
> +#define BPF_ITER_CTX_ARG_MAX 3
> struct bpf_iter_reg {
> const char *target;
> bpf_iter_attach_target_t attach_target;
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index 30b477a264827..c2db8a1d0cbd2 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -5151,4 +5151,11 @@ enum {
> BTF_F_ZERO = (1ULL << 3),
> };
>
> +struct __vm_area_struct {
> + __u64 start;
> + __u64 end;
> + __u64 flags;
> + __u64 pgoff;
> +};
> +
> #endif /* _UAPI__LINUX_BPF_H__ */
> diff --git a/kernel/bpf/task_iter.c b/kernel/bpf/task_iter.c
> index 0458a40edf10a..30e5475d0831e 100644
> --- a/kernel/bpf/task_iter.c
> +++ b/kernel/bpf/task_iter.c
> @@ -304,9 +304,171 @@ static const struct seq_operations task_file_seq_ops = {
> .show = task_file_seq_show,
> };
>
> +struct bpf_iter_seq_task_vma_info {
> + /* The first field must be struct bpf_iter_seq_task_common.
> + * this is assumed by {init, fini}_seq_pidns() callback functions.
> + */
> + struct bpf_iter_seq_task_common common;
> + struct task_struct *task;
> + struct __vm_area_struct vma;
> + struct file *file;
> + u32 tid;
> +};
> +
> +static struct __vm_area_struct *
> +task_vma_seq_get_next(struct bpf_iter_seq_task_vma_info *info)
> +{
> + struct pid_namespace *ns = info->common.ns;
> + struct task_struct *curr_task;
> + struct vm_area_struct *vma;
> + u32 curr_tid = info->tid;
> + bool new_task = false;
> +
> + /* If this function returns a non-NULL vma, it held a reference to
the function does not return vma, it returns an internal data
structure __vm_area_struct which captures some fields from vma.
> + * the task_struct. If info->file is non-NULL, it also holds a
> + * reference to the file. Otherwise, it does not hold any
> + * reference.
> + */
> +again:
> + if (info->task) {
> + curr_task = info->task;
> + } else {
> + curr_task = task_seq_get_next(ns, &curr_tid, true);
> + if (!curr_task) {
> + info->task = NULL;
adding "info->tid = curr_tid + 1" so next read, e.g. after read()
syscall return 0 read length, will start after last checked curr_tid.
> + return NULL;
> + }
> +
> + if (curr_tid != info->tid) {
> + info->tid = curr_tid;
> + new_task = true;
> + }
> +
> + if (!curr_task->mm)
> + goto next_task;
> + info->task = curr_task;
> + }
> +
> + mmap_read_lock(curr_task->mm);
> + if (new_task) {
> + vma = curr_task->mm->mmap;
> + } else {
> + /* We drop the lock between each iteration, so it is
> + * necessary to use find_vma() to find the next vma. This
> + * is similar to the mechanism in show_smaps_rollup().
> + */
> + vma = find_vma(curr_task->mm, info->vma.end - 1);
> + /* same vma as previous iteration, use vma->next */
> + if (vma && (vma->vm_start == info->vma.start))
> + vma = vma->vm_next;
> + }
> + if (!vma) {
> + mmap_read_unlock(curr_task->mm);
> + goto next_task;
> + }
> + info->task = curr_task;
> + info->vma.start = vma->vm_start;
> + info->vma.end = vma->vm_end;
> + info->vma.pgoff = vma->vm_pgoff;
> + info->vma.flags = vma->vm_flags;
> + if (vma->vm_file)
> + info->file = get_file(vma->vm_file);
> + mmap_read_unlock(curr_task->mm);
> + return &info->vma;
> +
> +next_task:
> + put_task_struct(curr_task);
> + info->task = NULL;
> + curr_tid = ++(info->tid);
> + goto again;
> +}
> +
> +static void *task_vma_seq_start(struct seq_file *seq, loff_t *pos)
> +{
> + struct bpf_iter_seq_task_vma_info *info = seq->private;
> + struct __vm_area_struct *vma;
> +
> + info->task = NULL;
Maybe put info->task = NULL in task_vma_seq_stop()?
> + vma = task_vma_seq_get_next(info);
> + if (vma && *pos == 0)
> + ++*pos;
> +
> + return vma;
> +}
> +
> +static void *task_vma_seq_next(struct seq_file *seq, void *v, loff_t *pos)
> +{
> + struct bpf_iter_seq_task_vma_info *info = seq->private;
> +
> + ++*pos;
> + if (info->file) {
> + fput(info->file);
> + info->file = NULL;
> + }
> + return task_vma_seq_get_next(info);
> +}
> +
> +struct bpf_iter__task_vma {
> + __bpf_md_ptr(struct bpf_iter_meta *, meta);
> + __bpf_md_ptr(struct task_struct *, task);
> + __bpf_md_ptr(struct __vm_area_struct *, vma);
> + __bpf_md_ptr(struct file *, file);
> +};
> +
> +DEFINE_BPF_ITER_FUNC(task_vma, struct bpf_iter_meta *meta,
> + struct task_struct *task, struct __vm_area_struct *vma,
> + struct file *file)
> +
[...]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH bpf-next 4/4] selftests/bpf: add test for bpf_iter_task_vma
2020-12-12 2:48 ` [PATCH bpf-next 4/4] selftests/bpf: add test for bpf_iter_task_vma Song Liu
@ 2020-12-15 20:21 ` Yonghong Song
2020-12-15 20:59 ` Song Liu
0 siblings, 1 reply; 10+ messages in thread
From: Yonghong Song @ 2020-12-15 20:21 UTC (permalink / raw)
To: Song Liu, bpf, netdev
Cc: ast, daniel, andrii, john.fastabend, kpsingh, kernel-team
On 12/11/20 6:48 PM, Song Liu wrote:
> The test dumps information similar to /proc/pid/maps. The first line of
> the output is compared against the /proc file to make sure they match.
>
> Signed-off-by: Song Liu <songliubraving@fb.com>
> ---
> .../selftests/bpf/prog_tests/bpf_iter.c | 106 ++++++++++++++++--
> tools/testing/selftests/bpf/progs/bpf_iter.h | 9 ++
> .../selftests/bpf/progs/bpf_iter_task_vma.c | 55 +++++++++
> 3 files changed, 160 insertions(+), 10 deletions(-)
> create mode 100644 tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
> index 0e586368948dd..7afd3abae1899 100644
> --- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
> +++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
> @@ -7,6 +7,7 @@
> #include "bpf_iter_task.skel.h"
> #include "bpf_iter_task_stack.skel.h"
> #include "bpf_iter_task_file.skel.h"
> +#include "bpf_iter_task_vma.skel.h"
> #include "bpf_iter_task_btf.skel.h"
> #include "bpf_iter_tcp4.skel.h"
> #include "bpf_iter_tcp6.skel.h"
> @@ -64,6 +65,22 @@ static void do_dummy_read(struct bpf_program *prog)
> bpf_link__destroy(link);
> }
>
[...]
> diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c b/tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c
> new file mode 100644
> index 0000000000000..d60b5b38cb396
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c
> @@ -0,0 +1,55 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2020 Facebook */
> +#include "bpf_iter.h"
> +#include <bpf/bpf_helpers.h>
> +#include <bpf/bpf_tracing.h>
> +
> +char _license[] SEC("license") = "GPL";
> +
> +/* Copied from mm.h */
> +#define VM_READ 0x00000001
> +#define VM_WRITE 0x00000002
> +#define VM_EXEC 0x00000004
> +#define VM_MAYSHARE 0x00000080
> +
> +/* Copied from kdev_t.h */
> +#define MINORBITS 20
> +#define MINORMASK ((1U << MINORBITS) - 1)
> +#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
> +#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
> +
> +#define D_PATH_BUF_SIZE 1024
> +char d_path_buf[D_PATH_BUF_SIZE];
> +__u32 pid;
> +
> +SEC("iter.s/task_vma") int proc_maps(struct bpf_iter__task_vma *ctx)
> +{
> + struct __vm_area_struct *vma = ctx->vma;
> + struct seq_file *seq = ctx->meta->seq;
> + struct task_struct *task = ctx->task;
> + struct file *file = ctx->file;
> + char perm_str[] = "----";
> +
> + if (task == (void *)0 || vma == (void *)0 || task->pid != pid)
> + return 0;
> +
> + perm_str[0] = (vma->flags & VM_READ) ? 'r' : '-';
> + perm_str[1] = (vma->flags & VM_WRITE) ? 'w' : '-';
> + perm_str[1] = (vma->flags & VM_EXEC) ? 'x' : '-';
typo here? The above should be perm_str[2].
> + perm_str[3] = (vma->flags & VM_MAYSHARE) ? 's' : 'p';
> + BPF_SEQ_PRINTF(seq, "%08llx-%08llx %s ", vma->start, vma->end, perm_str);
> +
> + if (file) {
> + __u32 dev = file->f_inode->i_sb->s_dev;
> +
> + bpf_d_path(&file->f_path, d_path_buf, D_PATH_BUF_SIZE);
> +
> + BPF_SEQ_PRINTF(seq, "%08llx ", vma->pgoff << 12);
> + BPF_SEQ_PRINTF(seq, "%02x:%02x %u", MAJOR(dev), MINOR(dev),
> + file->f_inode->i_ino);
> + BPF_SEQ_PRINTF(seq, "\t%s\n", d_path_buf);
> + } else {
> + BPF_SEQ_PRINTF(seq, "%08llx 00:00 0\n", 0ULL);
> + }
> + return 0;
> +}
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH bpf-next 4/4] selftests/bpf: add test for bpf_iter_task_vma
2020-12-15 20:21 ` Yonghong Song
@ 2020-12-15 20:59 ` Song Liu
0 siblings, 0 replies; 10+ messages in thread
From: Song Liu @ 2020-12-15 20:59 UTC (permalink / raw)
To: Yonghong Song
Cc: bpf, netdev, ast, daniel, andrii, john.fastabend, kpsingh, Kernel Team
> On Dec 15, 2020, at 12:21 PM, Yonghong Song <yhs@fb.com> wrote:
>
>
>
> On 12/11/20 6:48 PM, Song Liu wrote:
>> The test dumps information similar to /proc/pid/maps. The first line of
>> the output is compared against the /proc file to make sure they match.
>> Signed-off-by: Song Liu <songliubraving@fb.com>
>> ---
>> .../selftests/bpf/prog_tests/bpf_iter.c | 106 ++++++++++++++++--
>> tools/testing/selftests/bpf/progs/bpf_iter.h | 9 ++
>> .../selftests/bpf/progs/bpf_iter_task_vma.c | 55 +++++++++
>> 3 files changed, 160 insertions(+), 10 deletions(-)
>> create mode 100644 tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c
>> diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
>> index 0e586368948dd..7afd3abae1899 100644
>> --- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
>> +++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
>> @@ -7,6 +7,7 @@
>> #include "bpf_iter_task.skel.h"
>> #include "bpf_iter_task_stack.skel.h"
>> #include "bpf_iter_task_file.skel.h"
>> +#include "bpf_iter_task_vma.skel.h"
>> #include "bpf_iter_task_btf.skel.h"
>> #include "bpf_iter_tcp4.skel.h"
>> #include "bpf_iter_tcp6.skel.h"
>> @@ -64,6 +65,22 @@ static void do_dummy_read(struct bpf_program *prog)
>> bpf_link__destroy(link);
>> }
>>
> [...]
>> diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c b/tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c
>> new file mode 100644
>> index 0000000000000..d60b5b38cb396
>> --- /dev/null
>> +++ b/tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c
>> @@ -0,0 +1,55 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/* Copyright (c) 2020 Facebook */
>> +#include "bpf_iter.h"
>> +#include <bpf/bpf_helpers.h>
>> +#include <bpf/bpf_tracing.h>
>> +
>> +char _license[] SEC("license") = "GPL";
>> +
>> +/* Copied from mm.h */
>> +#define VM_READ 0x00000001
>> +#define VM_WRITE 0x00000002
>> +#define VM_EXEC 0x00000004
>> +#define VM_MAYSHARE 0x00000080
>> +
>> +/* Copied from kdev_t.h */
>> +#define MINORBITS 20
>> +#define MINORMASK ((1U << MINORBITS) - 1)
>> +#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
>> +#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
>> +
>> +#define D_PATH_BUF_SIZE 1024
>> +char d_path_buf[D_PATH_BUF_SIZE];
>> +__u32 pid;
>> +
>> +SEC("iter.s/task_vma") int proc_maps(struct bpf_iter__task_vma *ctx)
>> +{
>> + struct __vm_area_struct *vma = ctx->vma;
>> + struct seq_file *seq = ctx->meta->seq;
>> + struct task_struct *task = ctx->task;
>> + struct file *file = ctx->file;
>> + char perm_str[] = "----";
>> +
>> + if (task == (void *)0 || vma == (void *)0 || task->pid != pid)
>> + return 0;
>> +
>> + perm_str[0] = (vma->flags & VM_READ) ? 'r' : '-';
>> + perm_str[1] = (vma->flags & VM_WRITE) ? 'w' : '-';
>> + perm_str[1] = (vma->flags & VM_EXEC) ? 'x' : '-';
>
> typo here? The above should be perm_str[2].
Good catch! Fixing it in the next version.
Song
[...]
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2020-12-15 21:01 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-12 2:48 [PATCH bpf-next 0/4] introduce bpf_iter for task_vma Song Liu
2020-12-12 2:48 ` [PATCH bpf-next 1/4] bpf: introduce task_vma bpf_iter Song Liu
2020-12-14 7:13 ` Yonghong Song
2020-12-14 22:31 ` Song Liu
2020-12-15 19:46 ` Yonghong Song
2020-12-12 2:48 ` [PATCH bpf-next 2/4] bpf: allow bpf_d_path in sleepable bpf_iter program Song Liu
2020-12-12 2:48 ` [PATCH bpf-next 3/4] libbpf: introduce section "iter.s/" for " Song Liu
2020-12-12 2:48 ` [PATCH bpf-next 4/4] selftests/bpf: add test for bpf_iter_task_vma Song Liu
2020-12-15 20:21 ` Yonghong Song
2020-12-15 20:59 ` Song Liu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).