2018-12-13 11:59:26 +08:00
|
|
|
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
2017-12-13 23:18:54 +08:00
|
|
|
// Copyright (C) 2017 Facebook
|
|
|
|
// Author: Roman Gushchin <guro@fb.com>
|
|
|
|
|
2018-07-07 05:28:14 +08:00
|
|
|
#define _XOPEN_SOURCE 500
|
|
|
|
#include <errno.h>
|
2017-12-13 23:18:54 +08:00
|
|
|
#include <fcntl.h>
|
2018-07-07 05:28:14 +08:00
|
|
|
#include <ftw.h>
|
|
|
|
#include <mntent.h>
|
|
|
|
#include <stdio.h>
|
2017-12-13 23:18:54 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2020-01-20 21:06:46 +08:00
|
|
|
#include <bpf/bpf.h>
|
2022-06-29 01:43:13 +08:00
|
|
|
#include <bpf/btf.h>
|
2017-12-13 23:18:54 +08:00
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
|
|
|
|
#define HELP_SPEC_ATTACH_FLAGS \
|
|
|
|
"ATTACH_FLAGS := { multi | override }"
|
|
|
|
|
bpftool: Use libbpf_bpf_attach_type_str
This change switches bpftool over to using the recently introduced
libbpf_bpf_attach_type_str function instead of maintaining its own
string representation for the bpf_attach_type enum.
Note that contrary to other enum types, the variant names that bpftool
maps bpf_attach_type to do not adhere a simple to follow rule. With
bpf_prog_type, for example, the textual representation can easily be
inferred by stripping the BPF_PROG_TYPE_ prefix and lowercasing the
remaining string. bpf_attach_type violates this rule for various
variants.
We decided to fix up this deficiency with this change, meaning that
bpftool uses the same textual representations as libbpf. Supporting
tests, completion scripts, and man pages have been adjusted accordingly.
However, we did add support for accepting (the now undocumented)
original attach type names when they are provided by users.
For the test (test_bpftool_synctypes.py), I have removed the enum
representation checks, because we no longer mirror the various enum
variant names in bpftool source code. For the man page, help text, and
completion script checks we are now using enum definitions from
uapi/linux/bpf.h as the source of truth directly.
Signed-off-by: Daniel Müller <deso@posteo.net>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20220523230428.3077108-10-deso@posteo.net
2022-05-24 07:04:25 +08:00
|
|
|
#define HELP_SPEC_ATTACH_TYPES \
|
|
|
|
" ATTACH_TYPE := { cgroup_inet_ingress | cgroup_inet_egress |\n" \
|
|
|
|
" cgroup_inet_sock_create | cgroup_sock_ops |\n" \
|
|
|
|
" cgroup_device | cgroup_inet4_bind |\n" \
|
|
|
|
" cgroup_inet6_bind | cgroup_inet4_post_bind |\n" \
|
|
|
|
" cgroup_inet6_post_bind | cgroup_inet4_connect |\n" \
|
|
|
|
" cgroup_inet6_connect | cgroup_inet4_getpeername |\n" \
|
|
|
|
" cgroup_inet6_getpeername | cgroup_inet4_getsockname |\n" \
|
|
|
|
" cgroup_inet6_getsockname | cgroup_udp4_sendmsg |\n" \
|
|
|
|
" cgroup_udp6_sendmsg | cgroup_udp4_recvmsg |\n" \
|
|
|
|
" cgroup_udp6_recvmsg | cgroup_sysctl |\n" \
|
|
|
|
" cgroup_getsockopt | cgroup_setsockopt |\n" \
|
|
|
|
" cgroup_inet_sock_release }"
|
2017-12-13 23:18:54 +08:00
|
|
|
|
2019-07-31 05:03:00 +08:00
|
|
|
static unsigned int query_flags;
|
2022-06-29 01:43:13 +08:00
|
|
|
static struct btf *btf_vmlinux;
|
|
|
|
static __u32 btf_vmlinux_id;
|
2019-07-31 05:03:00 +08:00
|
|
|
|
2017-12-13 23:18:54 +08:00
|
|
|
static enum bpf_attach_type parse_attach_type(const char *str)
|
|
|
|
{
|
bpftool: Use libbpf_bpf_attach_type_str
This change switches bpftool over to using the recently introduced
libbpf_bpf_attach_type_str function instead of maintaining its own
string representation for the bpf_attach_type enum.
Note that contrary to other enum types, the variant names that bpftool
maps bpf_attach_type to do not adhere a simple to follow rule. With
bpf_prog_type, for example, the textual representation can easily be
inferred by stripping the BPF_PROG_TYPE_ prefix and lowercasing the
remaining string. bpf_attach_type violates this rule for various
variants.
We decided to fix up this deficiency with this change, meaning that
bpftool uses the same textual representations as libbpf. Supporting
tests, completion scripts, and man pages have been adjusted accordingly.
However, we did add support for accepting (the now undocumented)
original attach type names when they are provided by users.
For the test (test_bpftool_synctypes.py), I have removed the enum
representation checks, because we no longer mirror the various enum
variant names in bpftool source code. For the man page, help text, and
completion script checks we are now using enum definitions from
uapi/linux/bpf.h as the source of truth directly.
Signed-off-by: Daniel Müller <deso@posteo.net>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20220523230428.3077108-10-deso@posteo.net
2022-05-24 07:04:25 +08:00
|
|
|
const char *attach_type_str;
|
2017-12-13 23:18:54 +08:00
|
|
|
enum bpf_attach_type type;
|
|
|
|
|
bpftool: Use libbpf_bpf_attach_type_str
This change switches bpftool over to using the recently introduced
libbpf_bpf_attach_type_str function instead of maintaining its own
string representation for the bpf_attach_type enum.
Note that contrary to other enum types, the variant names that bpftool
maps bpf_attach_type to do not adhere a simple to follow rule. With
bpf_prog_type, for example, the textual representation can easily be
inferred by stripping the BPF_PROG_TYPE_ prefix and lowercasing the
remaining string. bpf_attach_type violates this rule for various
variants.
We decided to fix up this deficiency with this change, meaning that
bpftool uses the same textual representations as libbpf. Supporting
tests, completion scripts, and man pages have been adjusted accordingly.
However, we did add support for accepting (the now undocumented)
original attach type names when they are provided by users.
For the test (test_bpftool_synctypes.py), I have removed the enum
representation checks, because we no longer mirror the various enum
variant names in bpftool source code. For the man page, help text, and
completion script checks we are now using enum definitions from
uapi/linux/bpf.h as the source of truth directly.
Signed-off-by: Daniel Müller <deso@posteo.net>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20220523230428.3077108-10-deso@posteo.net
2022-05-24 07:04:25 +08:00
|
|
|
for (type = 0; ; type++) {
|
|
|
|
attach_type_str = libbpf_bpf_attach_type_str(type);
|
|
|
|
if (!attach_type_str)
|
|
|
|
break;
|
|
|
|
if (!strcmp(str, attach_type_str))
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Also check traditionally used attach type strings. For these we keep
|
|
|
|
* allowing prefixed usage.
|
|
|
|
*/
|
|
|
|
for (type = 0; ; type++) {
|
|
|
|
attach_type_str = bpf_attach_type_input_str(type);
|
|
|
|
if (!attach_type_str)
|
|
|
|
break;
|
|
|
|
if (is_prefix(str, attach_type_str))
|
2017-12-13 23:18:54 +08:00
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
return __MAX_BPF_ATTACH_TYPE;
|
|
|
|
}
|
|
|
|
|
2022-06-29 01:43:13 +08:00
|
|
|
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;
|
|
|
|
|
2023-02-15 07:12:16 +08:00
|
|
|
err = bpf_btf_get_info_by_fd(fd, &btf_info, &btf_len);
|
2022-06-29 01:43:13 +08:00
|
|
|
if (err)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if (btf_info.kernel_btf && strncmp(name, "vmlinux", sizeof(name)) == 0)
|
|
|
|
btf_vmlinux_id = btf_info.id;
|
|
|
|
|
|
|
|
out:
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
2020-04-29 08:16:11 +08:00
|
|
|
static int show_bpf_prog(int id, enum bpf_attach_type attach_type,
|
2018-07-07 05:28:14 +08:00
|
|
|
const char *attach_flags_str,
|
|
|
|
int level)
|
2017-12-13 23:18:54 +08:00
|
|
|
{
|
2022-01-19 18:02:55 +08:00
|
|
|
char prog_name[MAX_PROG_FULL_NAME];
|
2022-06-29 01:43:13 +08:00
|
|
|
const char *attach_btf_name = NULL;
|
2017-12-13 23:18:54 +08:00
|
|
|
struct bpf_prog_info info = {};
|
bpftool: Use libbpf_bpf_attach_type_str
This change switches bpftool over to using the recently introduced
libbpf_bpf_attach_type_str function instead of maintaining its own
string representation for the bpf_attach_type enum.
Note that contrary to other enum types, the variant names that bpftool
maps bpf_attach_type to do not adhere a simple to follow rule. With
bpf_prog_type, for example, the textual representation can easily be
inferred by stripping the BPF_PROG_TYPE_ prefix and lowercasing the
remaining string. bpf_attach_type violates this rule for various
variants.
We decided to fix up this deficiency with this change, meaning that
bpftool uses the same textual representations as libbpf. Supporting
tests, completion scripts, and man pages have been adjusted accordingly.
However, we did add support for accepting (the now undocumented)
original attach type names when they are provided by users.
For the test (test_bpftool_synctypes.py), I have removed the enum
representation checks, because we no longer mirror the various enum
variant names in bpftool source code. For the man page, help text, and
completion script checks we are now using enum definitions from
uapi/linux/bpf.h as the source of truth directly.
Signed-off-by: Daniel Müller <deso@posteo.net>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20220523230428.3077108-10-deso@posteo.net
2022-05-24 07:04:25 +08:00
|
|
|
const char *attach_type_str;
|
2017-12-13 23:18:54 +08:00
|
|
|
__u32 info_len = sizeof(info);
|
|
|
|
int prog_fd;
|
|
|
|
|
|
|
|
prog_fd = bpf_prog_get_fd_by_id(id);
|
|
|
|
if (prog_fd < 0)
|
|
|
|
return -1;
|
|
|
|
|
2023-02-15 07:12:16 +08:00
|
|
|
if (bpf_prog_get_info_by_fd(prog_fd, &info, &info_len)) {
|
2017-12-13 23:18:54 +08:00
|
|
|
close(prog_fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
bpftool: Use libbpf_bpf_attach_type_str
This change switches bpftool over to using the recently introduced
libbpf_bpf_attach_type_str function instead of maintaining its own
string representation for the bpf_attach_type enum.
Note that contrary to other enum types, the variant names that bpftool
maps bpf_attach_type to do not adhere a simple to follow rule. With
bpf_prog_type, for example, the textual representation can easily be
inferred by stripping the BPF_PROG_TYPE_ prefix and lowercasing the
remaining string. bpf_attach_type violates this rule for various
variants.
We decided to fix up this deficiency with this change, meaning that
bpftool uses the same textual representations as libbpf. Supporting
tests, completion scripts, and man pages have been adjusted accordingly.
However, we did add support for accepting (the now undocumented)
original attach type names when they are provided by users.
For the test (test_bpftool_synctypes.py), I have removed the enum
representation checks, because we no longer mirror the various enum
variant names in bpftool source code. For the man page, help text, and
completion script checks we are now using enum definitions from
uapi/linux/bpf.h as the source of truth directly.
Signed-off-by: Daniel Müller <deso@posteo.net>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20220523230428.3077108-10-deso@posteo.net
2022-05-24 07:04:25 +08:00
|
|
|
attach_type_str = libbpf_bpf_attach_type_str(attach_type);
|
2022-06-29 01:43:13 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-19 18:02:55 +08:00
|
|
|
get_prog_full_name(&info, prog_fd, prog_name, sizeof(prog_name));
|
2017-12-13 23:18:54 +08:00
|
|
|
if (json_output) {
|
|
|
|
jsonw_start_object(json_wtr);
|
|
|
|
jsonw_uint_field(json_wtr, "id", info.id);
|
bpftool: Use libbpf_bpf_attach_type_str
This change switches bpftool over to using the recently introduced
libbpf_bpf_attach_type_str function instead of maintaining its own
string representation for the bpf_attach_type enum.
Note that contrary to other enum types, the variant names that bpftool
maps bpf_attach_type to do not adhere a simple to follow rule. With
bpf_prog_type, for example, the textual representation can easily be
inferred by stripping the BPF_PROG_TYPE_ prefix and lowercasing the
remaining string. bpf_attach_type violates this rule for various
variants.
We decided to fix up this deficiency with this change, meaning that
bpftool uses the same textual representations as libbpf. Supporting
tests, completion scripts, and man pages have been adjusted accordingly.
However, we did add support for accepting (the now undocumented)
original attach type names when they are provided by users.
For the test (test_bpftool_synctypes.py), I have removed the enum
representation checks, because we no longer mirror the various enum
variant names in bpftool source code. For the man page, help text, and
completion script checks we are now using enum definitions from
uapi/linux/bpf.h as the source of truth directly.
Signed-off-by: Daniel Müller <deso@posteo.net>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20220523230428.3077108-10-deso@posteo.net
2022-05-24 07:04:25 +08:00
|
|
|
if (attach_type_str)
|
|
|
|
jsonw_string_field(json_wtr, "attach_type", attach_type_str);
|
2020-04-29 08:16:11 +08:00
|
|
|
else
|
|
|
|
jsonw_uint_field(json_wtr, "attach_type", attach_type);
|
2022-09-21 18:46:03 +08:00
|
|
|
if (!(query_flags & BPF_F_QUERY_EFFECTIVE))
|
|
|
|
jsonw_string_field(json_wtr, "attach_flags", attach_flags_str);
|
2022-01-19 18:02:55 +08:00
|
|
|
jsonw_string_field(json_wtr, "name", prog_name);
|
2022-06-29 01:43:13 +08:00
|
|
|
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);
|
2017-12-13 23:18:54 +08:00
|
|
|
jsonw_end_object(json_wtr);
|
|
|
|
} else {
|
2020-04-29 08:16:11 +08:00
|
|
|
printf("%s%-8u ", level ? " " : "", info.id);
|
bpftool: Use libbpf_bpf_attach_type_str
This change switches bpftool over to using the recently introduced
libbpf_bpf_attach_type_str function instead of maintaining its own
string representation for the bpf_attach_type enum.
Note that contrary to other enum types, the variant names that bpftool
maps bpf_attach_type to do not adhere a simple to follow rule. With
bpf_prog_type, for example, the textual representation can easily be
inferred by stripping the BPF_PROG_TYPE_ prefix and lowercasing the
remaining string. bpf_attach_type violates this rule for various
variants.
We decided to fix up this deficiency with this change, meaning that
bpftool uses the same textual representations as libbpf. Supporting
tests, completion scripts, and man pages have been adjusted accordingly.
However, we did add support for accepting (the now undocumented)
original attach type names when they are provided by users.
For the test (test_bpftool_synctypes.py), I have removed the enum
representation checks, because we no longer mirror the various enum
variant names in bpftool source code. For the man page, help text, and
completion script checks we are now using enum definitions from
uapi/linux/bpf.h as the source of truth directly.
Signed-off-by: Daniel Müller <deso@posteo.net>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20220523230428.3077108-10-deso@posteo.net
2022-05-24 07:04:25 +08:00
|
|
|
if (attach_type_str)
|
|
|
|
printf("%-15s", attach_type_str);
|
2020-04-29 08:16:11 +08:00
|
|
|
else
|
|
|
|
printf("type %-10u", attach_type);
|
2022-09-21 18:46:03 +08:00
|
|
|
if (query_flags & BPF_F_QUERY_EFFECTIVE)
|
|
|
|
printf(" %-15s", prog_name);
|
|
|
|
else
|
|
|
|
printf(" %-15s %-15s", attach_flags_str, prog_name);
|
2022-06-29 01:43:13 +08:00
|
|
|
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");
|
2017-12-13 23:18:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
close(prog_fd);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-07-07 05:28:14 +08:00
|
|
|
static int count_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type)
|
|
|
|
{
|
|
|
|
__u32 prog_cnt = 0;
|
|
|
|
int ret;
|
|
|
|
|
2019-07-31 05:03:00 +08:00
|
|
|
ret = bpf_prog_query(cgroup_fd, type, query_flags, NULL,
|
|
|
|
NULL, &prog_cnt);
|
2018-07-07 05:28:14 +08:00
|
|
|
if (ret)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return prog_cnt;
|
|
|
|
}
|
|
|
|
|
2019-12-24 09:17:42 +08:00
|
|
|
static int cgroup_has_attached_progs(int cgroup_fd)
|
|
|
|
{
|
|
|
|
enum bpf_attach_type type;
|
|
|
|
bool no_prog = true;
|
|
|
|
|
|
|
|
for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
|
|
|
|
int count = count_attached_bpf_progs(cgroup_fd, type);
|
|
|
|
|
|
|
|
if (count < 0 && errno != EINVAL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (count > 0) {
|
|
|
|
no_prog = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return no_prog ? 0 : 1;
|
|
|
|
}
|
2022-09-21 18:46:03 +08:00
|
|
|
|
|
|
|
static int show_effective_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
|
|
|
|
int level)
|
|
|
|
{
|
|
|
|
LIBBPF_OPTS(bpf_prog_query_opts, p);
|
|
|
|
__u32 prog_ids[1024] = {0};
|
|
|
|
__u32 iter;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
p.query_flags = query_flags;
|
|
|
|
p.prog_cnt = ARRAY_SIZE(prog_ids);
|
|
|
|
p.prog_ids = prog_ids;
|
|
|
|
|
|
|
|
ret = bpf_prog_query_opts(cgroup_fd, type, &p);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (p.prog_cnt == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (iter = 0; iter < p.prog_cnt; iter++)
|
|
|
|
show_bpf_prog(prog_ids[iter], type, NULL, level);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-07-07 05:28:14 +08:00
|
|
|
static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
|
|
|
|
int level)
|
2017-12-13 23:18:54 +08:00
|
|
|
{
|
2022-06-29 01:43:13 +08:00
|
|
|
LIBBPF_OPTS(bpf_prog_query_opts, p);
|
|
|
|
__u32 prog_attach_flags[1024] = {0};
|
2019-08-14 19:37:24 +08:00
|
|
|
const char *attach_flags_str;
|
2017-12-13 23:18:54 +08:00
|
|
|
__u32 prog_ids[1024] = {0};
|
|
|
|
char buf[32];
|
2022-06-29 01:43:13 +08:00
|
|
|
__u32 iter;
|
2017-12-13 23:18:54 +08:00
|
|
|
int ret;
|
|
|
|
|
2022-06-29 01:43:13 +08:00
|
|
|
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);
|
2017-12-13 23:18:54 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2022-06-29 01:43:13 +08:00
|
|
|
if (p.prog_cnt == 0)
|
2017-12-13 23:18:54 +08:00
|
|
|
return 0;
|
|
|
|
|
2022-06-29 01:43:13 +08:00
|
|
|
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;
|
|
|
|
}
|
2017-12-13 23:18:54 +08:00
|
|
|
|
2020-04-29 08:16:11 +08:00
|
|
|
show_bpf_prog(prog_ids[iter], type,
|
2018-07-07 05:28:14 +08:00
|
|
|
attach_flags_str, level);
|
2022-06-29 01:43:13 +08:00
|
|
|
}
|
2017-12-13 23:18:54 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-09-21 18:46:03 +08:00
|
|
|
static int show_bpf_progs(int cgroup_fd, enum bpf_attach_type type,
|
|
|
|
int level)
|
|
|
|
{
|
|
|
|
return query_flags & BPF_F_QUERY_EFFECTIVE ?
|
|
|
|
show_effective_bpf_progs(cgroup_fd, type, level) :
|
|
|
|
show_attached_bpf_progs(cgroup_fd, type, level);
|
|
|
|
}
|
|
|
|
|
2018-01-03 06:48:35 +08:00
|
|
|
static int do_show(int argc, char **argv)
|
2017-12-13 23:18:54 +08:00
|
|
|
{
|
|
|
|
enum bpf_attach_type type;
|
2019-12-24 09:17:42 +08:00
|
|
|
int has_attached_progs;
|
2019-07-31 05:03:00 +08:00
|
|
|
const char *path;
|
2017-12-13 23:18:54 +08:00
|
|
|
int cgroup_fd;
|
|
|
|
int ret = -1;
|
|
|
|
|
2019-07-31 05:03:00 +08:00
|
|
|
query_flags = 0;
|
|
|
|
|
|
|
|
if (!REQ_ARGS(1))
|
|
|
|
return -1;
|
|
|
|
path = GET_ARG();
|
|
|
|
|
|
|
|
while (argc) {
|
|
|
|
if (is_prefix(*argv, "effective")) {
|
|
|
|
if (query_flags & BPF_F_QUERY_EFFECTIVE) {
|
|
|
|
p_err("duplicated argument: %s", *argv);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
query_flags |= BPF_F_QUERY_EFFECTIVE;
|
|
|
|
NEXT_ARG();
|
|
|
|
} else {
|
|
|
|
p_err("expected no more arguments, 'effective', got: '%s'?",
|
|
|
|
*argv);
|
|
|
|
return -1;
|
|
|
|
}
|
2017-12-13 23:18:54 +08:00
|
|
|
}
|
|
|
|
|
2019-07-31 05:03:00 +08:00
|
|
|
cgroup_fd = open(path, O_RDONLY);
|
2017-12-13 23:18:54 +08:00
|
|
|
if (cgroup_fd < 0) {
|
2019-07-31 05:03:00 +08:00
|
|
|
p_err("can't open cgroup %s", path);
|
2017-12-13 23:18:54 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2019-12-24 09:17:42 +08:00
|
|
|
has_attached_progs = cgroup_has_attached_progs(cgroup_fd);
|
|
|
|
if (has_attached_progs < 0) {
|
|
|
|
p_err("can't query bpf programs attached to %s: %s",
|
|
|
|
path, strerror(errno));
|
|
|
|
goto exit_cgroup;
|
|
|
|
} else if (!has_attached_progs) {
|
|
|
|
ret = 0;
|
|
|
|
goto exit_cgroup;
|
|
|
|
}
|
|
|
|
|
2017-12-13 23:18:54 +08:00
|
|
|
if (json_output)
|
|
|
|
jsonw_start_array(json_wtr);
|
2022-09-21 18:46:03 +08:00
|
|
|
else if (query_flags & BPF_F_QUERY_EFFECTIVE)
|
|
|
|
printf("%-8s %-15s %-15s\n", "ID", "AttachType", "Name");
|
2017-12-13 23:18:54 +08:00
|
|
|
else
|
|
|
|
printf("%-8s %-15s %-15s %-15s\n", "ID", "AttachType",
|
|
|
|
"AttachFlags", "Name");
|
|
|
|
|
2022-06-29 01:43:13 +08:00
|
|
|
btf_vmlinux = libbpf_find_kernel_btf();
|
2017-12-13 23:18:54 +08:00
|
|
|
for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
|
|
|
|
/*
|
|
|
|
* Not all attach types may be supported, so it's expected,
|
|
|
|
* that some requests will fail.
|
2018-01-03 06:48:35 +08:00
|
|
|
* If we were able to get the show for at least one
|
2017-12-13 23:18:54 +08:00
|
|
|
* attach type, let's return 0.
|
|
|
|
*/
|
2022-09-21 18:46:03 +08:00
|
|
|
if (show_bpf_progs(cgroup_fd, type, 0) == 0)
|
2017-12-13 23:18:54 +08:00
|
|
|
ret = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (json_output)
|
|
|
|
jsonw_end_array(json_wtr);
|
|
|
|
|
2019-12-24 09:17:42 +08:00
|
|
|
exit_cgroup:
|
2017-12-13 23:18:54 +08:00
|
|
|
close(cgroup_fd);
|
|
|
|
exit:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-07-07 05:28:14 +08:00
|
|
|
/*
|
|
|
|
* To distinguish nftw() errors and do_show_tree_fn() errors
|
|
|
|
* and avoid duplicating error messages, let's return -2
|
|
|
|
* from do_show_tree_fn() in case of error.
|
|
|
|
*/
|
|
|
|
#define NFTW_ERR -1
|
|
|
|
#define SHOW_TREE_FN_ERR -2
|
|
|
|
static int do_show_tree_fn(const char *fpath, const struct stat *sb,
|
|
|
|
int typeflag, struct FTW *ftw)
|
|
|
|
{
|
|
|
|
enum bpf_attach_type type;
|
2019-12-24 09:17:42 +08:00
|
|
|
int has_attached_progs;
|
2018-07-07 05:28:14 +08:00
|
|
|
int cgroup_fd;
|
|
|
|
|
|
|
|
if (typeflag != FTW_D)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
cgroup_fd = open(fpath, O_RDONLY);
|
|
|
|
if (cgroup_fd < 0) {
|
|
|
|
p_err("can't open cgroup %s: %s", fpath, strerror(errno));
|
|
|
|
return SHOW_TREE_FN_ERR;
|
|
|
|
}
|
|
|
|
|
2019-12-24 09:17:42 +08:00
|
|
|
has_attached_progs = cgroup_has_attached_progs(cgroup_fd);
|
|
|
|
if (has_attached_progs < 0) {
|
|
|
|
p_err("can't query bpf programs attached to %s: %s",
|
|
|
|
fpath, strerror(errno));
|
|
|
|
close(cgroup_fd);
|
|
|
|
return SHOW_TREE_FN_ERR;
|
|
|
|
} else if (!has_attached_progs) {
|
2018-07-07 05:28:14 +08:00
|
|
|
close(cgroup_fd);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (json_output) {
|
|
|
|
jsonw_start_object(json_wtr);
|
|
|
|
jsonw_string_field(json_wtr, "cgroup", fpath);
|
|
|
|
jsonw_name(json_wtr, "programs");
|
|
|
|
jsonw_start_array(json_wtr);
|
|
|
|
} else {
|
|
|
|
printf("%s\n", fpath);
|
|
|
|
}
|
|
|
|
|
2022-06-29 01:43:13 +08:00
|
|
|
btf_vmlinux = libbpf_find_kernel_btf();
|
2018-07-07 05:28:14 +08:00
|
|
|
for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++)
|
2022-09-21 18:46:03 +08:00
|
|
|
show_bpf_progs(cgroup_fd, type, ftw->level);
|
2018-07-07 05:28:14 +08:00
|
|
|
|
2019-04-12 21:29:35 +08:00
|
|
|
if (errno == EINVAL)
|
|
|
|
/* Last attach type does not support query.
|
|
|
|
* Do not report an error for this, especially because batch
|
|
|
|
* mode would stop processing commands.
|
|
|
|
*/
|
|
|
|
errno = 0;
|
|
|
|
|
2018-07-07 05:28:14 +08:00
|
|
|
if (json_output) {
|
|
|
|
jsonw_end_array(json_wtr);
|
|
|
|
jsonw_end_object(json_wtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
close(cgroup_fd);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *find_cgroup_root(void)
|
|
|
|
{
|
|
|
|
struct mntent *mnt;
|
|
|
|
FILE *f;
|
|
|
|
|
|
|
|
f = fopen("/proc/mounts", "r");
|
|
|
|
if (f == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
while ((mnt = getmntent(f))) {
|
|
|
|
if (strcmp(mnt->mnt_type, "cgroup2") == 0) {
|
|
|
|
fclose(f);
|
|
|
|
return strdup(mnt->mnt_dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(f);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int do_show_tree(int argc, char **argv)
|
|
|
|
{
|
2019-07-31 05:03:00 +08:00
|
|
|
char *cgroup_root, *cgroup_alloced = NULL;
|
2018-07-07 05:28:14 +08:00
|
|
|
int ret;
|
|
|
|
|
2019-07-31 05:03:00 +08:00
|
|
|
query_flags = 0;
|
|
|
|
|
|
|
|
if (!argc) {
|
|
|
|
cgroup_alloced = find_cgroup_root();
|
|
|
|
if (!cgroup_alloced) {
|
2018-07-07 05:28:14 +08:00
|
|
|
p_err("cgroup v2 isn't mounted");
|
|
|
|
return -1;
|
|
|
|
}
|
2019-07-31 05:03:00 +08:00
|
|
|
cgroup_root = cgroup_alloced;
|
|
|
|
} else {
|
|
|
|
cgroup_root = GET_ARG();
|
|
|
|
|
|
|
|
while (argc) {
|
|
|
|
if (is_prefix(*argv, "effective")) {
|
|
|
|
if (query_flags & BPF_F_QUERY_EFFECTIVE) {
|
|
|
|
p_err("duplicated argument: %s", *argv);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
query_flags |= BPF_F_QUERY_EFFECTIVE;
|
|
|
|
NEXT_ARG();
|
|
|
|
} else {
|
|
|
|
p_err("expected no more arguments, 'effective', got: '%s'?",
|
|
|
|
*argv);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2018-07-07 05:28:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (json_output)
|
|
|
|
jsonw_start_array(json_wtr);
|
2022-09-21 18:46:03 +08:00
|
|
|
else if (query_flags & BPF_F_QUERY_EFFECTIVE)
|
|
|
|
printf("%s\n"
|
|
|
|
"%-8s %-15s %-15s\n",
|
|
|
|
"CgroupPath",
|
|
|
|
"ID", "AttachType", "Name");
|
2018-07-07 05:28:14 +08:00
|
|
|
else
|
|
|
|
printf("%s\n"
|
|
|
|
"%-8s %-15s %-15s %-15s\n",
|
|
|
|
"CgroupPath",
|
|
|
|
"ID", "AttachType", "AttachFlags", "Name");
|
|
|
|
|
|
|
|
switch (nftw(cgroup_root, do_show_tree_fn, 1024, FTW_MOUNT)) {
|
|
|
|
case NFTW_ERR:
|
|
|
|
p_err("can't iterate over %s: %s", cgroup_root,
|
|
|
|
strerror(errno));
|
|
|
|
ret = -1;
|
|
|
|
break;
|
|
|
|
case SHOW_TREE_FN_ERR:
|
|
|
|
ret = -1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (json_output)
|
|
|
|
jsonw_end_array(json_wtr);
|
|
|
|
|
2019-07-31 05:03:00 +08:00
|
|
|
free(cgroup_alloced);
|
2018-07-07 05:28:14 +08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-12-13 23:18:54 +08:00
|
|
|
static int do_attach(int argc, char **argv)
|
|
|
|
{
|
|
|
|
enum bpf_attach_type attach_type;
|
|
|
|
int cgroup_fd, prog_fd;
|
|
|
|
int attach_flags = 0;
|
|
|
|
int ret = -1;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (argc < 4) {
|
2018-01-03 06:48:37 +08:00
|
|
|
p_err("too few parameters for cgroup attach");
|
2017-12-13 23:18:54 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
cgroup_fd = open(argv[0], O_RDONLY);
|
|
|
|
if (cgroup_fd < 0) {
|
2019-06-26 00:56:31 +08:00
|
|
|
p_err("can't open cgroup %s", argv[0]);
|
2017-12-13 23:18:54 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
attach_type = parse_attach_type(argv[1]);
|
|
|
|
if (attach_type == __MAX_BPF_ATTACH_TYPE) {
|
2018-01-03 06:48:37 +08:00
|
|
|
p_err("invalid attach type");
|
2017-12-13 23:18:54 +08:00
|
|
|
goto exit_cgroup;
|
|
|
|
}
|
|
|
|
|
|
|
|
argc -= 2;
|
|
|
|
argv = &argv[2];
|
|
|
|
prog_fd = prog_parse_fd(&argc, &argv);
|
|
|
|
if (prog_fd < 0)
|
|
|
|
goto exit_cgroup;
|
|
|
|
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
|
|
if (is_prefix(argv[i], "multi")) {
|
|
|
|
attach_flags |= BPF_F_ALLOW_MULTI;
|
|
|
|
} else if (is_prefix(argv[i], "override")) {
|
|
|
|
attach_flags |= BPF_F_ALLOW_OVERRIDE;
|
|
|
|
} else {
|
2018-01-03 06:48:37 +08:00
|
|
|
p_err("unknown option: %s", argv[i]);
|
2017-12-13 23:18:54 +08:00
|
|
|
goto exit_cgroup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bpf_prog_attach(prog_fd, cgroup_fd, attach_type, attach_flags)) {
|
|
|
|
p_err("failed to attach program");
|
|
|
|
goto exit_prog;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (json_output)
|
|
|
|
jsonw_null(json_wtr);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
exit_prog:
|
|
|
|
close(prog_fd);
|
|
|
|
exit_cgroup:
|
|
|
|
close(cgroup_fd);
|
|
|
|
exit:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int do_detach(int argc, char **argv)
|
|
|
|
{
|
|
|
|
enum bpf_attach_type attach_type;
|
|
|
|
int prog_fd, cgroup_fd;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (argc < 4) {
|
2018-01-03 06:48:37 +08:00
|
|
|
p_err("too few parameters for cgroup detach");
|
2017-12-13 23:18:54 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
cgroup_fd = open(argv[0], O_RDONLY);
|
|
|
|
if (cgroup_fd < 0) {
|
2019-06-26 00:56:31 +08:00
|
|
|
p_err("can't open cgroup %s", argv[0]);
|
2017-12-13 23:18:54 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
attach_type = parse_attach_type(argv[1]);
|
|
|
|
if (attach_type == __MAX_BPF_ATTACH_TYPE) {
|
|
|
|
p_err("invalid attach type");
|
|
|
|
goto exit_cgroup;
|
|
|
|
}
|
|
|
|
|
|
|
|
argc -= 2;
|
|
|
|
argv = &argv[2];
|
|
|
|
prog_fd = prog_parse_fd(&argc, &argv);
|
|
|
|
if (prog_fd < 0)
|
|
|
|
goto exit_cgroup;
|
|
|
|
|
|
|
|
if (bpf_prog_detach2(prog_fd, cgroup_fd, attach_type)) {
|
|
|
|
p_err("failed to detach program");
|
|
|
|
goto exit_prog;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (json_output)
|
|
|
|
jsonw_null(json_wtr);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
exit_prog:
|
|
|
|
close(prog_fd);
|
|
|
|
exit_cgroup:
|
|
|
|
close(cgroup_fd);
|
|
|
|
exit:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int do_help(int argc, char **argv)
|
|
|
|
{
|
|
|
|
if (json_output) {
|
|
|
|
jsonw_null(json_wtr);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr,
|
2020-05-23 09:07:51 +08:00
|
|
|
"Usage: %1$s %2$s { show | list } CGROUP [**effective**]\n"
|
|
|
|
" %1$s %2$s tree [CGROUP_ROOT] [**effective**]\n"
|
|
|
|
" %1$s %2$s attach CGROUP ATTACH_TYPE PROG [ATTACH_FLAGS]\n"
|
|
|
|
" %1$s %2$s detach CGROUP ATTACH_TYPE PROG\n"
|
|
|
|
" %1$s %2$s help\n"
|
2017-12-13 23:18:54 +08:00
|
|
|
"\n"
|
2018-04-18 01:28:44 +08:00
|
|
|
HELP_SPEC_ATTACH_TYPES "\n"
|
2017-12-13 23:18:54 +08:00
|
|
|
" " HELP_SPEC_ATTACH_FLAGS "\n"
|
|
|
|
" " HELP_SPEC_PROGRAM "\n"
|
2021-07-31 05:54:32 +08:00
|
|
|
" " HELP_SPEC_OPTIONS " |\n"
|
2021-07-31 05:54:34 +08:00
|
|
|
" {-f|--bpffs} }\n"
|
2017-12-13 23:18:54 +08:00
|
|
|
"",
|
2020-05-23 09:07:51 +08:00
|
|
|
bin_name, argv[-2]);
|
2017-12-13 23:18:54 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct cmd cmds[] = {
|
2018-01-03 06:48:36 +08:00
|
|
|
{ "show", do_show },
|
2018-01-03 06:48:35 +08:00
|
|
|
{ "list", do_show },
|
2018-07-07 05:28:14 +08:00
|
|
|
{ "tree", do_show_tree },
|
2017-12-13 23:18:54 +08:00
|
|
|
{ "attach", do_attach },
|
|
|
|
{ "detach", do_detach },
|
|
|
|
{ "help", do_help },
|
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
int do_cgroup(int argc, char **argv)
|
|
|
|
{
|
|
|
|
return cmd_select(cmds, argc, argv, do_help);
|
|
|
|
}
|