99ce513723774119d6b27676df0fe4dda024e30d
[openwrt/openwrt.git] / package / network / utils / bpftools / patches / 004-v5.9-bpftool-use-only-ftw-for-file-tree-parsing.patch
1 From 6edda7633e4fdf33b91c2e86c05cab805a0dabb3 Mon Sep 17 00:00:00 2001
2 From: Tony Ambardar <tony.ambardar@gmail.com>
3 Date: Mon, 20 Jul 2020 19:48:16 -0700
4 Subject: [PATCH] bpftool: Use only nftw for file tree parsing
5
6 The bpftool sources include code to walk file trees, but use multiple
7 frameworks to do so: nftw and fts. While nftw conforms to POSIX/SUSv3 and
8 is widely available, fts is not conformant and less common, especially on
9 non-glibc systems. The inconsistent framework usage hampers maintenance
10 and portability of bpftool, in particular for embedded systems.
11
12 Standardize code usage by rewriting one fts-based function to use nftw and
13 clean up some related function warnings by extending use of "const char *"
14 arguments. This change helps in building bpftool against musl for OpenWrt.
15
16 Also fix an unsafe call to dirname() by duplicating the string to pass,
17 since some implementations may directly alter it. The same approach is
18 used in libbpf.c.
19
20 Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>
21 Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
22 Reviewed-by: Quentin Monnet <quentin@isovalent.com>
23 Link: https://lore.kernel.org/bpf/20200721024817.13701-1-Tony.Ambardar@gmail.com
24 ---
25 tools/bpf/bpftool/common.c | 137 ++++++++++++++++++++++---------------
26 tools/bpf/bpftool/main.h | 4 +-
27 2 files changed, 82 insertions(+), 59 deletions(-)
28
29 --- a/tools/bpf/bpftool/common.c
30 +++ b/tools/bpf/bpftool/common.c
31 @@ -1,10 +1,11 @@
32 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
33 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
34
35 +#define _GNU_SOURCE
36 #include <ctype.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 -#include <fts.h>
40 +#include <ftw.h>
41 #include <libgen.h>
42 #include <mntent.h>
43 #include <stdbool.h>
44 @@ -123,24 +124,35 @@ int mount_tracefs(const char *target)
45 return err;
46 }
47
48 -int open_obj_pinned(char *path, bool quiet)
49 +int open_obj_pinned(const char *path, bool quiet)
50 {
51 - int fd;
52 + char *pname;
53 + int fd = -1;
54
55 - fd = bpf_obj_get(path);
56 + pname = strdup(path);
57 + if (!pname) {
58 + if (!quiet)
59 + p_err("mem alloc failed");
60 + goto out_ret;
61 + }
62 +
63 + fd = bpf_obj_get(pname);
64 if (fd < 0) {
65 if (!quiet)
66 - p_err("bpf obj get (%s): %s", path,
67 - errno == EACCES && !is_bpffs(dirname(path)) ?
68 + p_err("bpf obj get (%s): %s", pname,
69 + errno == EACCES && !is_bpffs(dirname(pname)) ?
70 "directory not in bpf file system (bpffs)" :
71 strerror(errno));
72 - return -1;
73 + goto out_free;
74 }
75
76 +out_free:
77 + free(pname);
78 +out_ret:
79 return fd;
80 }
81
82 -int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type)
83 +int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type)
84 {
85 enum bpf_obj_type type;
86 int fd;
87 @@ -330,71 +342,82 @@ void print_hex_data_json(uint8_t *data,
88 jsonw_end_array(json_wtr);
89 }
90
91 +/* extra params for nftw cb */
92 +static struct pinned_obj_table *build_fn_table;
93 +static enum bpf_obj_type build_fn_type;
94 +
95 +static int do_build_table_cb(const char *fpath, const struct stat *sb,
96 + int typeflag, struct FTW *ftwbuf)
97 +{
98 + struct bpf_prog_info pinned_info;
99 + __u32 len = sizeof(pinned_info);
100 + struct pinned_obj *obj_node;
101 + enum bpf_obj_type objtype;
102 + int fd, err = 0;
103 +
104 + if (typeflag != FTW_F)
105 + goto out_ret;
106 +
107 + fd = open_obj_pinned(fpath, true);
108 + if (fd < 0)
109 + goto out_ret;
110 +
111 + objtype = get_fd_type(fd);
112 + if (objtype != build_fn_type)
113 + goto out_close;
114 +
115 + memset(&pinned_info, 0, sizeof(pinned_info));
116 + if (bpf_obj_get_info_by_fd(fd, &pinned_info, &len))
117 + goto out_close;
118 +
119 + obj_node = calloc(1, sizeof(*obj_node));
120 + if (!obj_node) {
121 + err = -1;
122 + goto out_close;
123 + }
124 +
125 + obj_node->id = pinned_info.id;
126 + obj_node->path = strdup(fpath);
127 + if (!obj_node->path) {
128 + err = -1;
129 + free(obj_node);
130 + goto out_close;
131 + }
132 +
133 + hash_add(build_fn_table->table, &obj_node->hash, obj_node->id);
134 +out_close:
135 + close(fd);
136 +out_ret:
137 + return err;
138 +}
139 +
140 int build_pinned_obj_table(struct pinned_obj_table *tab,
141 enum bpf_obj_type type)
142 {
143 - struct bpf_prog_info pinned_info = {};
144 - struct pinned_obj *obj_node = NULL;
145 - __u32 len = sizeof(pinned_info);
146 struct mntent *mntent = NULL;
147 - enum bpf_obj_type objtype;
148 FILE *mntfile = NULL;
149 - FTSENT *ftse = NULL;
150 - FTS *fts = NULL;
151 - int fd, err;
152 + int flags = FTW_PHYS;
153 + int nopenfd = 16;
154 + int err = 0;
155
156 mntfile = setmntent("/proc/mounts", "r");
157 if (!mntfile)
158 return -1;
159
160 + build_fn_table = tab;
161 + build_fn_type = type;
162 +
163 while ((mntent = getmntent(mntfile))) {
164 - char *path[] = { mntent->mnt_dir, NULL };
165 + char *path = mntent->mnt_dir;
166
167 if (strncmp(mntent->mnt_type, "bpf", 3) != 0)
168 continue;
169 -
170 - fts = fts_open(path, 0, NULL);
171 - if (!fts)
172 - continue;
173 -
174 - while ((ftse = fts_read(fts))) {
175 - if (!(ftse->fts_info & FTS_F))
176 - continue;
177 - fd = open_obj_pinned(ftse->fts_path, true);
178 - if (fd < 0)
179 - continue;
180 -
181 - objtype = get_fd_type(fd);
182 - if (objtype != type) {
183 - close(fd);
184 - continue;
185 - }
186 - memset(&pinned_info, 0, sizeof(pinned_info));
187 - err = bpf_obj_get_info_by_fd(fd, &pinned_info, &len);
188 - if (err) {
189 - close(fd);
190 - continue;
191 - }
192 -
193 - obj_node = malloc(sizeof(*obj_node));
194 - if (!obj_node) {
195 - close(fd);
196 - fts_close(fts);
197 - fclose(mntfile);
198 - return -1;
199 - }
200 -
201 - memset(obj_node, 0, sizeof(*obj_node));
202 - obj_node->id = pinned_info.id;
203 - obj_node->path = strdup(ftse->fts_path);
204 - hash_add(tab->table, &obj_node->hash, obj_node->id);
205 -
206 - close(fd);
207 - }
208 - fts_close(fts);
209 + err = nftw(path, do_build_table_cb, nopenfd, flags);
210 + if (err)
211 + break;
212 }
213 fclose(mntfile);
214 - return 0;
215 + return err;
216 }
217
218 void delete_pinned_obj_table(struct pinned_obj_table *tab)
219 --- a/tools/bpf/bpftool/main.h
220 +++ b/tools/bpf/bpftool/main.h
221 @@ -196,8 +196,8 @@ int cmd_select(const struct cmd *cmds, i
222 int get_fd_type(int fd);
223 const char *get_fd_type_name(enum bpf_obj_type type);
224 char *get_fdinfo(int fd, const char *key);
225 -int open_obj_pinned(char *path, bool quiet);
226 -int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type);
227 +int open_obj_pinned(const char *path, bool quiet);
228 +int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type);
229 int mount_bpffs_for_pin(const char *name);
230 int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(int *, char ***));
231 int do_pin_fd(int fd, const char *name);