Commit 596f5fb2 authored by Stanislav Fomichev's avatar Stanislav Fomichev Committed by Alexei Starovoitov
Browse files

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: default avatarQuentin Monnet <quentin@isovalent.com>
Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
Signed-off-by: default avatarStanislav Fomichev <sdf@google.com>
Link: https://lore.kernel.org/r/20220628174314.1216643-11-sdf@google.com


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent a4b2f3cf
Loading
Loading
Loading
Loading
+87 −22
Original line number Diff line number Diff line
@@ -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,22 +198,31 @@ 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;

	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";
@@ -175,9 +238,9 @@ static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
			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);