diff options
Diffstat (limited to 'package/network/utils/bpftools/patches/004-v5.9-bpftool-use-only-ftw-for-file-tree-parsing.patch')
-rw-r--r-- | package/network/utils/bpftools/patches/004-v5.9-bpftool-use-only-ftw-for-file-tree-parsing.patch | 238 |
1 files changed, 238 insertions, 0 deletions
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 index 0000000000..7767b5f595 --- /dev/null +++ b/package/network/utils/bpftools/patches/004-v5.9-bpftool-use-only-ftw-for-file-tree-parsing.patch @@ -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 + |