lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAKH8qBvqMSTc_4gF-WqgnTLgCRTU5JrxPESnt3aB+RW492Ppwg@mail.gmail.com>
Date:   Thu, 3 Jan 2019 09:15:22 -0800
From:   Stanislav Fomichev <sdf@...gle.com>
To:     Quentin Monnet <quentin.monnet@...ronome.com>
Cc:     Alexei Starovoitov <ast@...nel.org>,
        Daniel Borkmann <daniel@...earbox.net>, netdev@...r.kernel.org,
        oss-drivers@...ronome.com,
        Arnaldo Carvalho de Melo <acme@...nel.org>,
        Jesper Dangaard Brouer <brouer@...hat.com>
Subject: Re: [RFC bpf-next v3 6/9] tools: bpftool: add probes for eBPF helper functions

On Thu, Jan 3, 2019 at 6:03 AM Quentin Monnet
<quentin.monnet@...ronome.com> wrote:
>
> Similarly to what was done for program types and map types, add a set of
> probes to test the availability of the different eBPF helper functions
> on the current system.
>
> For each known program type, all known helpers are tested, in order to
> establish a compatibility matrix. Output is provided as a set of lists
> of available helpers, one per program type.
>
> Sample output:
>
>     # bpftool feature probe kernel
>     ...
>     Scanning eBPF helper functions...
>     eBPF helpers supported for program type socket_filter:
>             - bpf_map_lookup_elem
>             - bpf_map_update_elem
>             - bpf_map_delete_elem
>     ...
>     eBPF helpers supported for program type kprobe:
>             - bpf_map_lookup_elem
>             - bpf_map_update_elem
>             - bpf_map_delete_elem
>     ...
>
>     # bpftool --json --pretty feature probe kernel
>     {
>         ...
>         "helpers": {
>             "socket_filter_available_helpers": ["bpf_map_lookup_elem", \
>                     "bpf_map_update_elem","bpf_map_delete_elem", ...
>             ],
>             "kprobe_available_helpers": ["bpf_map_lookup_elem", \
>                     "bpf_map_update_elem","bpf_map_delete_elem", ...
>             ],
>             ...
>         }
>     }
>
> v3:
> - Do not pass kernel version from bpftool to libbpf probes (kernel
>   version for testing program with kprobes is retrieved directly from
>   libbpf).
> - Dump one list of available helpers per program type (instead of one
>   list of compatible program types per helper).
>
> v2:
> - Move probes from bpftool to libbpf.
> - Test all program types for each helper, print a list of working prog
>   types for each helper.
> - Fall back on include/uapi/linux/bpf.h for names and ids of helpers.
> - Remove C-style macros output from this patch.
>
> Signed-off-by: Quentin Monnet <quentin.monnet@...ronome.com>
> ---
>  .../bpftool/Documentation/bpftool-feature.rst |  4 ++
>  tools/bpf/bpftool/feature.c                   | 49 +++++++++++++++
>  tools/lib/bpf/libbpf.h                        |  2 +
>  tools/lib/bpf/libbpf.map                      |  1 +
>  tools/lib/bpf/libbpf_probes.c                 | 62 +++++++++++++++++++
>  5 files changed, 118 insertions(+)
>
> diff --git a/tools/bpf/bpftool/Documentation/bpftool-feature.rst b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
> index 40ac13c0b782..255e3b3629a0 100644
> --- a/tools/bpf/bpftool/Documentation/bpftool-feature.rst
> +++ b/tools/bpf/bpftool/Documentation/bpftool-feature.rst
> @@ -30,6 +30,10 @@ DESCRIPTION
>
>                   Keyword **kernel** can be omitted.
>
> +                 Note that when probed, some eBPF helpers (e.g.
> +                 **bpf_trace_printk**\ () or **bpf_probe_write_user**\ ()) may
> +                 print warnings to kernel logs.
> +
>         **bpftool feature help**
>                   Print short help message.
>
> diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
> index 6a4ff402854c..133cdfda00d4 100644
> --- a/tools/bpf/bpftool/feature.c
> +++ b/tools/bpf/bpftool/feature.c
> @@ -25,6 +25,11 @@ enum probe_component {
>         COMPONENT_KERNEL,
>  };
>
> +#define BPF_HELPER_MAKE_ENTRY(name)    [BPF_FUNC_ ## name] = "bpf_" # name
> +static const char * const helper_name[] = {
> +       __BPF_FUNC_MAPPER(BPF_HELPER_MAKE_ENTRY)
> +};
> +
>  /* Miscellaneous utility functions */
>
>  static bool check_procfs(void)
> @@ -400,6 +405,44 @@ static void probe_map_type(enum bpf_map_type map_type)
>         print_bool_feature(feat_name, plain_desc, res);
>  }
>
> +static void
> +probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type)
> +{
> +       const char *ptype_name = prog_type_name[prog_type];
> +       char feat_name[128];
> +       unsigned int id;
> +       bool res;
> +
> +       if (json_output) {
> +               sprintf(feat_name, "%s_available_helpers", ptype_name);
> +               jsonw_name(json_wtr, feat_name);
> +               jsonw_start_array(json_wtr);
> +       } else {
> +               printf("eBPF helpers supported for program type %s:",
> +                      ptype_name);
> +       }
> +
> +       for (id = 1; id < ARRAY_SIZE(helper_name); id++) {
> +               if (!supported_type)
> +                       res = false;
> +               else
> +                       res = bpf_probe_helper(id, prog_type, 0);
> +
> +               if (json_output) {
> +                       if (res)
> +                               jsonw_string(json_wtr, helper_name[id]);
> +               } else {
> +                       if (res)
> +                               printf("\n\t- %s", helper_name[id]);
> +               }
> +       }
> +
> +       if (json_output)
> +               jsonw_end_array(json_wtr);
> +       else
> +               printf("\n");
> +}
> +
>  static int do_probe(int argc, char **argv)
>  {
>         enum probe_component target = COMPONENT_UNSPEC;
> @@ -474,6 +517,12 @@ static int do_probe(int argc, char **argv)
>         for (i = BPF_MAP_TYPE_UNSPEC + 1; i < map_type_name_size; i++)
>                 probe_map_type(i);
>
> +       print_end_then_start_section("helpers",
> +                                    "Scanning eBPF helper functions...");
> +
> +       for (i = BPF_PROG_TYPE_UNSPEC + 1; i < ARRAY_SIZE(prog_type_name); i++)
> +               probe_helpers_for_progtype(i, supported_types[i]);
> +
>  exit_close_json:
>         if (json_output) {
>                 /* End current "section" of probes */
> diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> index 72385f6f9415..6ab275933d2e 100644
> --- a/tools/lib/bpf/libbpf.h
> +++ b/tools/lib/bpf/libbpf.h
> @@ -366,6 +366,8 @@ bpf_prog_linfo__lfind(const struct bpf_prog_linfo *prog_linfo,
>  LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type,
>                                     __u32 ifindex);
>  LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex);
> +LIBBPF_API bool bpf_probe_helper(__u32 id, enum bpf_prog_type prog_type,
Any reason not to use enum bpf_func_id as id type (instead of __u32)?

> +                                __u32 ifindex);
>
>  #ifdef __cplusplus
>  } /* extern "C" */
> diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
> index c08f4c726e8e..67e51b2becec 100644
> --- a/tools/lib/bpf/libbpf.map
> +++ b/tools/lib/bpf/libbpf.map
> @@ -56,6 +56,7 @@ LIBBPF_0.0.1 {
>                 bpf_object__unpin_maps;
>                 bpf_object__unpin_programs;
>                 bpf_perf_event_read_simple;
> +               bpf_probe_helper;
>                 bpf_probe_map_type;
>                 bpf_probe_prog_type;
>                 bpf_prog_attach;
> diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c
> index e3d57632a975..1b325142bca4 100644
> --- a/tools/lib/bpf/libbpf_probes.c
> +++ b/tools/lib/bpf/libbpf_probes.c
> @@ -2,7 +2,11 @@
>  /* Copyright (c) 2019 Netronome Systems, Inc. */
>
>  #include <errno.h>
> +#include <fcntl.h>
> +#include <string.h>
> +#include <stdlib.h>
>  #include <unistd.h>
> +#include <net/if.h>
>  #include <sys/utsname.h>
>
>  #include <linux/filter.h>
> @@ -11,6 +15,37 @@
>  #include "bpf.h"
>  #include "libbpf.h"
>
> +static bool grep(const char *buffer, const char *pattern)
> +{
> +       return !!strstr(buffer, pattern);
> +}
> +
> +static int get_vendor_id(int ifindex)
> +{
> +       char ifname[IF_NAMESIZE], path[64], buf[8];
> +       ssize_t len;
> +       int fd;
> +
> +       if (!if_indextoname(ifindex, ifname))
> +               return -1;
> +
> +       snprintf(path, sizeof(path), "/sys/class/net/%s/device/vendor", ifname);
> +
> +       fd = open(path, O_RDONLY);
> +       if (fd < 0)
> +               return -1;
> +
> +       len = read(fd, buf, sizeof(buf));
> +       close(fd);
> +       if (len < 0)
> +               return -1;
> +       if (len >= (ssize_t)sizeof(buf))
> +               return -1;
> +       buf[len] = '\0';
> +
> +       return strtol(buf, NULL, 0);
> +}
> +
>  static int get_kernel_version(void)
>  {
>         int version, subversion, patchlevel;
> @@ -177,3 +212,30 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
>
>         return fd >= 0;
>  }
> +
> +bool bpf_probe_helper(__u32 id, enum bpf_prog_type prog_type, __u32 ifindex)
> +{
> +       struct bpf_insn insns[2] = {
> +               BPF_EMIT_CALL(id),
> +               BPF_EXIT_INSN()
> +       };
> +       char buf[4096] = {};
> +       bool res;
> +
> +       prog_load(prog_type, insns, ARRAY_SIZE(insns), buf, sizeof(buf),
> +                 ifindex);
> +       res = !grep(buf, "invalid func ") && !grep(buf, "unknown func ");
> +
> +       if (ifindex) {
> +               switch (get_vendor_id(ifindex)) {
> +               case 0x19ee: /* Netronome specific */
> +                       res = res && !grep(buf, "not supported by FW") &&
> +                               !grep(buf, "unsupported function id");
> +                       break;
> +               default:
> +                       break;
> +               }
> +       }
> +
> +       return res;
> +}
> --
> 2.17.1
>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