bpftool: implement cgroup tree for BPF_LSM_CGROUP

$ bpftool --nomount prog loadall $KDIR/tools/testing/selftests/bpf/lsm_cgroup.o /sys/fs/bpf/x
$ bpftool cgroup attach /sys/fs/cgroup lsm_cgroup pinned /sys/fs/bpf/x/socket_alloc
$ bpftool cgroup attach /sys/fs/cgroup lsm_cgroup pinned /sys/fs/bpf/x/socket_bind
$ bpftool cgroup attach /sys/fs/cgroup lsm_cgroup pinned /sys/fs/bpf/x/socket_clone
$ bpftool cgroup attach /sys/fs/cgroup lsm_cgroup pinned /sys/fs/bpf/x/socket_post_create
$ bpftool cgroup tree
CgroupPath
ID       AttachType      AttachFlags     Name
/sys/fs/cgroup
6        lsm_cgroup                      socket_post_create bpf_lsm_socket_post_create
8        lsm_cgroup                      socket_bind     bpf_lsm_socket_bind
10       lsm_cgroup                      socket_alloc    bpf_lsm_sk_alloc_security
11       lsm_cgroup                      socket_clone    bpf_lsm_inet_csk_clone

$ bpftool cgroup detach /sys/fs/cgroup lsm_cgroup pinned /sys/fs/bpf/x/socket_post_create
$ bpftool cgroup tree
CgroupPath
ID       AttachType      AttachFlags     Name
/sys/fs/cgroup
8        lsm_cgroup                      socket_bind     bpf_lsm_socket_bind
10       lsm_cgroup                      socket_alloc    bpf_lsm_sk_alloc_security
11       lsm_cgroup                      socket_clone    bpf_lsm_inet_csk_clone

Reviewed-by: Quentin Monnet <quentin@isovalent.com>
Acked-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Stanislav Fomichev <sdf@google.com>
Link: https://lore.kernel.org/r/20220628174314.1216643-11-sdf@google.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Stanislav Fomichev 2022-06-28 10:43:13 -07:00 committed by Alexei Starovoitov
parent a4b2f3cf69
commit 596f5fb2ea

View File

