bpftool: Enable libbpf's strict mode by default
authorStanislav Fomichev <sdf@google.com>
Wed, 10 Nov 2021 19:23:24 +0000 (11:23 -0800)
committerDaniel Borkmann <daniel@iogearbox.net>
Fri, 12 Nov 2021 15:54:58 +0000 (16:54 +0100)
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
tools/bpf/bpftool/Documentation/common_options.rst
tools/bpf/bpftool/bash-completion/bpftool
tools/bpf/bpftool/main.c
tools/bpf/bpftool/main.h
tools/bpf/bpftool/prog.c

index 05d06c7..75adf23 100644 (file)
          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.
index 88e2bcf..4a1b02f 100644 (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
index 28237d7..473791e 100644 (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)
index 383835c..8d76d93 100644 (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;
 
index dea7a49..bf85c91 100644 (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,21 +1492,26 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
                        if (!REQ_ARGS(1))
                                goto err_free_reuse_maps;
 
-                       /* Put a '/' at the end of type to appease libbpf */
-                       type = malloc(strlen(*argv) + 2);
-                       if (!type) {
-                               p_err("mem alloc failed");
-                               goto err_free_reuse_maps;
-                       }
-                       *type = 0;
-                       strcat(type, *argv);
-                       strcat(type, "/");
+                       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 */
+                               char *type = malloc(strlen(*argv) + 2);
 
-                       err = get_prog_type_by_name(type, &common_prog_type,
-                                                   &expected_attach_type);
-                       free(type);
-                       if (err < 0)
-                               goto err_free_reuse_maps;
+                               if (!type) {
+                                       p_err("mem alloc failed");
+                                       goto err_free_reuse_maps;
+                               }
+                               *type = 0;
+                               strcat(type, *argv);
+                               strcat(type, "/");
+
+                               err = get_prog_type_by_name(type, &common_prog_type,
+                                                           &expected_attach_type);
+                               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++)