bpftool: Enable libbpf's strict mode by default

Otherwise, attaching with bpftool doesn't work with strict section names.

Also:

  - Add --legacy option to switch back to pre-1.0 behavior
  - Print a warning when program fails to load in strict mode to
    point to --legacy flag
  - By default, don't append / to the section name; in strict
    mode it's relevant only for a small subset of prog types

+ bpftool --legacy prog loadall tools/testing/selftests/bpf/test_cgroup_link.o /sys/fs/bpf/kprobe type kprobe
libbpf: failed to pin program: File exists
Error: failed to pin all programs
+ bpftool prog loadall tools/testing/selftests/bpf/test_cgroup_link.o /sys/fs/bpf/kprobe type kprobe

v1 -> v2:
  - strict by default (Quentin Monnet)
  - add more info to --legacy description (Quentin Monnet)
  - add bash completion (Quentin Monnet)

Signed-off-by: Stanislav Fomichev <sdf@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: Quentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20211110192324.920934-1-sdf@google.com
This commit is contained in:
Stanislav Fomichev 2021-11-10 11:23:24 -08:00 committed by Daniel Borkmann
parent 9faaffbe85
commit 314f14abde
5 changed files with 48 additions and 19 deletions

View File

@ -20,3 +20,12 @@
Print all logs available, even debug-level information. This includes
logs from libbpf as well as from the verifier, when attempting to
load programs.
-l, --legacy
Use legacy libbpf mode which has more relaxed BPF program
requirements. By default, bpftool has more strict requirements
about section names, changes pinning logic and doesn't support
some of the older non-BTF map declarations.
See https://github.com/libbpf/libbpf/wiki/Libbpf:-the-road-to-v1.0
for details.

View File

@ -261,7 +261,7 @@ _bpftool()
# Deal with options
if [[ ${words[cword]} == -* ]]; then
local c='--version --json --pretty --bpffs --mapcompat --debug \
--use-loader --base-btf'
--use-loader --base-btf --legacy'
COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
return 0
fi

View File

@ -31,6 +31,7 @@ bool block_mount;
bool verifier_logs;
bool relaxed_maps;
bool use_loader;
bool legacy_libbpf;
struct btf *base_btf;
struct hashmap *refs_table;
@ -396,6 +397,7 @@ int main(int argc, char **argv)
{ "debug", no_argument, NULL, 'd' },
{ "use-loader", no_argument, NULL, 'L' },
{ "base-btf", required_argument, NULL, 'B' },
{ "legacy", no_argument, NULL, 'l' },
{ 0 }
};
int opt, ret;
@ -408,7 +410,7 @@ int main(int argc, char **argv)
bin_name = argv[0];
opterr = 0;
while ((opt = getopt_long(argc, argv, "VhpjfLmndB:",
while ((opt = getopt_long(argc, argv, "VhpjfLmndB:l",
options, NULL)) >= 0) {
switch (opt) {
case 'V':
@ -454,6 +456,9 @@ int main(int argc, char **argv)
case 'L':
use_loader = true;
break;
case 'l':
legacy_libbpf = true;
break;
default:
p_err("unrecognized option '%s'", argv[optind - 1]);
if (json_output)
@ -463,6 +468,12 @@ int main(int argc, char **argv)
}
}
if (!legacy_libbpf) {
ret = libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
if (ret)
p_err("failed to enable libbpf strict mode: %d", ret);
}
argc -= optind;
argv += optind;
if (argc < 0)

View File

@ -57,7 +57,7 @@ static inline void *u64_to_ptr(__u64 ptr)
#define HELP_SPEC_PROGRAM \
"PROG := { id PROG_ID | pinned FILE | tag PROG_TAG | name PROG_NAME }"
#define HELP_SPEC_OPTIONS \
"OPTIONS := { {-j|--json} [{-p|--pretty}] | {-d|--debug}"
"OPTIONS := { {-j|--json} [{-p|--pretty}] | {-d|--debug} | {-l|--legacy}"
#define HELP_SPEC_MAP \
"MAP := { id MAP_ID | pinned FILE | name MAP_NAME }"
#define HELP_SPEC_LINK \
@ -90,6 +90,7 @@ extern bool block_mount;
extern bool verifier_logs;
extern bool relaxed_maps;
extern bool use_loader;
extern bool legacy_libbpf;
extern struct btf *base_btf;
extern struct hashmap *refs_table;

View File

@ -1483,8 +1483,6 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
while (argc) {
if (is_prefix(*argv, "type")) {
char *type;
NEXT_ARG();
if (common_prog_type != BPF_PROG_TYPE_UNSPEC) {
@ -1494,8 +1492,12 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
if (!REQ_ARGS(1))
goto err_free_reuse_maps;
err = libbpf_prog_type_by_name(*argv, &common_prog_type,
&expected_attach_type);
if (err < 0) {
/* Put a '/' at the end of type to appease libbpf */
type = malloc(strlen(*argv) + 2);
char *type = malloc(strlen(*argv) + 2);
if (!type) {
p_err("mem alloc failed");
goto err_free_reuse_maps;
@ -1509,6 +1511,7 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
free(type);
if (err < 0)
goto err_free_reuse_maps;
}
NEXT_ARG();
} else if (is_prefix(*argv, "map")) {
@ -1731,6 +1734,11 @@ err_unpin:
else
bpf_object__unpin_programs(obj, pinfile);
err_close_obj:
if (!legacy_libbpf) {
p_info("Warning: bpftool is now running in libbpf strict mode and has more stringent requirements about BPF programs.\n"
"If it used to work for this object file but now doesn't, see --legacy option for more details.\n");
}
bpf_object__close(obj);
err_free_reuse_maps:
for (i = 0; i < old_map_fds; i++)