@ -15,6 +15,7 @@
#include <unistd.h>
#include <bpf/bpf.h>
#include <bpf/btf.h>
#include "main.h"
@ -36,6 +37,8 @@
" cgroup_inet_sock_release }"
static unsigned int query_flags;
static struct btf *btf_vmlinux;
static __u32 btf_vmlinux_id;
static enum bpf_attach_type parse_attach_type(const char *str)
{
@ -64,11 +67,38 @@ static enum bpf_attach_type parse_attach_type(const char *str)
return __MAX_BPF_ATTACH_TYPE;
}
static void guess_vmlinux_btf_id(__u32 attach_btf_obj_id)
{
struct bpf_btf_info btf_info = {};
__u32 btf_len = sizeof(btf_info);
char name[16] = {};
int err;
int fd;
btf_info.name = ptr_to_u64(name);
btf_info.name_len = sizeof(name);
fd = bpf_btf_get_fd_by_id(attach_btf_obj_id);
if (fd < 0)
return;
err = bpf_obj_get_info_by_fd(fd, &btf_info, &btf_len);
if (err)
goto out;
if (btf_info.kernel_btf && strncmp(name, "vmlinux", sizeof(name)) == 0)
btf_vmlinux_id = btf_info.id;
out:
close(fd);
}
static int show_bpf_prog(int id, enum bpf_attach_type attach_type,
const char *attach_flags_str,
int level)
{
char prog_name[MAX_PROG_FULL_NAME];
const char *attach_btf_name = NULL;
struct bpf_prog_info info = {};
const char *attach_type_str;
__u32 info_len = sizeof(info);
@ -84,6 +114,20 @@ static int show_bpf_prog(int id, enum bpf_attach_type attach_type,
}
attach_type_str = libbpf_bpf_attach_type_str(attach_type);
if (btf_vmlinux) {
if (!btf_vmlinux_id)
guess_vmlinux_btf_id(info.attach_btf_obj_id);
if (btf_vmlinux_id == info.attach_btf_obj_id &&
info.attach_btf_id < btf__type_cnt(btf_vmlinux)) {
const struct btf_type *t =
btf__type_by_id(btf_vmlinux, info.attach_btf_id);
attach_btf_name =
btf__name_by_offset(btf_vmlinux, t->name_off);
}
}
get_prog_full_name(&info, prog_fd, prog_name, sizeof(prog_name));
if (json_output) {
jsonw_start_object(json_wtr);
@ -95,6 +139,10 @@ static int show_bpf_prog(int id, enum bpf_attach_type attach_type,
jsonw_string_field(json_wtr, "attach_flags",
attach_flags_str);
jsonw_string_field(json_wtr, "name", prog_name);
if (attach_btf_name)
jsonw_string_field(json_wtr, "attach_btf_name", attach_btf_name);
jsonw_uint_field(json_wtr, "attach_btf_obj_id", info.attach_btf_obj_id);
jsonw_uint_field(json_wtr, "attach_btf_id", info.attach_btf_id);
jsonw_end_object(json_wtr);
} else {
printf("%s%-8u ", level ? " " : "", info.id);
@ -102,7 +150,13 @@ static int show_bpf_prog(int id, enum bpf_attach_type attach_type,
printf("%-15s", attach_type_str);
else
printf("type %-10u", attach_type);
printf(" %-15s %-15s\n", attach_flags_str, prog_name);
printf(" %-15s %-15s", attach_flags_str, prog_name);
if (attach_btf_name)
printf(" %-15s", attach_btf_name);
else if (info.attach_btf_id)
printf(" attach_btf_obj_id=%d attach_btf_id=%d",
info.attach_btf_obj_id, info.attach_btf_id);
printf("\n");
}
close(prog_fd);
@ -144,40 +198,49 @@ static int cgroup_has_attached_progs(int cgroup_fd)
static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
int level)
{
LIBBPF_OPTS(bpf_prog_query_opts, p);
__u32 prog_attach_flags[1024] = {0};
const char *attach_flags_str;
__u32 prog_ids[1024] = {0};
__u32 prog_cnt, iter;
__u32 attach_flags;
char buf[32];
__u32 iter;
int ret;
prog_cnt = ARRAY_SIZE(prog_ids);
ret = bpf_prog_query(cgroup_fd, type, query_flags, &attach_flags,
prog_ids, &prog_cnt);
p.query_flags = query_flags;
p.prog_cnt = ARRAY_SIZE(prog_ids);
p.prog_ids = prog_ids;
p.prog_attach_flags = prog_attach_flags;
ret = bpf_prog_query_opts(cgroup_fd, type, &p);
if (ret)
return ret;
if (prog_cnt == 0)
if (p.prog_cnt == 0)
return 0;
switch (attach_flags) {
case BPF_F_ALLOW_MULTI:
attach_flags_str = "multi";
break;
case BPF_F_ALLOW_OVERRIDE:
attach_flags_str = "override";
break;
case 0:
attach_flags_str = "";
break;
default:
snprintf(buf, sizeof(buf), "unknown(%x)", attach_flags);
attach_flags_str = buf;
}
for (iter = 0; iter < p.prog_cnt; iter++) {
__u32 attach_flags;
attach_flags = prog_attach_flags[iter] ?: p.attach_flags;
switch (attach_flags) {
case BPF_F_ALLOW_MULTI:
attach_flags_str = "multi";
break;
case BPF_F_ALLOW_OVERRIDE:
attach_flags_str = "override";
break;
case 0:
attach_flags_str = "";
break;
default:
snprintf(buf, sizeof(buf), "unknown(%x)", attach_flags);
attach_flags_str = buf;
}
for (iter = 0; iter < prog_cnt; iter++)
show_bpf_prog(prog_ids[iter], type,
attach_flags_str, level);
}
return 0;
}
@ -233,6 +296,7 @@ static int do_show(int argc, char **argv)
printf("%-8s %-15s %-15s %-15s\n", "ID", "AttachType",
"AttachFlags", "Name");
btf_vmlinux = libbpf_find_kernel_btf();
for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
/*
* Not all attach types may be supported, so it's expected,
@ -296,6 +360,7 @@ static int do_show_tree_fn(const char *fpath, const struct stat *sb,
printf("%s\n", fpath);
}
btf_vmlinux = libbpf_find_kernel_btf();
for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++)
show_attached_bpf_progs(cgroup_fd, type, ftw->level);