bpftools: add utility and library packages supporting eBPF usage
[openwrt/staging/wigyori.git] / package / network / utils / bpftools / patches / 004-v5.9-bpftool-use-only-ftw-for-file-tree-parsing.patch
diff --git a/package/network/utils/bpftools/patches/004-v5.9-bpftool-use-only-ftw-for-file-tree-parsing.patch b/package/network/utils/bpftools/patches/004-v5.9-bpftool-use-only-ftw-for-file-tree-parsing.patch
new file mode 100644 (file)
index 0000000..7767b5f
--- /dev/null
@@ -0,0 +1,238 @@
+From 6edda7633e4fdf33b91c2e86c05cab805a0dabb3 Mon Sep 17 00:00:00 2001
+From: Tony Ambardar <tony.ambardar@gmail.com>
+Date: Mon, 20 Jul 2020 19:48:16 -0700
+Subject: [PATCH] bpftool: Use only nftw for file tree parsing
+
+The bpftool sources include code to walk file trees, but use multiple
+frameworks to do so: nftw and fts. While nftw conforms to POSIX/SUSv3 and
+is widely available, fts is not conformant and less common, especially on
+non-glibc systems. The inconsistent framework usage hampers maintenance
+and portability of bpftool, in particular for embedded systems.
+
+Standardize code usage by rewriting one fts-based function to use nftw and
+clean up some related function warnings by extending use of "const char *"
+arguments. This change helps in building bpftool against musl for OpenWrt.
+
+Also fix an unsafe call to dirname() by duplicating the string to pass,
+since some implementations may directly alter it. The same approach is
+used in libbpf.c.
+
+Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Reviewed-by: Quentin Monnet <quentin@isovalent.com>
+Link: https://lore.kernel.org/bpf/20200721024817.13701-1-Tony.Ambardar@gmail.com
+---
+ tools/bpf/bpftool/common.c | 137 ++++++++++++++++++++++---------------
+ tools/bpf/bpftool/main.h   |   4 +-
+ 2 files changed, 82 insertions(+), 59 deletions(-)
+
+diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
+index 88264abaa738..d8bb4dd18c8a 100644
+--- a/tools/bpf/bpftool/common.c
++++ b/tools/bpf/bpftool/common.c
+@@ -1,10 +1,11 @@
+ // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+ /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
++#define _GNU_SOURCE
+ #include <ctype.h>
+ #include <errno.h>
+ #include <fcntl.h>
+-#include <fts.h>
++#include <ftw.h>
+ #include <libgen.h>
+ #include <mntent.h>
+ #include <stdbool.h>
+@@ -123,24 +124,35 @@ int mount_tracefs(const char *target)
+       return err;
+ }
+-int open_obj_pinned(char *path, bool quiet)
++int open_obj_pinned(const char *path, bool quiet)
+ {
+-      int fd;
++      char *pname;
++      int fd = -1;
+-      fd = bpf_obj_get(path);
++      pname = strdup(path);
++      if (!pname) {
++              if (!quiet)
++                      p_err("mem alloc failed");
++              goto out_ret;
++      }
++
++      fd = bpf_obj_get(pname);
+       if (fd < 0) {
+               if (!quiet)
+-                      p_err("bpf obj get (%s): %s", path,
+-                            errno == EACCES && !is_bpffs(dirname(path)) ?
++                      p_err("bpf obj get (%s): %s", pname,
++                            errno == EACCES && !is_bpffs(dirname(pname)) ?
+                           "directory not in bpf file system (bpffs)" :
+                           strerror(errno));
+-              return -1;
++              goto out_free;
+       }
++out_free:
++      free(pname);
++out_ret:
+       return fd;
+ }
+-int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type)
++int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type)
+ {
+       enum bpf_obj_type type;
+       int fd;
+@@ -353,71 +365,82 @@ void print_hex_data_json(uint8_t *data, size_t len)
+       jsonw_end_array(json_wtr);
+ }
++/* extra params for nftw cb */
++static struct pinned_obj_table *build_fn_table;
++static enum bpf_obj_type build_fn_type;
++
++static int do_build_table_cb(const char *fpath, const struct stat *sb,
++                           int typeflag, struct FTW *ftwbuf)
++{
++      struct bpf_prog_info pinned_info;
++      __u32 len = sizeof(pinned_info);
++      struct pinned_obj *obj_node;
++      enum bpf_obj_type objtype;
++      int fd, err = 0;
++
++      if (typeflag != FTW_F)
++              goto out_ret;
++
++      fd = open_obj_pinned(fpath, true);
++      if (fd < 0)
++              goto out_ret;
++
++      objtype = get_fd_type(fd);
++      if (objtype != build_fn_type)
++              goto out_close;
++
++      memset(&pinned_info, 0, sizeof(pinned_info));
++      if (bpf_obj_get_info_by_fd(fd, &pinned_info, &len))
++              goto out_close;
++
++      obj_node = calloc(1, sizeof(*obj_node));
++      if (!obj_node) {
++              err = -1;
++              goto out_close;
++      }
++
++      obj_node->id = pinned_info.id;
++      obj_node->path = strdup(fpath);
++      if (!obj_node->path) {
++              err = -1;
++              free(obj_node);
++              goto out_close;
++      }
++
++      hash_add(build_fn_table->table, &obj_node->hash, obj_node->id);
++out_close:
++      close(fd);
++out_ret:
++      return err;
++}
++
+ int build_pinned_obj_table(struct pinned_obj_table *tab,
+                          enum bpf_obj_type type)
+ {
+-      struct bpf_prog_info pinned_info = {};
+-      struct pinned_obj *obj_node = NULL;
+-      __u32 len = sizeof(pinned_info);
+       struct mntent *mntent = NULL;
+-      enum bpf_obj_type objtype;
+       FILE *mntfile = NULL;
+-      FTSENT *ftse = NULL;
+-      FTS *fts = NULL;
+-      int fd, err;
++      int flags = FTW_PHYS;
++      int nopenfd = 16;
++      int err = 0;
+       mntfile = setmntent("/proc/mounts", "r");
+       if (!mntfile)
+               return -1;
++      build_fn_table = tab;
++      build_fn_type = type;
++
+       while ((mntent = getmntent(mntfile))) {
+-              char *path[] = { mntent->mnt_dir, NULL };
++              char *path = mntent->mnt_dir;
+               if (strncmp(mntent->mnt_type, "bpf", 3) != 0)
+                       continue;
+-
+-              fts = fts_open(path, 0, NULL);
+-              if (!fts)
+-                      continue;
+-
+-              while ((ftse = fts_read(fts))) {
+-                      if (!(ftse->fts_info & FTS_F))
+-                              continue;
+-                      fd = open_obj_pinned(ftse->fts_path, true);
+-                      if (fd < 0)
+-                              continue;
+-
+-                      objtype = get_fd_type(fd);
+-                      if (objtype != type) {
+-                              close(fd);
+-                              continue;
+-                      }
+-                      memset(&pinned_info, 0, sizeof(pinned_info));
+-                      err = bpf_obj_get_info_by_fd(fd, &pinned_info, &len);
+-                      if (err) {
+-                              close(fd);
+-                              continue;
+-                      }
+-
+-                      obj_node = malloc(sizeof(*obj_node));
+-                      if (!obj_node) {
+-                              close(fd);
+-                              fts_close(fts);
+-                              fclose(mntfile);
+-                              return -1;
+-                      }
+-
+-                      memset(obj_node, 0, sizeof(*obj_node));
+-                      obj_node->id = pinned_info.id;
+-                      obj_node->path = strdup(ftse->fts_path);
+-                      hash_add(tab->table, &obj_node->hash, obj_node->id);
+-
+-                      close(fd);
+-              }
+-              fts_close(fts);
++              err = nftw(path, do_build_table_cb, nopenfd, flags);
++              if (err)
++                      break;
+       }
+       fclose(mntfile);
+-      return 0;
++      return err;
+ }
+ void delete_pinned_obj_table(struct pinned_obj_table *tab)
+diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
+index af9ad56c303a..b02e763f1e9c 100644
+--- a/tools/bpf/bpftool/main.h
++++ b/tools/bpf/bpftool/main.h
+@@ -140,8 +140,8 @@ int cmd_select(const struct cmd *cmds, int argc, char **argv,
+ int get_fd_type(int fd);
+ const char *get_fd_type_name(enum bpf_obj_type type);
+ char *get_fdinfo(int fd, const char *key);
+-int open_obj_pinned(char *path, bool quiet);
+-int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type);
++int open_obj_pinned(const char *path, bool quiet);
++int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type);
+ int mount_bpffs_for_pin(const char *name);
+ int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32));
+ int do_pin_fd(int fd, const char *name);
+-- 
+2.17.1
+