Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
4 : : */
5 : :
6 : : #include "bpfilter/bpf.h"
7 : :
8 : : #include <linux/bpf.h>
9 : :
10 : : #include <errno.h>
11 : : #include <stdint.h>
12 : : #include <stdio.h>
13 : : #include <stdlib.h>
14 : : #include <unistd.h>
15 : :
16 : : #include "bpfilter/bpf_types.h"
17 : : #include "bpfilter/btf.h"
18 : : #include "bpfilter/helper.h"
19 : : #include "bpfilter/logger.h"
20 : :
21 : : #ifdef __i386__
22 : : #define _BF_NR_bpf 357
23 : : #elif defined(__x86_64__)
24 : : #define _BF_NR_bpf 321
25 : : #elif defined(__aarch64__)
26 : : #define _BF_NR_bpf 280
27 : : #elif defined(__loongarch__)
28 : : #define _BF_NR_bpf 280
29 : : #else
30 : : #error _BF_NR_bpf not defined. bpfilter does not support your arch.
31 : : #endif
32 : :
33 : 55517 : int bf_bpf(enum bf_bpf_cmd cmd, union bpf_attr *attr)
34 : : {
35 : 55517 : int r = (int)syscall(_BF_NR_bpf, cmd, attr, sizeof(*attr));
36 [ + + ]: 55517 : if (r < 0)
37 : 170 : return -errno;
38 : :
39 : : return r;
40 : : }
41 : :
42 : 1310 : int bf_bpf_prog_load(const char *name, enum bf_bpf_prog_type prog_type,
43 : : void *img, size_t img_len,
44 : : enum bf_bpf_attach_type attach_type, const char *log_buf,
45 : : size_t log_size, int token_fd, int *fd)
46 : : {
47 : : union bpf_attr attr;
48 : : int r;
49 : :
50 : : assert(name);
51 : : assert(img);
52 : : assert(fd);
53 : :
54 : 1310 : memset(&attr, 0, sizeof(attr));
55 : :
56 : 1310 : attr.prog_type = prog_type;
57 : 1310 : attr.insns = bf_ptr_to_u64(img);
58 : 1310 : attr.insn_cnt = (unsigned int)img_len;
59 : 1310 : attr.license = bf_ptr_to_u64("GPL");
60 : 1310 : attr.expected_attach_type = attach_type;
61 : 1310 : attr.log_buf = bf_ptr_to_u64(log_buf);
62 : 1310 : attr.log_size = log_size;
63 : 1310 : attr.log_level = 1;
64 : :
65 : 1310 : (void)snprintf(attr.prog_name, BPF_OBJ_NAME_LEN, "%s", name);
66 : :
67 [ + + ]: 1310 : if (token_fd != -1) {
68 : 1 : attr.prog_token_fd = token_fd;
69 : 1 : attr.prog_flags |= BPF_F_TOKEN_FD;
70 : : }
71 : :
72 : 1310 : r = bf_bpf(BF_BPF_PROG_LOAD, &attr);
73 [ + + ]: 1310 : if (r < 0)
74 : : return r;
75 : :
76 : 1309 : *fd = r;
77 : :
78 : 1309 : return 0;
79 : : }
80 : :
81 : 8809 : int bf_bpf_map_lookup_elem(int fd, const void *key, void *value)
82 : : {
83 : : union bpf_attr attr;
84 : :
85 : : assert(key);
86 : : assert(value);
87 : :
88 : 8809 : memset(&attr, 0, sizeof(attr));
89 : :
90 : 8809 : attr.map_fd = fd;
91 : 8809 : attr.key = (uint64_t)key;
92 : 8809 : attr.value = (uint64_t)value;
93 : :
94 : 8809 : return bf_bpf(BF_BPF_MAP_LOOKUP_ELEM, &attr);
95 : : }
96 : :
97 : 5330 : int bf_bpf_map_get_info(int fd, struct bpf_map_info *info)
98 : : {
99 : : union bpf_attr attr;
100 : :
101 : : assert(info);
102 : :
103 : 5330 : memset(&attr, 0, sizeof(attr));
104 : 5330 : memset(info, 0, sizeof(*info));
105 : :
106 : 5330 : attr.info.bpf_fd = fd;
107 : 5330 : attr.info.info_len = sizeof(*info);
108 : 5330 : attr.info.info = bf_ptr_to_u64(info);
109 : :
110 : 5330 : return bf_bpf(BF_BPF_OBJ_GET_INFO_BY_FD, &attr);
111 : : }
112 : :
113 : 5712 : int bf_bpf_obj_pin(const char *path, int fd, int dir_fd)
114 : : {
115 : : union bpf_attr attr;
116 : :
117 : : assert(path);
118 : : assert(dir_fd >= 0);
119 : : assert(path[0] == '/' ? !dir_fd : 1);
120 : :
121 : 5712 : memset(&attr, 0, sizeof(attr));
122 : :
123 : 5712 : attr.pathname = bf_ptr_to_u64(path);
124 : 5712 : attr.bpf_fd = fd;
125 [ + + ]: 5712 : attr.file_flags = dir_fd ? BPF_F_PATH_FD : 0;
126 : 5712 : attr.path_fd = dir_fd;
127 : :
128 : 5712 : return bf_bpf(BF_BPF_OBJ_PIN, &attr);
129 : : }
130 : :
131 : 22662 : int bf_bpf_obj_get(const char *path, int dir_fd, int *fd)
132 : : {
133 : : union bpf_attr attr;
134 : : int r;
135 : :
136 : : assert(path);
137 : : assert(fd);
138 : : assert(dir_fd >= 0);
139 : : assert(path[0] == '/' ? !dir_fd : 1);
140 : :
141 : 22662 : memset(&attr, 0, sizeof(attr));
142 : :
143 : 22662 : attr.pathname = bf_ptr_to_u64(path);
144 [ + + ]: 22662 : attr.file_flags = dir_fd ? BPF_F_PATH_FD : 0;
145 : 22662 : attr.path_fd = dir_fd;
146 : :
147 : 22662 : r = bf_bpf(BF_BPF_OBJ_GET, &attr);
148 [ + + ]: 22662 : if (r < 0)
149 : : return r;
150 : :
151 : 22507 : *fd = r;
152 : :
153 : 22507 : return 0;
154 : : }
155 : :
156 : 2883 : int bf_bpf_prog_run(int prog_fd, const void *pkt, size_t pkt_len,
157 : : const void *ctx, size_t ctx_len)
158 : : {
159 : : union bpf_attr attr;
160 : : int r;
161 : :
162 : : assert(pkt);
163 : : assert(pkt_len > 0);
164 : : assert(!(!!ctx ^ !!ctx_len));
165 : :
166 : 2883 : memset(&attr, 0, sizeof(attr));
167 : :
168 : 2883 : attr.test.prog_fd = prog_fd;
169 : 2883 : attr.test.data_size_in = pkt_len;
170 : 2883 : attr.test.data_in = (unsigned long long)pkt;
171 : 2883 : attr.test.repeat = 1;
172 : :
173 [ + + ]: 2883 : if (ctx_len) {
174 : 1426 : attr.test.ctx_size_in = ctx_len;
175 : 1426 : attr.test.ctx_in = (unsigned long long)ctx;
176 : : }
177 : :
178 : 2883 : r = bf_bpf(BF_BPF_PROG_TEST_RUN, &attr);
179 [ + + ]: 2883 : if (r)
180 [ + - ]: 1 : return bf_err_r(r, "failed to run the test program");
181 : :
182 : 2882 : return (int)attr.test.retval;
183 : : }
184 : :
185 : 2 : int bf_bpf_token_create(int bpffs_fd)
186 : : {
187 : : union bpf_attr attr;
188 : :
189 : 2 : memset(&attr, 0, sizeof(attr));
190 : :
191 : 2 : attr.token_create.bpffs_fd = bpffs_fd;
192 : :
193 : 2 : return bf_bpf(BF_BPF_TOKEN_CREATE, &attr);
194 : : }
195 : :
196 : 1311 : int bf_bpf_btf_load(const void *btf_data, size_t btf_data_len, int token_fd)
197 : : {
198 : : assert(btf_data);
199 : :
200 : : union bpf_attr attr;
201 : :
202 : 1311 : memset(&attr, 0, sizeof(attr));
203 : :
204 : 1311 : attr.btf = bf_ptr_to_u64(btf_data);
205 : 1311 : attr.btf_size = btf_data_len;
206 : :
207 [ + + ]: 1311 : if (token_fd != -1) {
208 : 1 : attr.btf_token_fd = token_fd;
209 : 1 : attr.btf_flags |= BPF_F_TOKEN_FD;
210 : : }
211 : :
212 : 1311 : return bf_bpf(BF_BPF_BTF_LOAD, &attr);
213 : : }
214 : :
215 : 4282 : int bf_bpf_map_create(const char *name, enum bf_bpf_map_type type,
216 : : size_t key_size, size_t value_size, size_t n_elems,
217 : : const struct bf_btf *btf, int token_fd)
218 : : {
219 : : assert(name);
220 : :
221 : : union bpf_attr attr;
222 : :
223 : 4282 : memset(&attr, 0, sizeof(attr));
224 : :
225 : 4282 : attr.map_type = type;
226 : 4282 : attr.key_size = key_size;
227 : 4282 : attr.value_size = value_size;
228 : 4282 : attr.max_entries = n_elems;
229 : :
230 : : // NO_PREALLOC is *required* for LPM_TRIE map
231 [ + + ]: 4282 : if (type == BF_BPF_MAP_TYPE_LPM_TRIE)
232 : 65 : attr.map_flags |= BPF_F_NO_PREALLOC;
233 : :
234 [ + + ]: 4282 : if (token_fd != -1) {
235 : 1 : attr.map_token_fd = token_fd;
236 : 1 : attr.map_flags |= BPF_F_TOKEN_FD;
237 : : };
238 : :
239 [ + + ]: 4282 : if (btf) {
240 : 1309 : attr.btf_fd = btf->fd;
241 : 1309 : attr.btf_key_type_id = btf->key_type_id;
242 : 1309 : attr.btf_value_type_id = btf->value_type_id;
243 : : }
244 : :
245 : 4282 : (void)snprintf(attr.map_name, BPF_OBJ_NAME_LEN, "%s", name);
246 : :
247 : 4282 : return bf_bpf(BF_BPF_MAP_CREATE, &attr);
248 : : }
249 : :
250 : 2645 : int bf_bpf_map_update_elem(int map_fd, const void *key, const void *value,
251 : : int flags)
252 : : {
253 : : assert(key);
254 : : assert(value);
255 : :
256 : : union bpf_attr attr;
257 : :
258 : 2645 : memset(&attr, 0, sizeof(attr));
259 : :
260 : 2645 : attr.map_fd = map_fd;
261 : 2645 : attr.key = bf_ptr_to_u64(key);
262 : 2645 : attr.value = bf_ptr_to_u64(value);
263 : 2645 : attr.flags = flags;
264 : :
265 : 2645 : return bf_bpf(BF_BPF_MAP_UPDATE_ELEM, &attr);
266 : : }
267 : :
268 : 303 : int bf_bpf_map_update_batch(int map_fd, const void *keys, const void *values,
269 : : size_t count, int flags)
270 : : {
271 : : assert(keys);
272 : : assert(values);
273 : :
274 : : union bpf_attr attr;
275 : :
276 : 303 : memset(&attr, 0, sizeof(attr));
277 : :
278 : 303 : attr.batch.map_fd = map_fd;
279 : 303 : attr.batch.keys = bf_ptr_to_u64(keys);
280 : 303 : attr.batch.values = bf_ptr_to_u64(values);
281 : 303 : attr.batch.count = count;
282 : 303 : attr.batch.flags = flags;
283 : :
284 : 303 : return bf_bpf(BF_BPF_MAP_UPDATE_BATCH, &attr);
285 : : }
286 : :
287 : 134 : int bf_bpf_link_create(int prog_fd, int target_fd, enum bf_hook hook, int flags,
288 : : uint32_t family, int32_t priority)
289 : : {
290 : : enum bf_bpf_attach_type attach_type;
291 : : union bpf_attr attr;
292 : :
293 : 134 : memset(&attr, 0, sizeof(attr));
294 : :
295 : 134 : attach_type = bf_hook_to_bpf_attach_type(hook);
296 : :
297 : 134 : attr.link_create.prog_fd = prog_fd;
298 : 134 : attr.link_create.target_fd = target_fd;
299 : 134 : attr.link_create.attach_type = attach_type;
300 : 134 : attr.link_create.flags = flags;
301 : :
302 [ + + ]: 134 : if (attach_type == BF_BPF_NETFILTER) {
303 : 16 : attr.link_create.netfilter.pf = family;
304 : 16 : attr.link_create.netfilter.hooknum = bf_hook_to_nf_hook(hook);
305 : 16 : attr.link_create.netfilter.priority = priority;
306 : : }
307 : :
308 : 134 : return bf_bpf(BF_BPF_LINK_CREATE, &attr);
309 : : }
310 : :
311 : 13 : int bf_bpf_link_update(int link_fd, int new_prog_fd)
312 : : {
313 : : union bpf_attr attr;
314 : :
315 : 13 : memset(&attr, 0, sizeof(attr));
316 : :
317 : 13 : attr.link_update.link_fd = link_fd;
318 : 13 : attr.link_update.new_map_fd = new_prog_fd;
319 : :
320 : 13 : return bf_bpf(BF_BPF_LINK_UPDATE, &attr);
321 : : }
322 : :
323 : 119 : int bf_bpf_link_detach(int link_fd)
324 : : {
325 : : union bpf_attr attr;
326 : :
327 : 119 : memset(&attr, 0, sizeof(attr));
328 : :
329 : 119 : attr.link_detach.link_fd = link_fd;
330 : :
331 : 119 : return bf_bpf(BF_BPF_LINK_DETACH, &attr);
332 : : }
|