tools/bpftool: Show info for processes holding BPF map/prog/link/btf FDs
Add bpf_iter-based way to find all the processes that hold open FDs against
BPF object (map, prog, link, btf). bpftool always attempts to discover this,
but will silently give up if kernel doesn't yet support bpf_iter BPF programs.
Process name and PID are emitted for each process (task group).
Sample output for each of 4 BPF objects:
$ sudo ./bpftool prog show
2694: cgroup_device tag 8c42dee26e8cd4c2 gpl
loaded_at 2020-06-16T15:34:32-0700 uid 0
xlated 648B jited 409B memlock 4096B
pids systemd(1)
2907: cgroup_skb name egress tag 9ad187367cf2b9e8 gpl
loaded_at 2020-06-16T18:06:54-0700 uid 0
xlated 48B jited 59B memlock 4096B map_ids 2436
btf_id 1202
pids test_progs(2238417), test_progs(2238445)
$ sudo ./bpftool map show
2436: array name test_cgr.bss flags 0x400
key 4B value 8B max_entries 1 memlock 8192B
btf_id 1202
pids test_progs(2238417), test_progs(2238445)
2445: array name pid_iter.rodata flags 0x480
key 4B value 4B max_entries 1 memlock 8192B
btf_id 1214 frozen
pids bpftool(2239612)
$ sudo ./bpftool link show
61: cgroup prog 2908
cgroup_id 375301 attach_type egress
pids test_progs(2238417), test_progs(2238445)
62: cgroup prog 2908
cgroup_id 375344 attach_type egress
pids test_progs(2238417), test_progs(2238445)
$ sudo ./bpftool btf show
1202: size 1527B prog_ids 2908,2907 map_ids 2436
pids test_progs(2238417), test_progs(2238445)
1242: size 34684B
pids bpftool(2258892)
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20200619231703.738941-9-andriin@fb.com
2020-06-20 07:17:02 +08:00
|
|
|
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
|
|
|
/* Copyright (C) 2020 Facebook */
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <bpf/bpf.h>
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
#include "skeleton/pid_iter.h"
|
|
|
|
|
|
|
|
#ifdef BPFTOOL_WITHOUT_SKELETONS
|
|
|
|
|
|
|
|
int build_obj_refs_table(struct obj_refs_table *table, enum bpf_obj_type type)
|
|
|
|
{
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
void delete_obj_refs_table(struct obj_refs_table *table) {}
|
2020-07-03 12:31:59 +08:00
|
|
|
void emit_obj_refs_plain(struct obj_refs_table *table, __u32 id, const char *prefix) {}
|
bpf: Fix another bpftool segfault without skeleton code enabled
emit_obj_refs_json needs to added the same as with emit_obj_refs_plain
to prevent segfaults, similar to Commit "8ae4121bd89e bpf: Fix bpftool
without skeleton code enabled"). See the error below:
# ./bpftool -p prog
{
"error": "bpftool built without PID iterator support"
},[{
"id": 2,
"type": "cgroup_skb",
"tag": "7be49e3934a125ba",
"gpl_compatible": true,
"loaded_at": 1594052789,
"uid": 0,
"bytes_xlated": 296,
"jited": true,
"bytes_jited": 203,
"bytes_memlock": 4096,
"map_ids": [2,3
Segmentation fault (core dumped)
The same happens for ./bpftool -p map, as well as ./bpftool -j prog/map.
Fixes: d53dee3fe013 ("tools/bpftool: Show info for processes holding BPF map/prog/link/btf FDs")
Signed-off-by: Louis Peens <louis.peens@netronome.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20200708110827.7673-1-louis.peens@netronome.com
2020-07-08 19:08:27 +08:00
|
|
|
void emit_obj_refs_json(struct obj_refs_table *table, __u32 id, json_writer_t *json_writer) {}
|
tools/bpftool: Show info for processes holding BPF map/prog/link/btf FDs
Add bpf_iter-based way to find all the processes that hold open FDs against
BPF object (map, prog, link, btf). bpftool always attempts to discover this,
but will silently give up if kernel doesn't yet support bpf_iter BPF programs.
Process name and PID are emitted for each process (task group).
Sample output for each of 4 BPF objects:
$ sudo ./bpftool prog show
2694: cgroup_device tag 8c42dee26e8cd4c2 gpl
loaded_at 2020-06-16T15:34:32-0700 uid 0
xlated 648B jited 409B memlock 4096B
pids systemd(1)
2907: cgroup_skb name egress tag 9ad187367cf2b9e8 gpl
loaded_at 2020-06-16T18:06:54-0700 uid 0
xlated 48B jited 59B memlock 4096B map_ids 2436
btf_id 1202
pids test_progs(2238417), test_progs(2238445)
$ sudo ./bpftool map show
2436: array name test_cgr.bss flags 0x400
key 4B value 8B max_entries 1 memlock 8192B
btf_id 1202
pids test_progs(2238417), test_progs(2238445)
2445: array name pid_iter.rodata flags 0x480
key 4B value 4B max_entries 1 memlock 8192B
btf_id 1214 frozen
pids bpftool(2239612)
$ sudo ./bpftool link show
61: cgroup prog 2908
cgroup_id 375301 attach_type egress
pids test_progs(2238417), test_progs(2238445)
62: cgroup prog 2908
cgroup_id 375344 attach_type egress
pids test_progs(2238417), test_progs(2238445)
$ sudo ./bpftool btf show
1202: size 1527B prog_ids 2908,2907 map_ids 2436
pids test_progs(2238417), test_progs(2238445)
1242: size 34684B
pids bpftool(2258892)
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20200619231703.738941-9-andriin@fb.com
2020-06-20 07:17:02 +08:00
|
|
|
|
|
|
|
#else /* BPFTOOL_WITHOUT_SKELETONS */
|
|
|
|
|
|
|
|
#include "pid_iter.skel.h"
|
|
|
|
|
|
|
|
static void add_ref(struct obj_refs_table *table, struct pid_iter_entry *e)
|
|
|
|
{
|
|
|
|
struct obj_refs *refs;
|
|
|
|
struct obj_ref *ref;
|
|
|
|
void *tmp;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
hash_for_each_possible(table->table, refs, node, e->id) {
|
|
|
|
if (refs->id != e->id)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (i = 0; i < refs->ref_cnt; i++) {
|
|
|
|
if (refs->refs[i].pid == e->pid)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = realloc(refs->refs, (refs->ref_cnt + 1) * sizeof(*ref));
|
|
|
|
if (!tmp) {
|
|
|
|
p_err("failed to re-alloc memory for ID %u, PID %d, COMM %s...",
|
|
|
|
e->id, e->pid, e->comm);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
refs->refs = tmp;
|
|
|
|
ref = &refs->refs[refs->ref_cnt];
|
|
|
|
ref->pid = e->pid;
|
|
|
|
memcpy(ref->comm, e->comm, sizeof(ref->comm));
|
|
|
|
refs->ref_cnt++;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* new ref */
|
|
|
|
refs = calloc(1, sizeof(*refs));
|
|
|
|
if (!refs) {
|
|
|
|
p_err("failed to alloc memory for ID %u, PID %d, COMM %s...",
|
|
|
|
e->id, e->pid, e->comm);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
refs->id = e->id;
|
|
|
|
refs->refs = malloc(sizeof(*refs->refs));
|
|
|
|
if (!refs->refs) {
|
|
|
|
free(refs);
|
|
|
|
p_err("failed to alloc memory for ID %u, PID %d, COMM %s...",
|
|
|
|
e->id, e->pid, e->comm);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ref = &refs->refs[0];
|
|
|
|
ref->pid = e->pid;
|
|
|
|
memcpy(ref->comm, e->comm, sizeof(ref->comm));
|
|
|
|
refs->ref_cnt = 1;
|
|
|
|
hash_add(table->table, &refs->node, e->id);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __printf(2, 0)
|
|
|
|
libbpf_print_none(__maybe_unused enum libbpf_print_level level,
|
|
|
|
__maybe_unused const char *format,
|
|
|
|
__maybe_unused va_list args)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int build_obj_refs_table(struct obj_refs_table *table, enum bpf_obj_type type)
|
|
|
|
{
|
|
|
|
char buf[4096];
|
|
|
|
struct pid_iter_bpf *skel;
|
|
|
|
struct pid_iter_entry *e;
|
|
|
|
int err, ret, fd = -1, i;
|
|
|
|
libbpf_print_fn_t default_print;
|
|
|
|
|
|
|
|
hash_init(table->table);
|
|
|
|
set_max_rlimit();
|
|
|
|
|
|
|
|
skel = pid_iter_bpf__open();
|
|
|
|
if (!skel) {
|
|
|
|
p_err("failed to open PID iterator skeleton");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
skel->rodata->obj_type = type;
|
|
|
|
|
|
|
|
/* we don't want output polluted with libbpf errors if bpf_iter is not
|
|
|
|
* supported
|
|
|
|
*/
|
|
|
|
default_print = libbpf_set_print(libbpf_print_none);
|
|
|
|
err = pid_iter_bpf__load(skel);
|
|
|
|
libbpf_set_print(default_print);
|
|
|
|
if (err) {
|
|
|
|
/* too bad, kernel doesn't support BPF iterators yet */
|
|
|
|
err = 0;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
err = pid_iter_bpf__attach(skel);
|
|
|
|
if (err) {
|
|
|
|
/* if we loaded above successfully, attach has to succeed */
|
|
|
|
p_err("failed to attach PID iterator: %d", err);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
fd = bpf_iter_create(bpf_link__fd(skel->links.iter));
|
|
|
|
if (fd < 0) {
|
|
|
|
err = -errno;
|
|
|
|
p_err("failed to create PID iterator session: %d", err);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
ret = read(fd, buf, sizeof(buf));
|
|
|
|
if (ret < 0) {
|
|
|
|
err = -errno;
|
|
|
|
p_err("failed to read PID iterator output: %d", err);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (ret == 0)
|
|
|
|
break;
|
|
|
|
if (ret % sizeof(*e)) {
|
|
|
|
err = -EINVAL;
|
|
|
|
p_err("invalid PID iterator output format");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
ret /= sizeof(*e);
|
|
|
|
|
|
|
|
e = (void *)buf;
|
|
|
|
for (i = 0; i < ret; i++, e++) {
|
|
|
|
add_ref(table, e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
err = 0;
|
|
|
|
out:
|
|
|
|
if (fd >= 0)
|
|
|
|
close(fd);
|
|
|
|
pid_iter_bpf__destroy(skel);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
void delete_obj_refs_table(struct obj_refs_table *table)
|
|
|
|
{
|
|
|
|
struct obj_refs *refs;
|
|
|
|
struct hlist_node *tmp;
|
|
|
|
unsigned int bkt;
|
|
|
|
|
|
|
|
hash_for_each_safe(table->table, bkt, tmp, refs, node) {
|
|
|
|
hash_del(&refs->node);
|
|
|
|
free(refs->refs);
|
|
|
|
free(refs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-24 05:36:00 +08:00
|
|
|
void emit_obj_refs_json(struct obj_refs_table *table, __u32 id,
|
|
|
|
json_writer_t *json_writer)
|
tools/bpftool: Show info for processes holding BPF map/prog/link/btf FDs
Add bpf_iter-based way to find all the processes that hold open FDs against
BPF object (map, prog, link, btf). bpftool always attempts to discover this,
but will silently give up if kernel doesn't yet support bpf_iter BPF programs.
Process name and PID are emitted for each process (task group).
Sample output for each of 4 BPF objects:
$ sudo ./bpftool prog show
2694: cgroup_device tag 8c42dee26e8cd4c2 gpl
loaded_at 2020-06-16T15:34:32-0700 uid 0
xlated 648B jited 409B memlock 4096B
pids systemd(1)
2907: cgroup_skb name egress tag 9ad187367cf2b9e8 gpl
loaded_at 2020-06-16T18:06:54-0700 uid 0
xlated 48B jited 59B memlock 4096B map_ids 2436
btf_id 1202
pids test_progs(2238417), test_progs(2238445)
$ sudo ./bpftool map show
2436: array name test_cgr.bss flags 0x400
key 4B value 8B max_entries 1 memlock 8192B
btf_id 1202
pids test_progs(2238417), test_progs(2238445)
2445: array name pid_iter.rodata flags 0x480
key 4B value 4B max_entries 1 memlock 8192B
btf_id 1214 frozen
pids bpftool(2239612)
$ sudo ./bpftool link show
61: cgroup prog 2908
cgroup_id 375301 attach_type egress
pids test_progs(2238417), test_progs(2238445)
62: cgroup prog 2908
cgroup_id 375344 attach_type egress
pids test_progs(2238417), test_progs(2238445)
$ sudo ./bpftool btf show
1202: size 1527B prog_ids 2908,2907 map_ids 2436
pids test_progs(2238417), test_progs(2238445)
1242: size 34684B
pids bpftool(2258892)
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20200619231703.738941-9-andriin@fb.com
2020-06-20 07:17:02 +08:00
|
|
|
{
|
|
|
|
struct obj_refs *refs;
|
|
|
|
struct obj_ref *ref;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (hash_empty(table->table))
|
|
|
|
return;
|
|
|
|
|
|
|
|
hash_for_each_possible(table->table, refs, node, id) {
|
|
|
|
if (refs->id != id)
|
|
|
|
continue;
|
|
|
|
if (refs->ref_cnt == 0)
|
|
|
|
break;
|
|
|
|
|
2020-06-24 05:36:00 +08:00
|
|
|
jsonw_name(json_writer, "pids");
|
|
|
|
jsonw_start_array(json_writer);
|
tools/bpftool: Show info for processes holding BPF map/prog/link/btf FDs
Add bpf_iter-based way to find all the processes that hold open FDs against
BPF object (map, prog, link, btf). bpftool always attempts to discover this,
but will silently give up if kernel doesn't yet support bpf_iter BPF programs.
Process name and PID are emitted for each process (task group).
Sample output for each of 4 BPF objects:
$ sudo ./bpftool prog show
2694: cgroup_device tag 8c42dee26e8cd4c2 gpl
loaded_at 2020-06-16T15:34:32-0700 uid 0
xlated 648B jited 409B memlock 4096B
pids systemd(1)
2907: cgroup_skb name egress tag 9ad187367cf2b9e8 gpl
loaded_at 2020-06-16T18:06:54-0700 uid 0
xlated 48B jited 59B memlock 4096B map_ids 2436
btf_id 1202
pids test_progs(2238417), test_progs(2238445)
$ sudo ./bpftool map show
2436: array name test_cgr.bss flags 0x400
key 4B value 8B max_entries 1 memlock 8192B
btf_id 1202
pids test_progs(2238417), test_progs(2238445)
2445: array name pid_iter.rodata flags 0x480
key 4B value 4B max_entries 1 memlock 8192B
btf_id 1214 frozen
pids bpftool(2239612)
$ sudo ./bpftool link show
61: cgroup prog 2908
cgroup_id 375301 attach_type egress
pids test_progs(2238417), test_progs(2238445)
62: cgroup prog 2908
cgroup_id 375344 attach_type egress
pids test_progs(2238417), test_progs(2238445)
$ sudo ./bpftool btf show
1202: size 1527B prog_ids 2908,2907 map_ids 2436
pids test_progs(2238417), test_progs(2238445)
1242: size 34684B
pids bpftool(2258892)
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20200619231703.738941-9-andriin@fb.com
2020-06-20 07:17:02 +08:00
|
|
|
for (i = 0; i < refs->ref_cnt; i++) {
|
|
|
|
ref = &refs->refs[i];
|
2020-06-24 05:36:00 +08:00
|
|
|
jsonw_start_object(json_writer);
|
|
|
|
jsonw_int_field(json_writer, "pid", ref->pid);
|
|
|
|
jsonw_string_field(json_writer, "comm", ref->comm);
|
|
|
|
jsonw_end_object(json_writer);
|
tools/bpftool: Show info for processes holding BPF map/prog/link/btf FDs
Add bpf_iter-based way to find all the processes that hold open FDs against
BPF object (map, prog, link, btf). bpftool always attempts to discover this,
but will silently give up if kernel doesn't yet support bpf_iter BPF programs.
Process name and PID are emitted for each process (task group).
Sample output for each of 4 BPF objects:
$ sudo ./bpftool prog show
2694: cgroup_device tag 8c42dee26e8cd4c2 gpl
loaded_at 2020-06-16T15:34:32-0700 uid 0
xlated 648B jited 409B memlock 4096B
pids systemd(1)
2907: cgroup_skb name egress tag 9ad187367cf2b9e8 gpl
loaded_at 2020-06-16T18:06:54-0700 uid 0
xlated 48B jited 59B memlock 4096B map_ids 2436
btf_id 1202
pids test_progs(2238417), test_progs(2238445)
$ sudo ./bpftool map show
2436: array name test_cgr.bss flags 0x400
key 4B value 8B max_entries 1 memlock 8192B
btf_id 1202
pids test_progs(2238417), test_progs(2238445)
2445: array name pid_iter.rodata flags 0x480
key 4B value 4B max_entries 1 memlock 8192B
btf_id 1214 frozen
pids bpftool(2239612)
$ sudo ./bpftool link show
61: cgroup prog 2908
cgroup_id 375301 attach_type egress
pids test_progs(2238417), test_progs(2238445)
62: cgroup prog 2908
cgroup_id 375344 attach_type egress
pids test_progs(2238417), test_progs(2238445)
$ sudo ./bpftool btf show
1202: size 1527B prog_ids 2908,2907 map_ids 2436
pids test_progs(2238417), test_progs(2238445)
1242: size 34684B
pids bpftool(2258892)
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20200619231703.738941-9-andriin@fb.com
2020-06-20 07:17:02 +08:00
|
|
|
}
|
2020-06-24 05:36:00 +08:00
|
|
|
jsonw_end_array(json_writer);
|
tools/bpftool: Show info for processes holding BPF map/prog/link/btf FDs
Add bpf_iter-based way to find all the processes that hold open FDs against
BPF object (map, prog, link, btf). bpftool always attempts to discover this,
but will silently give up if kernel doesn't yet support bpf_iter BPF programs.
Process name and PID are emitted for each process (task group).
Sample output for each of 4 BPF objects:
$ sudo ./bpftool prog show
2694: cgroup_device tag 8c42dee26e8cd4c2 gpl
loaded_at 2020-06-16T15:34:32-0700 uid 0
xlated 648B jited 409B memlock 4096B
pids systemd(1)
2907: cgroup_skb name egress tag 9ad187367cf2b9e8 gpl
loaded_at 2020-06-16T18:06:54-0700 uid 0
xlated 48B jited 59B memlock 4096B map_ids 2436
btf_id 1202
pids test_progs(2238417), test_progs(2238445)
$ sudo ./bpftool map show
2436: array name test_cgr.bss flags 0x400
key 4B value 8B max_entries 1 memlock 8192B
btf_id 1202
pids test_progs(2238417), test_progs(2238445)
2445: array name pid_iter.rodata flags 0x480
key 4B value 4B max_entries 1 memlock 8192B
btf_id 1214 frozen
pids bpftool(2239612)
$ sudo ./bpftool link show
61: cgroup prog 2908
cgroup_id 375301 attach_type egress
pids test_progs(2238417), test_progs(2238445)
62: cgroup prog 2908
cgroup_id 375344 attach_type egress
pids test_progs(2238417), test_progs(2238445)
$ sudo ./bpftool btf show
1202: size 1527B prog_ids 2908,2907 map_ids 2436
pids test_progs(2238417), test_progs(2238445)
1242: size 34684B
pids bpftool(2258892)
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20200619231703.738941-9-andriin@fb.com
2020-06-20 07:17:02 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void emit_obj_refs_plain(struct obj_refs_table *table, __u32 id, const char *prefix)
|
|
|
|
{
|
|
|
|
struct obj_refs *refs;
|
|
|
|
struct obj_ref *ref;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (hash_empty(table->table))
|
|
|
|
return;
|
|
|
|
|
|
|
|
hash_for_each_possible(table->table, refs, node, id) {
|
|
|
|
if (refs->id != id)
|
|
|
|
continue;
|
|
|
|
if (refs->ref_cnt == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
printf("%s", prefix);
|
|
|
|
for (i = 0; i < refs->ref_cnt; i++) {
|
|
|
|
ref = &refs->refs[i];
|
|
|
|
printf("%s%s(%d)", i == 0 ? "" : ", ", ref->comm, ref->pid);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|