Commit | Line | Data |
---|---|---|
1bc38b8f | 1 | // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) |
6061a3d6 | 2 | |
e3ed2fef WN |
3 | /* |
4 | * common eBPF ELF operations. | |
5 | * | |
6 | * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> | |
7 | * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> | |
8 | * Copyright (C) 2015 Huawei Inc. | |
203d1cac WN |
9 | * |
10 | * This program is free software; you can redistribute it and/or | |
11 | * modify it under the terms of the GNU Lesser General Public | |
12 | * License as published by the Free Software Foundation; | |
13 | * version 2.1 of the License (not later!) | |
14 | * | |
15 | * This program is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | * GNU Lesser General Public License for more details. | |
19 | * | |
20 | * You should have received a copy of the GNU Lesser General Public | |
21 | * License along with this program; if not, see <http://www.gnu.org/licenses> | |
e3ed2fef WN |
22 | */ |
23 | ||
24 | #include <stdlib.h> | |
1ad9cbb8 | 25 | #include <string.h> |
e3ed2fef WN |
26 | #include <memory.h> |
27 | #include <unistd.h> | |
28 | #include <asm/unistd.h> | |
d7fe74f9 | 29 | #include <errno.h> |
e3ed2fef | 30 | #include <linux/bpf.h> |
e542f2c4 | 31 | #include <linux/filter.h> |
04b6de64 | 32 | #include <linux/kernel.h> |
d10ef2b8 | 33 | #include <limits.h> |
e542f2c4 | 34 | #include <sys/resource.h> |
e3ed2fef | 35 | #include "bpf.h" |
949abbe8 | 36 | #include "libbpf.h" |
d7fe74f9 | 37 | #include "libbpf_internal.h" |
e3ed2fef WN |
38 | |
39 | /* | |
03671057 | 40 | * When building perf, unistd.h is overridden. __NR_bpf is |
8f9e05fb | 41 | * required to be defined explicitly. |
e3ed2fef WN |
42 | */ |
43 | #ifndef __NR_bpf | |
44 | # if defined(__i386__) | |
45 | # define __NR_bpf 357 | |
46 | # elif defined(__x86_64__) | |
47 | # define __NR_bpf 321 | |
48 | # elif defined(__aarch64__) | |
49 | # define __NR_bpf 280 | |
b0c47807 DM |
50 | # elif defined(__sparc__) |
51 | # define __NR_bpf 349 | |
bad1926d DB |
52 | # elif defined(__s390__) |
53 | # define __NR_bpf 351 | |
ca31ca82 VG |
54 | # elif defined(__arc__) |
55 | # define __NR_bpf 280 | |
e32cb12f TY |
56 | # elif defined(__mips__) && defined(_ABIO32) |
57 | # define __NR_bpf 4355 | |
58 | # elif defined(__mips__) && defined(_ABIN32) | |
59 | # define __NR_bpf 6319 | |
60 | # elif defined(__mips__) && defined(_ABI64) | |
61 | # define __NR_bpf 5315 | |
e3ed2fef WN |
62 | # else |
63 | # error __NR_bpf not defined. libbpf does not support your arch. | |
64 | # endif | |
65 | #endif | |
66 | ||
cdc6a4ba | 67 | static inline __u64 ptr_to_u64(const void *ptr) |
7bf98369 WN |
68 | { |
69 | return (__u64) (unsigned long) ptr; | |
70 | } | |
71 | ||
cdc6a4ba MS |
72 | static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, |
73 | unsigned int size) | |
e3ed2fef WN |
74 | { |
75 | return syscall(__NR_bpf, cmd, attr, size); | |
76 | } | |
77 | ||
549a6323 KKD |
78 | static inline int sys_bpf_fd(enum bpf_cmd cmd, union bpf_attr *attr, |
79 | unsigned int size) | |
80 | { | |
81 | int fd; | |
82 | ||
83 | fd = sys_bpf(cmd, attr, size); | |
84 | return ensure_good_fd(fd); | |
85 | } | |
86 | ||
1f235777 | 87 | int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts) |
86edaed3 LB |
88 | { |
89 | int fd; | |
90 | ||
91 | do { | |
549a6323 | 92 | fd = sys_bpf_fd(BPF_PROG_LOAD, attr, size); |
45493cba | 93 | } while (fd < 0 && errno == EAGAIN && --attempts > 0); |
86edaed3 LB |
94 | |
95 | return fd; | |
96 | } | |
97 | ||
e542f2c4 AN |
98 | /* Probe whether kernel switched from memlock-based (RLIMIT_MEMLOCK) to |
99 | * memcg-based memory accounting for BPF maps and progs. This was done in [0]. | |
100 | * We use the support for bpf_ktime_get_coarse_ns() helper, which was added in | |
101 | * the same 5.11 Linux release ([1]), to detect memcg-based accounting for BPF. | |
102 | * | |
103 | * [0] https://lore.kernel.org/bpf/20201201215900.3569844-1-guro@fb.com/ | |
104 | * [1] d05512618056 ("bpf: Add bpf_ktime_get_coarse_ns helper") | |
105 | */ | |
f3dcee93 | 106 | int probe_memcg_account(int token_fd) |
e542f2c4 | 107 | { |
1de27bba | 108 | const size_t attr_sz = offsetofend(union bpf_attr, prog_token_fd); |
e542f2c4 AN |
109 | struct bpf_insn insns[] = { |
110 | BPF_EMIT_CALL(BPF_FUNC_ktime_get_coarse_ns), | |
111 | BPF_EXIT_INSN(), | |
112 | }; | |
04b6de64 | 113 | size_t insn_cnt = ARRAY_SIZE(insns); |
e542f2c4 AN |
114 | union bpf_attr attr; |
115 | int prog_fd; | |
116 | ||
117 | /* attempt loading freplace trying to use custom BTF */ | |
813847a3 | 118 | memset(&attr, 0, attr_sz); |
e542f2c4 AN |
119 | attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER; |
120 | attr.insns = ptr_to_u64(insns); | |
121 | attr.insn_cnt = insn_cnt; | |
122 | attr.license = ptr_to_u64("GPL"); | |
f3dcee93 AN |
123 | attr.prog_token_fd = token_fd; |
124 | if (token_fd) | |
125 | attr.prog_flags |= BPF_F_TOKEN_FD; | |
e542f2c4 | 126 | |
813847a3 | 127 | prog_fd = sys_bpf_fd(BPF_PROG_LOAD, &attr, attr_sz); |
e542f2c4 AN |
128 | if (prog_fd >= 0) { |
129 | close(prog_fd); | |
130 | return 1; | |
131 | } | |
132 | return 0; | |
133 | } | |
134 | ||
135 | static bool memlock_bumped; | |
136 | static rlim_t memlock_rlim = RLIM_INFINITY; | |
137 | ||
138 | int libbpf_set_memlock_rlim(size_t memlock_bytes) | |
139 | { | |
140 | if (memlock_bumped) | |
141 | return libbpf_err(-EBUSY); | |
142 | ||
143 | memlock_rlim = memlock_bytes; | |
144 | return 0; | |
145 | } | |
146 | ||
147 | int bump_rlimit_memlock(void) | |
148 | { | |
149 | struct rlimit rlim; | |
150 | ||
e542f2c4 | 151 | /* if kernel supports memcg-based accounting, skip bumping RLIMIT_MEMLOCK */ |
d6dd1d49 | 152 | if (memlock_bumped || feat_supported(NULL, FEAT_MEMCG_ACCOUNT)) |
e542f2c4 AN |
153 | return 0; |
154 | ||
155 | memlock_bumped = true; | |
156 | ||
157 | /* zero memlock_rlim_max disables auto-bumping RLIMIT_MEMLOCK */ | |
158 | if (memlock_rlim == 0) | |
159 | return 0; | |
160 | ||
161 | rlim.rlim_cur = rlim.rlim_max = memlock_rlim; | |
162 | if (setrlimit(RLIMIT_MEMLOCK, &rlim)) | |
163 | return -errno; | |
164 | ||
165 | return 0; | |
166 | } | |
167 | ||
992c4225 AN |
168 | int bpf_map_create(enum bpf_map_type map_type, |
169 | const char *map_name, | |
170 | __u32 key_size, | |
171 | __u32 value_size, | |
172 | __u32 max_entries, | |
173 | const struct bpf_map_create_opts *opts) | |
e3ed2fef | 174 | { |
364f8483 | 175 | const size_t attr_sz = offsetofend(union bpf_attr, map_token_fd); |
e3ed2fef | 176 | union bpf_attr attr; |
f12b6543 | 177 | int fd; |
e3ed2fef | 178 | |
e542f2c4 AN |
179 | bump_rlimit_memlock(); |
180 | ||
992c4225 AN |
181 | memset(&attr, 0, attr_sz); |
182 | ||
183 | if (!OPTS_VALID(opts, bpf_map_create_opts)) | |
184 | return libbpf_err(-EINVAL); | |
185 | ||
186 | attr.map_type = map_type; | |
d6dd1d49 | 187 | if (map_name && feat_supported(NULL, FEAT_PROG_NAME)) |
9fc205b4 | 188 | libbpf_strlcpy(attr.map_name, map_name, sizeof(attr.map_name)); |
992c4225 AN |
189 | attr.key_size = key_size; |
190 | attr.value_size = value_size; | |
191 | attr.max_entries = max_entries; | |
192 | ||
193 | attr.btf_fd = OPTS_GET(opts, btf_fd, 0); | |
194 | attr.btf_key_type_id = OPTS_GET(opts, btf_key_type_id, 0); | |
195 | attr.btf_value_type_id = OPTS_GET(opts, btf_value_type_id, 0); | |
196 | attr.btf_vmlinux_value_type_id = OPTS_GET(opts, btf_vmlinux_value_type_id, 0); | |
c9f11556 | 197 | attr.value_type_btf_obj_fd = OPTS_GET(opts, value_type_btf_obj_fd, 0); |
992c4225 AN |
198 | |
199 | attr.inner_map_fd = OPTS_GET(opts, inner_map_fd, 0); | |
200 | attr.map_flags = OPTS_GET(opts, map_flags, 0); | |
201 | attr.map_extra = OPTS_GET(opts, map_extra, 0); | |
202 | attr.numa_node = OPTS_GET(opts, numa_node, 0); | |
203 | attr.map_ifindex = OPTS_GET(opts, map_ifindex, 0); | |
8a138aed | 204 | |
364f8483 AN |
205 | attr.map_token_fd = OPTS_GET(opts, token_fd, 0); |
206 | ||
992c4225 | 207 | fd = sys_bpf_fd(BPF_MAP_CREATE, &attr, attr_sz); |
f12b6543 | 208 | return libbpf_err_errno(fd); |
8a138aed | 209 | } |
88cda1c9 | 210 | |
3d650141 MKL |
211 | static void * |
212 | alloc_zero_tailing_info(const void *orecord, __u32 cnt, | |
213 | __u32 actual_rec_size, __u32 expected_rec_size) | |
214 | { | |
4ee11356 | 215 | __u64 info_len = (__u64)actual_rec_size * cnt; |
3d650141 MKL |
216 | void *info, *nrecord; |
217 | int i; | |
218 | ||
219 | info = malloc(info_len); | |
220 | if (!info) | |
221 | return NULL; | |
222 | ||
223 | /* zero out bytes kernel does not understand */ | |
224 | nrecord = info; | |
225 | for (i = 0; i < cnt; i++) { | |
226 | memcpy(nrecord, orecord, expected_rec_size); | |
227 | memset(nrecord + expected_rec_size, 0, | |
228 | actual_rec_size - expected_rec_size); | |
229 | orecord += actual_rec_size; | |
230 | nrecord += actual_rec_size; | |
231 | } | |
232 | ||
233 | return info; | |
234 | } | |
235 | ||
765a3413 AN |
236 | int bpf_prog_load(enum bpf_prog_type prog_type, |
237 | const char *prog_name, const char *license, | |
238 | const struct bpf_insn *insns, size_t insn_cnt, | |
94e55c0f | 239 | struct bpf_prog_load_opts *opts) |
7bf98369 | 240 | { |
f9933acd | 241 | const size_t attr_sz = offsetofend(union bpf_attr, fd_array_cnt); |
3d650141 | 242 | void *finfo = NULL, *linfo = NULL; |
d10ef2b8 AN |
243 | const char *func_info, *line_info; |
244 | __u32 log_size, log_level, attach_prog_fd, attach_btf_obj_fd; | |
245 | __u32 func_info_rec_size, line_info_rec_size; | |
246 | int fd, attempts; | |
7bf98369 | 247 | union bpf_attr attr; |
d10ef2b8 | 248 | char *log_buf; |
d7be143b | 249 | |
e542f2c4 AN |
250 | bump_rlimit_memlock(); |
251 | ||
d10ef2b8 | 252 | if (!OPTS_VALID(opts, bpf_prog_load_opts)) |
f12b6543 | 253 | return libbpf_err(-EINVAL); |
a4021a35 | 254 | |
d10ef2b8 AN |
255 | attempts = OPTS_GET(opts, attempts, 0); |
256 | if (attempts < 0) | |
f12b6543 | 257 | return libbpf_err(-EINVAL); |
d10ef2b8 AN |
258 | if (attempts == 0) |
259 | attempts = PROG_LOAD_ATTEMPTS; | |
d7be143b | 260 | |
813847a3 | 261 | memset(&attr, 0, attr_sz); |
6aef10a4 | 262 | |
d10ef2b8 AN |
263 | attr.prog_type = prog_type; |
264 | attr.expected_attach_type = OPTS_GET(opts, expected_attach_type, 0); | |
6aef10a4 | 265 | |
d10ef2b8 AN |
266 | attr.prog_btf_fd = OPTS_GET(opts, prog_btf_fd, 0); |
267 | attr.prog_flags = OPTS_GET(opts, prog_flags, 0); | |
268 | attr.prog_ifindex = OPTS_GET(opts, prog_ifindex, 0); | |
269 | attr.kern_version = OPTS_GET(opts, kern_version, 0); | |
404cbc14 | 270 | attr.prog_token_fd = OPTS_GET(opts, token_fd, 0); |
6aef10a4 | 271 | |
d6dd1d49 | 272 | if (prog_name && feat_supported(NULL, FEAT_PROG_NAME)) |
9fc205b4 | 273 | libbpf_strlcpy(attr.prog_name, prog_name, sizeof(attr.prog_name)); |
d10ef2b8 | 274 | attr.license = ptr_to_u64(license); |
a4021a35 | 275 | |
d10ef2b8 AN |
276 | if (insn_cnt > UINT_MAX) |
277 | return libbpf_err(-E2BIG); | |
278 | ||
279 | attr.insns = ptr_to_u64(insns); | |
280 | attr.insn_cnt = (__u32)insn_cnt; | |
281 | ||
282 | attach_prog_fd = OPTS_GET(opts, attach_prog_fd, 0); | |
283 | attach_btf_obj_fd = OPTS_GET(opts, attach_btf_obj_fd, 0); | |
284 | ||
285 | if (attach_prog_fd && attach_btf_obj_fd) | |
286 | return libbpf_err(-EINVAL); | |
287 | ||
288 | attr.attach_btf_id = OPTS_GET(opts, attach_btf_id, 0); | |
289 | if (attach_prog_fd) | |
290 | attr.attach_prog_fd = attach_prog_fd; | |
291 | else | |
292 | attr.attach_btf_obj_fd = attach_btf_obj_fd; | |
a4021a35 | 293 | |
d10ef2b8 AN |
294 | log_buf = OPTS_GET(opts, log_buf, NULL); |
295 | log_size = OPTS_GET(opts, log_size, 0); | |
296 | log_level = OPTS_GET(opts, log_level, 0); | |
6aef10a4 | 297 | |
d10ef2b8 AN |
298 | if (!!log_buf != !!log_size) |
299 | return libbpf_err(-EINVAL); | |
6aef10a4 | 300 | |
d10ef2b8 AN |
301 | func_info_rec_size = OPTS_GET(opts, func_info_rec_size, 0); |
302 | func_info = OPTS_GET(opts, func_info, NULL); | |
303 | attr.func_info_rec_size = func_info_rec_size; | |
304 | attr.func_info = ptr_to_u64(func_info); | |
305 | attr.func_info_cnt = OPTS_GET(opts, func_info_cnt, 0); | |
7bf98369 | 306 | |
d10ef2b8 AN |
307 | line_info_rec_size = OPTS_GET(opts, line_info_rec_size, 0); |
308 | line_info = OPTS_GET(opts, line_info, NULL); | |
309 | attr.line_info_rec_size = line_info_rec_size; | |
310 | attr.line_info = ptr_to_u64(line_info); | |
311 | attr.line_info_cnt = OPTS_GET(opts, line_info_cnt, 0); | |
6aef10a4 | 312 | |
d10ef2b8 | 313 | attr.fd_array = ptr_to_u64(OPTS_GET(opts, fd_array, NULL)); |
f9933acd | 314 | attr.fd_array_cnt = OPTS_GET(opts, fd_array_cnt, 0); |
7bf98369 | 315 | |
4cf23a3c AN |
316 | if (log_level) { |
317 | attr.log_buf = ptr_to_u64(log_buf); | |
318 | attr.log_size = log_size; | |
319 | attr.log_level = log_level; | |
320 | } | |
321 | ||
813847a3 | 322 | fd = sys_bpf_prog_load(&attr, attr_sz, attempts); |
94e55c0f | 323 | OPTS_SET(opts, log_true_size, attr.log_true_size); |
f0187f0b | 324 | if (fd >= 0) |
7bf98369 WN |
325 | return fd; |
326 | ||
2993e051 YS |
327 | /* After bpf_prog_load, the kernel may modify certain attributes |
328 | * to give user space a hint how to deal with loading failure. | |
329 | * Check to see whether we can make some changes and load again. | |
330 | */ | |
3d650141 MKL |
331 | while (errno == E2BIG && (!finfo || !linfo)) { |
332 | if (!finfo && attr.func_info_cnt && | |
d10ef2b8 | 333 | attr.func_info_rec_size < func_info_rec_size) { |
3d650141 | 334 | /* try with corrected func info records */ |
d10ef2b8 AN |
335 | finfo = alloc_zero_tailing_info(func_info, |
336 | attr.func_info_cnt, | |
337 | func_info_rec_size, | |
3d650141 | 338 | attr.func_info_rec_size); |
f12b6543 AN |
339 | if (!finfo) { |
340 | errno = E2BIG; | |
3d650141 | 341 | goto done; |
f12b6543 | 342 | } |
3d650141 MKL |
343 | |
344 | attr.func_info = ptr_to_u64(finfo); | |
d10ef2b8 | 345 | attr.func_info_rec_size = func_info_rec_size; |
3d650141 | 346 | } else if (!linfo && attr.line_info_cnt && |
d10ef2b8 AN |
347 | attr.line_info_rec_size < line_info_rec_size) { |
348 | linfo = alloc_zero_tailing_info(line_info, | |
349 | attr.line_info_cnt, | |
350 | line_info_rec_size, | |
3d650141 | 351 | attr.line_info_rec_size); |
f12b6543 AN |
352 | if (!linfo) { |
353 | errno = E2BIG; | |
3d650141 | 354 | goto done; |
f12b6543 | 355 | } |
3d650141 MKL |
356 | |
357 | attr.line_info = ptr_to_u64(linfo); | |
d10ef2b8 | 358 | attr.line_info_rec_size = line_info_rec_size; |
3d650141 MKL |
359 | } else { |
360 | break; | |
2993e051 YS |
361 | } |
362 | ||
813847a3 | 363 | fd = sys_bpf_prog_load(&attr, attr_sz, attempts); |
94e55c0f | 364 | OPTS_SET(opts, log_true_size, attr.log_true_size); |
f0187f0b | 365 | if (fd >= 0) |
2993e051 YS |
366 | goto done; |
367 | } | |
368 | ||
4cf23a3c AN |
369 | if (log_level == 0 && log_buf) { |
370 | /* log_level == 0 with non-NULL log_buf requires retrying on error | |
371 | * with log_level == 1 and log_buf/log_buf_size set, to get details of | |
372 | * failure | |
373 | */ | |
374 | attr.log_buf = ptr_to_u64(log_buf); | |
375 | attr.log_size = log_size; | |
376 | attr.log_level = 1; | |
6aef10a4 | 377 | |
813847a3 | 378 | fd = sys_bpf_prog_load(&attr, attr_sz, attempts); |
94e55c0f | 379 | OPTS_SET(opts, log_true_size, attr.log_true_size); |
4cf23a3c | 380 | } |
2993e051 | 381 | done: |
f12b6543 | 382 | /* free() doesn't affect errno, so we don't need to restore it */ |
2993e051 | 383 | free(finfo); |
3d650141 | 384 | free(linfo); |
f12b6543 | 385 | return libbpf_err_errno(fd); |
7bf98369 | 386 | } |
43798bf3 | 387 | |
10ecc728 | 388 | int bpf_map_update_elem(int fd, const void *key, const void *value, |
83d994d0 | 389 | __u64 flags) |
43798bf3 | 390 | { |
813847a3 | 391 | const size_t attr_sz = offsetofend(union bpf_attr, flags); |
43798bf3 | 392 | union bpf_attr attr; |
f12b6543 | 393 | int ret; |
43798bf3 | 394 | |
813847a3 | 395 | memset(&attr, 0, attr_sz); |
43798bf3 HK |
396 | attr.map_fd = fd; |
397 | attr.key = ptr_to_u64(key); | |
398 | attr.value = ptr_to_u64(value); | |
399 | attr.flags = flags; | |
400 | ||
813847a3 | 401 | ret = sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, attr_sz); |
f12b6543 | 402 | return libbpf_err_errno(ret); |
43798bf3 | 403 | } |
9742da01 | 404 | |
e5ff7c40 | 405 | int bpf_map_lookup_elem(int fd, const void *key, void *value) |
9742da01 | 406 | { |
813847a3 | 407 | const size_t attr_sz = offsetofend(union bpf_attr, flags); |
9742da01 | 408 | union bpf_attr attr; |
f12b6543 | 409 | int ret; |
9742da01 | 410 | |
813847a3 | 411 | memset(&attr, 0, attr_sz); |
9742da01 WN |
412 | attr.map_fd = fd; |
413 | attr.key = ptr_to_u64(key); | |
414 | attr.value = ptr_to_u64(value); | |
415 | ||
813847a3 | 416 | ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, attr_sz); |
f12b6543 | 417 | return libbpf_err_errno(ret); |
9742da01 WN |
418 | } |
419 | ||
df5d22fa AS |
420 | int bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags) |
421 | { | |
813847a3 | 422 | const size_t attr_sz = offsetofend(union bpf_attr, flags); |
df5d22fa | 423 | union bpf_attr attr; |
f12b6543 | 424 | int ret; |
df5d22fa | 425 | |
813847a3 | 426 | memset(&attr, 0, attr_sz); |
df5d22fa AS |
427 | attr.map_fd = fd; |
428 | attr.key = ptr_to_u64(key); | |
429 | attr.value = ptr_to_u64(value); | |
430 | attr.flags = flags; | |
431 | ||
813847a3 | 432 | ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, attr_sz); |
f12b6543 | 433 | return libbpf_err_errno(ret); |
df5d22fa AS |
434 | } |
435 | ||
43b987d2 MV |
436 | int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value) |
437 | { | |
813847a3 | 438 | const size_t attr_sz = offsetofend(union bpf_attr, flags); |
43b987d2 | 439 | union bpf_attr attr; |
f12b6543 | 440 | int ret; |
43b987d2 | 441 | |
813847a3 | 442 | memset(&attr, 0, attr_sz); |
43b987d2 MV |
443 | attr.map_fd = fd; |
444 | attr.key = ptr_to_u64(key); | |
445 | attr.value = ptr_to_u64(value); | |
446 | ||
813847a3 | 447 | ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, attr_sz); |
f12b6543 | 448 | return libbpf_err_errno(ret); |
43b987d2 MV |
449 | } |
450 | ||
d59b9f2d DS |
451 | int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key, void *value, __u64 flags) |
452 | { | |
813847a3 | 453 | const size_t attr_sz = offsetofend(union bpf_attr, flags); |
d59b9f2d | 454 | union bpf_attr attr; |
64165ddf | 455 | int ret; |
d59b9f2d | 456 | |
813847a3 | 457 | memset(&attr, 0, attr_sz); |
d59b9f2d DS |
458 | attr.map_fd = fd; |
459 | attr.key = ptr_to_u64(key); | |
460 | attr.value = ptr_to_u64(value); | |
461 | attr.flags = flags; | |
462 | ||
813847a3 | 463 | ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, attr_sz); |
64165ddf | 464 | return libbpf_err_errno(ret); |
d59b9f2d DS |
465 | } |
466 | ||
e58383b8 | 467 | int bpf_map_delete_elem(int fd, const void *key) |
9742da01 | 468 | { |
813847a3 | 469 | const size_t attr_sz = offsetofend(union bpf_attr, flags); |
9742da01 | 470 | union bpf_attr attr; |
f12b6543 | 471 | int ret; |
9742da01 | 472 | |
813847a3 | 473 | memset(&attr, 0, attr_sz); |
9742da01 WN |
474 | attr.map_fd = fd; |
475 | attr.key = ptr_to_u64(key); | |
476 | ||
813847a3 | 477 | ret = sys_bpf(BPF_MAP_DELETE_ELEM, &attr, attr_sz); |
f12b6543 | 478 | return libbpf_err_errno(ret); |
9742da01 WN |
479 | } |
480 | ||
737d0646 AN |
481 | int bpf_map_delete_elem_flags(int fd, const void *key, __u64 flags) |
482 | { | |
813847a3 | 483 | const size_t attr_sz = offsetofend(union bpf_attr, flags); |
737d0646 AN |
484 | union bpf_attr attr; |
485 | int ret; | |
486 | ||
813847a3 | 487 | memset(&attr, 0, attr_sz); |
737d0646 AN |
488 | attr.map_fd = fd; |
489 | attr.key = ptr_to_u64(key); | |
490 | attr.flags = flags; | |
491 | ||
813847a3 | 492 | ret = sys_bpf(BPF_MAP_DELETE_ELEM, &attr, attr_sz); |
737d0646 AN |
493 | return libbpf_err_errno(ret); |
494 | } | |
495 | ||
5f155c25 | 496 | int bpf_map_get_next_key(int fd, const void *key, void *next_key) |
9742da01 | 497 | { |
813847a3 | 498 | const size_t attr_sz = offsetofend(union bpf_attr, next_key); |
9742da01 | 499 | union bpf_attr attr; |
f12b6543 | 500 | int ret; |
9742da01 | 501 | |
813847a3 | 502 | memset(&attr, 0, attr_sz); |
9742da01 WN |
503 | attr.map_fd = fd; |
504 | attr.key = ptr_to_u64(key); | |
505 | attr.next_key = ptr_to_u64(next_key); | |
506 | ||
813847a3 | 507 | ret = sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, attr_sz); |
f12b6543 | 508 | return libbpf_err_errno(ret); |
9742da01 WN |
509 | } |
510 | ||
d859900c DB |
511 | int bpf_map_freeze(int fd) |
512 | { | |
813847a3 | 513 | const size_t attr_sz = offsetofend(union bpf_attr, map_fd); |
d859900c | 514 | union bpf_attr attr; |
f12b6543 | 515 | int ret; |
d859900c | 516 | |
813847a3 | 517 | memset(&attr, 0, attr_sz); |
d859900c DB |
518 | attr.map_fd = fd; |
519 | ||
813847a3 | 520 | ret = sys_bpf(BPF_MAP_FREEZE, &attr, attr_sz); |
f12b6543 | 521 | return libbpf_err_errno(ret); |
d859900c DB |
522 | } |
523 | ||
2ab3d86e YS |
524 | static int bpf_map_batch_common(int cmd, int fd, void *in_batch, |
525 | void *out_batch, void *keys, void *values, | |
526 | __u32 *count, | |
527 | const struct bpf_map_batch_opts *opts) | |
528 | { | |
813847a3 | 529 | const size_t attr_sz = offsetofend(union bpf_attr, batch); |
858e284f | 530 | union bpf_attr attr; |
2ab3d86e YS |
531 | int ret; |
532 | ||
533 | if (!OPTS_VALID(opts, bpf_map_batch_opts)) | |
f12b6543 | 534 | return libbpf_err(-EINVAL); |
2ab3d86e | 535 | |
813847a3 | 536 | memset(&attr, 0, attr_sz); |
2ab3d86e YS |
537 | attr.batch.map_fd = fd; |
538 | attr.batch.in_batch = ptr_to_u64(in_batch); | |
539 | attr.batch.out_batch = ptr_to_u64(out_batch); | |
540 | attr.batch.keys = ptr_to_u64(keys); | |
541 | attr.batch.values = ptr_to_u64(values); | |
542 | attr.batch.count = *count; | |
543 | attr.batch.elem_flags = OPTS_GET(opts, elem_flags, 0); | |
544 | attr.batch.flags = OPTS_GET(opts, flags, 0); | |
545 | ||
813847a3 | 546 | ret = sys_bpf(cmd, &attr, attr_sz); |
2ab3d86e YS |
547 | *count = attr.batch.count; |
548 | ||
f12b6543 | 549 | return libbpf_err_errno(ret); |
2ab3d86e YS |
550 | } |
551 | ||
e59618f0 | 552 | int bpf_map_delete_batch(int fd, const void *keys, __u32 *count, |
2ab3d86e YS |
553 | const struct bpf_map_batch_opts *opts) |
554 | { | |
555 | return bpf_map_batch_common(BPF_MAP_DELETE_BATCH, fd, NULL, | |
e59618f0 | 556 | NULL, (void *)keys, NULL, count, opts); |
2ab3d86e YS |
557 | } |
558 | ||
559 | int bpf_map_lookup_batch(int fd, void *in_batch, void *out_batch, void *keys, | |
560 | void *values, __u32 *count, | |
561 | const struct bpf_map_batch_opts *opts) | |
562 | { | |
563 | return bpf_map_batch_common(BPF_MAP_LOOKUP_BATCH, fd, in_batch, | |
564 | out_batch, keys, values, count, opts); | |
565 | } | |
566 | ||
567 | int bpf_map_lookup_and_delete_batch(int fd, void *in_batch, void *out_batch, | |
568 | void *keys, void *values, __u32 *count, | |
569 | const struct bpf_map_batch_opts *opts) | |
570 | { | |
571 | return bpf_map_batch_common(BPF_MAP_LOOKUP_AND_DELETE_BATCH, | |
572 | fd, in_batch, out_batch, keys, values, | |
573 | count, opts); | |
574 | } | |
575 | ||
e59618f0 | 576 | int bpf_map_update_batch(int fd, const void *keys, const void *values, __u32 *count, |
2ab3d86e YS |
577 | const struct bpf_map_batch_opts *opts) |
578 | { | |
579 | return bpf_map_batch_common(BPF_MAP_UPDATE_BATCH, fd, NULL, NULL, | |
e59618f0 | 580 | (void *)keys, (void *)values, count, opts); |
2ab3d86e YS |
581 | } |
582 | ||
f1674dc7 | 583 | int bpf_obj_pin_opts(int fd, const char *pathname, const struct bpf_obj_pin_opts *opts) |
9742da01 | 584 | { |
f1674dc7 | 585 | const size_t attr_sz = offsetofend(union bpf_attr, path_fd); |
9742da01 | 586 | union bpf_attr attr; |
f12b6543 | 587 | int ret; |
9742da01 | 588 | |
f1674dc7 AN |
589 | if (!OPTS_VALID(opts, bpf_obj_pin_opts)) |
590 | return libbpf_err(-EINVAL); | |
591 | ||
813847a3 | 592 | memset(&attr, 0, attr_sz); |
f1674dc7 | 593 | attr.path_fd = OPTS_GET(opts, path_fd, 0); |
9742da01 | 594 | attr.pathname = ptr_to_u64((void *)pathname); |
f1674dc7 | 595 | attr.file_flags = OPTS_GET(opts, file_flags, 0); |
9742da01 WN |
596 | attr.bpf_fd = fd; |
597 | ||
813847a3 | 598 | ret = sys_bpf(BPF_OBJ_PIN, &attr, attr_sz); |
f12b6543 | 599 | return libbpf_err_errno(ret); |
9742da01 WN |
600 | } |
601 | ||
f1674dc7 AN |
602 | int bpf_obj_pin(int fd, const char *pathname) |
603 | { | |
604 | return bpf_obj_pin_opts(fd, pathname, NULL); | |
605 | } | |
606 | ||
9742da01 | 607 | int bpf_obj_get(const char *pathname) |
395fc4fa JB |
608 | { |
609 | return bpf_obj_get_opts(pathname, NULL); | |
610 | } | |
611 | ||
612 | int bpf_obj_get_opts(const char *pathname, const struct bpf_obj_get_opts *opts) | |
9742da01 | 613 | { |
f1674dc7 | 614 | const size_t attr_sz = offsetofend(union bpf_attr, path_fd); |
9742da01 | 615 | union bpf_attr attr; |
f12b6543 | 616 | int fd; |
9742da01 | 617 | |
395fc4fa JB |
618 | if (!OPTS_VALID(opts, bpf_obj_get_opts)) |
619 | return libbpf_err(-EINVAL); | |
620 | ||
813847a3 | 621 | memset(&attr, 0, attr_sz); |
f1674dc7 | 622 | attr.path_fd = OPTS_GET(opts, path_fd, 0); |
9742da01 | 623 | attr.pathname = ptr_to_u64((void *)pathname); |
395fc4fa | 624 | attr.file_flags = OPTS_GET(opts, file_flags, 0); |
9742da01 | 625 | |
813847a3 | 626 | fd = sys_bpf_fd(BPF_OBJ_GET, &attr, attr_sz); |
f12b6543 | 627 | return libbpf_err_errno(fd); |
9742da01 | 628 | } |
5dc880de | 629 | |
464bc0fd JF |
630 | int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type, |
631 | unsigned int flags) | |
cdbee383 AI |
632 | { |
633 | DECLARE_LIBBPF_OPTS(bpf_prog_attach_opts, opts, | |
634 | .flags = flags, | |
635 | ); | |
636 | ||
d6c9c24e | 637 | return bpf_prog_attach_opts(prog_fd, target_fd, type, &opts); |
cdbee383 AI |
638 | } |
639 | ||
fe20ce3a DB |
640 | int bpf_prog_attach_opts(int prog_fd, int target, enum bpf_attach_type type, |
641 | const struct bpf_prog_attach_opts *opts) | |
5dc880de | 642 | { |
fe20ce3a DB |
643 | const size_t attr_sz = offsetofend(union bpf_attr, expected_revision); |
644 | __u32 relative_id, flags; | |
645 | int ret, relative_fd; | |
5dc880de JS |
646 | union bpf_attr attr; |
647 | ||
cdbee383 | 648 | if (!OPTS_VALID(opts, bpf_prog_attach_opts)) |
f12b6543 | 649 | return libbpf_err(-EINVAL); |
cdbee383 | 650 | |
fe20ce3a DB |
651 | relative_id = OPTS_GET(opts, relative_id, 0); |
652 | relative_fd = OPTS_GET(opts, relative_fd, 0); | |
653 | flags = OPTS_GET(opts, flags, 0); | |
654 | ||
655 | /* validate we don't have unexpected combinations of non-zero fields */ | |
656 | if (relative_fd && relative_id) | |
657 | return libbpf_err(-EINVAL); | |
658 | ||
813847a3 | 659 | memset(&attr, 0, attr_sz); |
fe20ce3a DB |
660 | attr.target_fd = target; |
661 | attr.attach_bpf_fd = prog_fd; | |
662 | attr.attach_type = type; | |
663 | attr.replace_bpf_fd = OPTS_GET(opts, replace_fd, 0); | |
664 | attr.expected_revision = OPTS_GET(opts, expected_revision, 0); | |
665 | ||
666 | if (relative_id) { | |
667 | attr.attach_flags = flags | BPF_F_ID; | |
668 | attr.relative_id = relative_id; | |
669 | } else { | |
670 | attr.attach_flags = flags; | |
671 | attr.relative_fd = relative_fd; | |
672 | } | |
5dc880de | 673 | |
813847a3 | 674 | ret = sys_bpf(BPF_PROG_ATTACH, &attr, attr_sz); |
f12b6543 | 675 | return libbpf_err_errno(ret); |
5dc880de JS |
676 | } |
677 | ||
fe20ce3a DB |
678 | int bpf_prog_detach_opts(int prog_fd, int target, enum bpf_attach_type type, |
679 | const struct bpf_prog_detach_opts *opts) | |
5dc880de | 680 | { |
fe20ce3a DB |
681 | const size_t attr_sz = offsetofend(union bpf_attr, expected_revision); |
682 | __u32 relative_id, flags; | |
683 | int ret, relative_fd; | |
5dc880de | 684 | union bpf_attr attr; |
fe20ce3a DB |
685 | |
686 | if (!OPTS_VALID(opts, bpf_prog_detach_opts)) | |
687 | return libbpf_err(-EINVAL); | |
688 | ||
689 | relative_id = OPTS_GET(opts, relative_id, 0); | |
690 | relative_fd = OPTS_GET(opts, relative_fd, 0); | |
691 | flags = OPTS_GET(opts, flags, 0); | |
692 | ||
693 | /* validate we don't have unexpected combinations of non-zero fields */ | |
694 | if (relative_fd && relative_id) | |
695 | return libbpf_err(-EINVAL); | |
5dc880de | 696 | |
813847a3 | 697 | memset(&attr, 0, attr_sz); |
fe20ce3a DB |
698 | attr.target_fd = target; |
699 | attr.attach_bpf_fd = prog_fd; | |
700 | attr.attach_type = type; | |
701 | attr.expected_revision = OPTS_GET(opts, expected_revision, 0); | |
702 | ||
703 | if (relative_id) { | |
704 | attr.attach_flags = flags | BPF_F_ID; | |
705 | attr.relative_id = relative_id; | |
706 | } else { | |
707 | attr.attach_flags = flags; | |
708 | attr.relative_fd = relative_fd; | |
709 | } | |
5dc880de | 710 | |
813847a3 | 711 | ret = sys_bpf(BPF_PROG_DETACH, &attr, attr_sz); |
f12b6543 | 712 | return libbpf_err_errno(ret); |
5dc880de | 713 | } |
30848873 | 714 | |
fe20ce3a | 715 | int bpf_prog_detach(int target_fd, enum bpf_attach_type type) |
244d20ef | 716 | { |
fe20ce3a DB |
717 | return bpf_prog_detach_opts(0, target_fd, type, NULL); |
718 | } | |
244d20ef | 719 | |
fe20ce3a DB |
720 | int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type) |
721 | { | |
722 | return bpf_prog_detach_opts(prog_fd, target_fd, type, NULL); | |
244d20ef AS |
723 | } |
724 | ||
cc4f864b AN |
725 | int bpf_link_create(int prog_fd, int target_fd, |
726 | enum bpf_attach_type attach_type, | |
727 | const struct bpf_link_create_opts *opts) | |
728 | { | |
813847a3 | 729 | const size_t attr_sz = offsetofend(union bpf_attr, link_create); |
55cc3768 DB |
730 | __u32 target_btf_id, iter_info_len, relative_id; |
731 | int fd, err, relative_fd; | |
cc4f864b AN |
732 | union bpf_attr attr; |
733 | ||
734 | if (!OPTS_VALID(opts, bpf_link_create_opts)) | |
f12b6543 | 735 | return libbpf_err(-EINVAL); |
cc4f864b | 736 | |
a5359091 THJ |
737 | iter_info_len = OPTS_GET(opts, iter_info_len, 0); |
738 | target_btf_id = OPTS_GET(opts, target_btf_id, 0); | |
739 | ||
3ec84f4b AN |
740 | /* validate we don't have unexpected combinations of non-zero fields */ |
741 | if (iter_info_len || target_btf_id) { | |
742 | if (iter_info_len && target_btf_id) | |
743 | return libbpf_err(-EINVAL); | |
744 | if (!OPTS_ZEROED(opts, target_btf_id)) | |
745 | return libbpf_err(-EINVAL); | |
746 | } | |
a5359091 | 747 | |
813847a3 | 748 | memset(&attr, 0, attr_sz); |
cc4f864b AN |
749 | attr.link_create.prog_fd = prog_fd; |
750 | attr.link_create.target_fd = target_fd; | |
751 | attr.link_create.attach_type = attach_type; | |
cd31039a | 752 | attr.link_create.flags = OPTS_GET(opts, flags, 0); |
a5359091 | 753 | |
3ec84f4b | 754 | if (target_btf_id) { |
a5359091 | 755 | attr.link_create.target_btf_id = target_btf_id; |
3ec84f4b | 756 | goto proceed; |
a5359091 | 757 | } |
cc4f864b | 758 | |
3ec84f4b AN |
759 | switch (attach_type) { |
760 | case BPF_TRACE_ITER: | |
761 | attr.link_create.iter_info = ptr_to_u64(OPTS_GET(opts, iter_info, (void *)0)); | |
762 | attr.link_create.iter_info_len = iter_info_len; | |
763 | break; | |
764 | case BPF_PERF_EVENT: | |
765 | attr.link_create.perf_event.bpf_cookie = OPTS_GET(opts, perf_event.bpf_cookie, 0); | |
766 | if (!OPTS_ZEROED(opts, perf_event)) | |
767 | return libbpf_err(-EINVAL); | |
5117c26e JO |
768 | break; |
769 | case BPF_TRACE_KPROBE_MULTI: | |
2ca178f0 | 770 | case BPF_TRACE_KPROBE_SESSION: |
5117c26e JO |
771 | attr.link_create.kprobe_multi.flags = OPTS_GET(opts, kprobe_multi.flags, 0); |
772 | attr.link_create.kprobe_multi.cnt = OPTS_GET(opts, kprobe_multi.cnt, 0); | |
773 | attr.link_create.kprobe_multi.syms = ptr_to_u64(OPTS_GET(opts, kprobe_multi.syms, 0)); | |
774 | attr.link_create.kprobe_multi.addrs = ptr_to_u64(OPTS_GET(opts, kprobe_multi.addrs, 0)); | |
775 | attr.link_create.kprobe_multi.cookies = ptr_to_u64(OPTS_GET(opts, kprobe_multi.cookies, 0)); | |
776 | if (!OPTS_ZEROED(opts, kprobe_multi)) | |
777 | return libbpf_err(-EINVAL); | |
3ec84f4b | 778 | break; |
5054a303 | 779 | case BPF_TRACE_UPROBE_MULTI: |
022367ec | 780 | case BPF_TRACE_UPROBE_SESSION: |
5054a303 JO |
781 | attr.link_create.uprobe_multi.flags = OPTS_GET(opts, uprobe_multi.flags, 0); |
782 | attr.link_create.uprobe_multi.cnt = OPTS_GET(opts, uprobe_multi.cnt, 0); | |
783 | attr.link_create.uprobe_multi.path = ptr_to_u64(OPTS_GET(opts, uprobe_multi.path, 0)); | |
784 | attr.link_create.uprobe_multi.offsets = ptr_to_u64(OPTS_GET(opts, uprobe_multi.offsets, 0)); | |
785 | attr.link_create.uprobe_multi.ref_ctr_offsets = ptr_to_u64(OPTS_GET(opts, uprobe_multi.ref_ctr_offsets, 0)); | |
786 | attr.link_create.uprobe_multi.cookies = ptr_to_u64(OPTS_GET(opts, uprobe_multi.cookies, 0)); | |
787 | attr.link_create.uprobe_multi.pid = OPTS_GET(opts, uprobe_multi.pid, 0); | |
788 | if (!OPTS_ZEROED(opts, uprobe_multi)) | |
789 | return libbpf_err(-EINVAL); | |
790 | break; | |
36ffb202 | 791 | case BPF_TRACE_RAW_TP: |
129b9c5e KFL |
792 | case BPF_TRACE_FENTRY: |
793 | case BPF_TRACE_FEXIT: | |
794 | case BPF_MODIFY_RETURN: | |
795 | case BPF_LSM_MAC: | |
796 | attr.link_create.tracing.cookie = OPTS_GET(opts, tracing.cookie, 0); | |
797 | if (!OPTS_ZEROED(opts, tracing)) | |
798 | return libbpf_err(-EINVAL); | |
799 | break; | |
52364abb FW |
800 | case BPF_NETFILTER: |
801 | attr.link_create.netfilter.pf = OPTS_GET(opts, netfilter.pf, 0); | |
802 | attr.link_create.netfilter.hooknum = OPTS_GET(opts, netfilter.hooknum, 0); | |
803 | attr.link_create.netfilter.priority = OPTS_GET(opts, netfilter.priority, 0); | |
804 | attr.link_create.netfilter.flags = OPTS_GET(opts, netfilter.flags, 0); | |
805 | if (!OPTS_ZEROED(opts, netfilter)) | |
806 | return libbpf_err(-EINVAL); | |
807 | break; | |
55cc3768 DB |
808 | case BPF_TCX_INGRESS: |
809 | case BPF_TCX_EGRESS: | |
810 | relative_fd = OPTS_GET(opts, tcx.relative_fd, 0); | |
811 | relative_id = OPTS_GET(opts, tcx.relative_id, 0); | |
812 | if (relative_fd && relative_id) | |
813 | return libbpf_err(-EINVAL); | |
814 | if (relative_id) { | |
815 | attr.link_create.tcx.relative_id = relative_id; | |
816 | attr.link_create.flags |= BPF_F_ID; | |
817 | } else { | |
818 | attr.link_create.tcx.relative_fd = relative_fd; | |
819 | } | |
820 | attr.link_create.tcx.expected_revision = OPTS_GET(opts, tcx.expected_revision, 0); | |
821 | if (!OPTS_ZEROED(opts, tcx)) | |
822 | return libbpf_err(-EINVAL); | |
823 | break; | |
05c31b4a DB |
824 | case BPF_NETKIT_PRIMARY: |
825 | case BPF_NETKIT_PEER: | |
826 | relative_fd = OPTS_GET(opts, netkit.relative_fd, 0); | |
827 | relative_id = OPTS_GET(opts, netkit.relative_id, 0); | |
828 | if (relative_fd && relative_id) | |
829 | return libbpf_err(-EINVAL); | |
830 | if (relative_id) { | |
831 | attr.link_create.netkit.relative_id = relative_id; | |
832 | attr.link_create.flags |= BPF_F_ID; | |
833 | } else { | |
834 | attr.link_create.netkit.relative_fd = relative_fd; | |
835 | } | |
836 | attr.link_create.netkit.expected_revision = OPTS_GET(opts, netkit.expected_revision, 0); | |
837 | if (!OPTS_ZEROED(opts, netkit)) | |
838 | return libbpf_err(-EINVAL); | |
839 | break; | |
3ec84f4b AN |
840 | default: |
841 | if (!OPTS_ZEROED(opts, flags)) | |
842 | return libbpf_err(-EINVAL); | |
843 | break; | |
844 | } | |
845 | proceed: | |
813847a3 | 846 | fd = sys_bpf_fd(BPF_LINK_CREATE, &attr, attr_sz); |
8462e0b4 AN |
847 | if (fd >= 0) |
848 | return fd; | |
849 | /* we'll get EINVAL if LINK_CREATE doesn't support attaching fentry | |
850 | * and other similar programs | |
851 | */ | |
852 | err = -errno; | |
853 | if (err != -EINVAL) | |
854 | return libbpf_err(err); | |
855 | ||
856 | /* if user used features not supported by | |
857 | * BPF_RAW_TRACEPOINT_OPEN command, then just give up immediately | |
858 | */ | |
859 | if (attr.link_create.target_fd || attr.link_create.target_btf_id) | |
860 | return libbpf_err(err); | |
861 | if (!OPTS_ZEROED(opts, sz)) | |
862 | return libbpf_err(err); | |
863 | ||
864 | /* otherwise, for few select kinds of programs that can be | |
865 | * attached using BPF_RAW_TRACEPOINT_OPEN command, try that as | |
866 | * a fallback for older kernels | |
867 | */ | |
868 | switch (attach_type) { | |
869 | case BPF_TRACE_RAW_TP: | |
870 | case BPF_LSM_MAC: | |
871 | case BPF_TRACE_FENTRY: | |
872 | case BPF_TRACE_FEXIT: | |
873 | case BPF_MODIFY_RETURN: | |
874 | return bpf_raw_tracepoint_open(NULL, prog_fd); | |
875 | default: | |
876 | return libbpf_err(err); | |
877 | } | |
cc4f864b AN |
878 | } |
879 | ||
2e49527e AN |
880 | int bpf_link_detach(int link_fd) |
881 | { | |
813847a3 | 882 | const size_t attr_sz = offsetofend(union bpf_attr, link_detach); |
2e49527e | 883 | union bpf_attr attr; |
f12b6543 | 884 | int ret; |
2e49527e | 885 | |
813847a3 | 886 | memset(&attr, 0, attr_sz); |
2e49527e AN |
887 | attr.link_detach.link_fd = link_fd; |
888 | ||
813847a3 | 889 | ret = sys_bpf(BPF_LINK_DETACH, &attr, attr_sz); |
f12b6543 | 890 | return libbpf_err_errno(ret); |
2e49527e AN |
891 | } |
892 | ||
cc4f864b AN |
893 | int bpf_link_update(int link_fd, int new_prog_fd, |
894 | const struct bpf_link_update_opts *opts) | |
895 | { | |
813847a3 | 896 | const size_t attr_sz = offsetofend(union bpf_attr, link_update); |
cc4f864b | 897 | union bpf_attr attr; |
f12b6543 | 898 | int ret; |
cc4f864b AN |
899 | |
900 | if (!OPTS_VALID(opts, bpf_link_update_opts)) | |
f12b6543 | 901 | return libbpf_err(-EINVAL); |
cc4f864b | 902 | |
912dd4b0 KFL |
903 | if (OPTS_GET(opts, old_prog_fd, 0) && OPTS_GET(opts, old_map_fd, 0)) |
904 | return libbpf_err(-EINVAL); | |
905 | ||
813847a3 | 906 | memset(&attr, 0, attr_sz); |
cc4f864b AN |
907 | attr.link_update.link_fd = link_fd; |
908 | attr.link_update.new_prog_fd = new_prog_fd; | |
909 | attr.link_update.flags = OPTS_GET(opts, flags, 0); | |
912dd4b0 KFL |
910 | if (OPTS_GET(opts, old_prog_fd, 0)) |
911 | attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0); | |
912 | else if (OPTS_GET(opts, old_map_fd, 0)) | |
913 | attr.link_update.old_map_fd = OPTS_GET(opts, old_map_fd, 0); | |
cc4f864b | 914 | |
813847a3 | 915 | ret = sys_bpf(BPF_LINK_UPDATE, &attr, attr_sz); |
f12b6543 | 916 | return libbpf_err_errno(ret); |
cc4f864b AN |
917 | } |
918 | ||
c09add2f YS |
919 | int bpf_iter_create(int link_fd) |
920 | { | |
813847a3 | 921 | const size_t attr_sz = offsetofend(union bpf_attr, iter_create); |
c09add2f | 922 | union bpf_attr attr; |
f12b6543 | 923 | int fd; |
c09add2f | 924 | |
813847a3 | 925 | memset(&attr, 0, attr_sz); |
c09add2f YS |
926 | attr.iter_create.link_fd = link_fd; |
927 | ||
813847a3 | 928 | fd = sys_bpf_fd(BPF_ITER_CREATE, &attr, attr_sz); |
f12b6543 | 929 | return libbpf_err_errno(fd); |
c09add2f YS |
930 | } |
931 | ||
fe20ce3a | 932 | int bpf_prog_query_opts(int target, enum bpf_attach_type type, |
a4b2f3cf | 933 | struct bpf_prog_query_opts *opts) |
5d0cbf9b | 934 | { |
813847a3 | 935 | const size_t attr_sz = offsetofend(union bpf_attr, query); |
5d0cbf9b AS |
936 | union bpf_attr attr; |
937 | int ret; | |
938 | ||
a4b2f3cf SF |
939 | if (!OPTS_VALID(opts, bpf_prog_query_opts)) |
940 | return libbpf_err(-EINVAL); | |
941 | ||
813847a3 | 942 | memset(&attr, 0, attr_sz); |
fe20ce3a DB |
943 | attr.query.target_fd = target; |
944 | attr.query.attach_type = type; | |
945 | attr.query.query_flags = OPTS_GET(opts, query_flags, 0); | |
946 | attr.query.count = OPTS_GET(opts, count, 0); | |
947 | attr.query.prog_ids = ptr_to_u64(OPTS_GET(opts, prog_ids, NULL)); | |
948 | attr.query.link_ids = ptr_to_u64(OPTS_GET(opts, link_ids, NULL)); | |
949 | attr.query.prog_attach_flags = ptr_to_u64(OPTS_GET(opts, prog_attach_flags, NULL)); | |
950 | attr.query.link_attach_flags = ptr_to_u64(OPTS_GET(opts, link_attach_flags, NULL)); | |
5d0cbf9b | 951 | |
813847a3 | 952 | ret = sys_bpf(BPF_PROG_QUERY, &attr, attr_sz); |
f12b6543 | 953 | |
a4b2f3cf | 954 | OPTS_SET(opts, attach_flags, attr.query.attach_flags); |
fe20ce3a DB |
955 | OPTS_SET(opts, revision, attr.query.revision); |
956 | OPTS_SET(opts, count, attr.query.count); | |
a4b2f3cf SF |
957 | |
958 | return libbpf_err_errno(ret); | |
959 | } | |
960 | ||
961 | int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags, | |
962 | __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt) | |
963 | { | |
964 | LIBBPF_OPTS(bpf_prog_query_opts, opts); | |
965 | int ret; | |
966 | ||
967 | opts.query_flags = query_flags; | |
968 | opts.prog_ids = prog_ids; | |
969 | opts.prog_cnt = *prog_cnt; | |
970 | ||
971 | ret = bpf_prog_query_opts(target_fd, type, &opts); | |
972 | ||
5d0cbf9b | 973 | if (attach_flags) |
a4b2f3cf SF |
974 | *attach_flags = opts.attach_flags; |
975 | *prog_cnt = opts.prog_cnt; | |
f12b6543 AN |
976 | |
977 | return libbpf_err_errno(ret); | |
5d0cbf9b AS |
978 | } |
979 | ||
88f7fe72 SL |
980 | int bpf_prog_test_run_opts(int prog_fd, struct bpf_test_run_opts *opts) |
981 | { | |
813847a3 | 982 | const size_t attr_sz = offsetofend(union bpf_attr, test); |
88f7fe72 SL |
983 | union bpf_attr attr; |
984 | int ret; | |
985 | ||
986 | if (!OPTS_VALID(opts, bpf_test_run_opts)) | |
f12b6543 | 987 | return libbpf_err(-EINVAL); |
88f7fe72 | 988 | |
813847a3 | 989 | memset(&attr, 0, attr_sz); |
88f7fe72 | 990 | attr.test.prog_fd = prog_fd; |
24592ad1 | 991 | attr.test.batch_size = OPTS_GET(opts, batch_size, 0); |
88f7fe72 SL |
992 | attr.test.cpu = OPTS_GET(opts, cpu, 0); |
993 | attr.test.flags = OPTS_GET(opts, flags, 0); | |
994 | attr.test.repeat = OPTS_GET(opts, repeat, 0); | |
995 | attr.test.duration = OPTS_GET(opts, duration, 0); | |
996 | attr.test.ctx_size_in = OPTS_GET(opts, ctx_size_in, 0); | |
997 | attr.test.ctx_size_out = OPTS_GET(opts, ctx_size_out, 0); | |
998 | attr.test.data_size_in = OPTS_GET(opts, data_size_in, 0); | |
999 | attr.test.data_size_out = OPTS_GET(opts, data_size_out, 0); | |
1000 | attr.test.ctx_in = ptr_to_u64(OPTS_GET(opts, ctx_in, NULL)); | |
1001 | attr.test.ctx_out = ptr_to_u64(OPTS_GET(opts, ctx_out, NULL)); | |
1002 | attr.test.data_in = ptr_to_u64(OPTS_GET(opts, data_in, NULL)); | |
1003 | attr.test.data_out = ptr_to_u64(OPTS_GET(opts, data_out, NULL)); | |
1004 | ||
813847a3 | 1005 | ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, attr_sz); |
f12b6543 | 1006 | |
88f7fe72 SL |
1007 | OPTS_SET(opts, data_size_out, attr.test.data_size_out); |
1008 | OPTS_SET(opts, ctx_size_out, attr.test.ctx_size_out); | |
1009 | OPTS_SET(opts, duration, attr.test.duration); | |
1010 | OPTS_SET(opts, retval, attr.test.retval); | |
f12b6543 AN |
1011 | |
1012 | return libbpf_err_errno(ret); | |
88f7fe72 SL |
1013 | } |
1014 | ||
a6e130c4 | 1015 | static int bpf_obj_get_next_id(__u32 start_id, __u32 *next_id, int cmd) |
95b9afd3 | 1016 | { |
813847a3 | 1017 | const size_t attr_sz = offsetofend(union bpf_attr, open_flags); |
95b9afd3 MKL |
1018 | union bpf_attr attr; |
1019 | int err; | |
1020 | ||
813847a3 | 1021 | memset(&attr, 0, attr_sz); |
95b9afd3 MKL |
1022 | attr.start_id = start_id; |
1023 | ||
813847a3 | 1024 | err = sys_bpf(cmd, &attr, attr_sz); |
95b9afd3 MKL |
1025 | if (!err) |
1026 | *next_id = attr.next_id; | |
1027 | ||
f12b6543 | 1028 | return libbpf_err_errno(err); |
95b9afd3 MKL |
1029 | } |
1030 | ||
a6e130c4 | 1031 | int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id) |
95b9afd3 | 1032 | { |
a6e130c4 QM |
1033 | return bpf_obj_get_next_id(start_id, next_id, BPF_PROG_GET_NEXT_ID); |
1034 | } | |
95b9afd3 | 1035 | |
a6e130c4 QM |
1036 | int bpf_map_get_next_id(__u32 start_id, __u32 *next_id) |
1037 | { | |
1038 | return bpf_obj_get_next_id(start_id, next_id, BPF_MAP_GET_NEXT_ID); | |
95b9afd3 MKL |
1039 | } |
1040 | ||
09d7c2e3 QM |
1041 | int bpf_btf_get_next_id(__u32 start_id, __u32 *next_id) |
1042 | { | |
1043 | return bpf_obj_get_next_id(start_id, next_id, BPF_BTF_GET_NEXT_ID); | |
1044 | } | |
1045 | ||
0dbc8668 AN |
1046 | int bpf_link_get_next_id(__u32 start_id, __u32 *next_id) |
1047 | { | |
1048 | return bpf_obj_get_next_id(start_id, next_id, BPF_LINK_GET_NEXT_ID); | |
1049 | } | |
1050 | ||
8f13f168 RS |
1051 | int bpf_prog_get_fd_by_id_opts(__u32 id, |
1052 | const struct bpf_get_fd_by_id_opts *opts) | |
95b9afd3 | 1053 | { |
813847a3 | 1054 | const size_t attr_sz = offsetofend(union bpf_attr, open_flags); |
95b9afd3 | 1055 | union bpf_attr attr; |
f12b6543 | 1056 | int fd; |
95b9afd3 | 1057 | |
8f13f168 RS |
1058 | if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts)) |
1059 | return libbpf_err(-EINVAL); | |
1060 | ||
813847a3 | 1061 | memset(&attr, 0, attr_sz); |
95b9afd3 | 1062 | attr.prog_id = id; |
8f13f168 | 1063 | attr.open_flags = OPTS_GET(opts, open_flags, 0); |
95b9afd3 | 1064 | |
813847a3 | 1065 | fd = sys_bpf_fd(BPF_PROG_GET_FD_BY_ID, &attr, attr_sz); |
f12b6543 | 1066 | return libbpf_err_errno(fd); |
95b9afd3 MKL |
1067 | } |
1068 | ||
8f13f168 RS |
1069 | int bpf_prog_get_fd_by_id(__u32 id) |
1070 | { | |
1071 | return bpf_prog_get_fd_by_id_opts(id, NULL); | |
1072 | } | |
1073 | ||
243e3005 RS |
1074 | int bpf_map_get_fd_by_id_opts(__u32 id, |
1075 | const struct bpf_get_fd_by_id_opts *opts) | |
95b9afd3 | 1076 | { |
813847a3 | 1077 | const size_t attr_sz = offsetofend(union bpf_attr, open_flags); |
95b9afd3 | 1078 | union bpf_attr attr; |
f12b6543 | 1079 | int fd; |
95b9afd3 | 1080 | |
243e3005 RS |
1081 | if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts)) |
1082 | return libbpf_err(-EINVAL); | |
1083 | ||
813847a3 | 1084 | memset(&attr, 0, attr_sz); |
95b9afd3 | 1085 | attr.map_id = id; |
243e3005 | 1086 | attr.open_flags = OPTS_GET(opts, open_flags, 0); |
95b9afd3 | 1087 | |
813847a3 | 1088 | fd = sys_bpf_fd(BPF_MAP_GET_FD_BY_ID, &attr, attr_sz); |
f12b6543 | 1089 | return libbpf_err_errno(fd); |
95b9afd3 MKL |
1090 | } |
1091 | ||
243e3005 RS |
1092 | int bpf_map_get_fd_by_id(__u32 id) |
1093 | { | |
1094 | return bpf_map_get_fd_by_id_opts(id, NULL); | |
1095 | } | |
1096 | ||
2ce7cbf2 RS |
1097 | int bpf_btf_get_fd_by_id_opts(__u32 id, |
1098 | const struct bpf_get_fd_by_id_opts *opts) | |
cd8b8928 | 1099 | { |
974ef9f0 | 1100 | const size_t attr_sz = offsetofend(union bpf_attr, fd_by_id_token_fd); |
cd8b8928 | 1101 | union bpf_attr attr; |
f12b6543 | 1102 | int fd; |
cd8b8928 | 1103 | |
2ce7cbf2 RS |
1104 | if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts)) |
1105 | return libbpf_err(-EINVAL); | |
1106 | ||
813847a3 | 1107 | memset(&attr, 0, attr_sz); |
cd8b8928 | 1108 | attr.btf_id = id; |
2ce7cbf2 | 1109 | attr.open_flags = OPTS_GET(opts, open_flags, 0); |
974ef9f0 | 1110 | attr.fd_by_id_token_fd = OPTS_GET(opts, token_fd, 0); |
cd8b8928 | 1111 | |
813847a3 | 1112 | fd = sys_bpf_fd(BPF_BTF_GET_FD_BY_ID, &attr, attr_sz); |
f12b6543 | 1113 | return libbpf_err_errno(fd); |
cd8b8928 MKL |
1114 | } |
1115 | ||
2ce7cbf2 RS |
1116 | int bpf_btf_get_fd_by_id(__u32 id) |
1117 | { | |
1118 | return bpf_btf_get_fd_by_id_opts(id, NULL); | |
1119 | } | |
1120 | ||
97c8f9dd RS |
1121 | int bpf_link_get_fd_by_id_opts(__u32 id, |
1122 | const struct bpf_get_fd_by_id_opts *opts) | |
0dbc8668 | 1123 | { |
813847a3 | 1124 | const size_t attr_sz = offsetofend(union bpf_attr, open_flags); |
0dbc8668 | 1125 | union bpf_attr attr; |
f12b6543 | 1126 | int fd; |
0dbc8668 | 1127 | |
97c8f9dd RS |
1128 | if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts)) |
1129 | return libbpf_err(-EINVAL); | |
1130 | ||
813847a3 | 1131 | memset(&attr, 0, attr_sz); |
0dbc8668 | 1132 | attr.link_id = id; |
97c8f9dd | 1133 | attr.open_flags = OPTS_GET(opts, open_flags, 0); |
0dbc8668 | 1134 | |
813847a3 | 1135 | fd = sys_bpf_fd(BPF_LINK_GET_FD_BY_ID, &attr, attr_sz); |
f12b6543 | 1136 | return libbpf_err_errno(fd); |
0dbc8668 AN |
1137 | } |
1138 | ||
97c8f9dd RS |
1139 | int bpf_link_get_fd_by_id(__u32 id) |
1140 | { | |
1141 | return bpf_link_get_fd_by_id_opts(id, NULL); | |
1142 | } | |
1143 | ||
0dbc8668 | 1144 | int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len) |
95b9afd3 | 1145 | { |
813847a3 | 1146 | const size_t attr_sz = offsetofend(union bpf_attr, info); |
95b9afd3 MKL |
1147 | union bpf_attr attr; |
1148 | int err; | |
1149 | ||
813847a3 | 1150 | memset(&attr, 0, attr_sz); |
0dbc8668 | 1151 | attr.info.bpf_fd = bpf_fd; |
95b9afd3 MKL |
1152 | attr.info.info_len = *info_len; |
1153 | attr.info.info = ptr_to_u64(info); | |
1154 | ||
813847a3 | 1155 | err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, attr_sz); |
95b9afd3 MKL |
1156 | if (!err) |
1157 | *info_len = attr.info.info_len; | |
f12b6543 | 1158 | return libbpf_err_errno(err); |
95b9afd3 | 1159 | } |
949abbe8 | 1160 | |
55a9ed0e IL |
1161 | int bpf_prog_get_info_by_fd(int prog_fd, struct bpf_prog_info *info, __u32 *info_len) |
1162 | { | |
1163 | return bpf_obj_get_info_by_fd(prog_fd, info, info_len); | |
1164 | } | |
1165 | ||
1166 | int bpf_map_get_info_by_fd(int map_fd, struct bpf_map_info *info, __u32 *info_len) | |
1167 | { | |
1168 | return bpf_obj_get_info_by_fd(map_fd, info, info_len); | |
1169 | } | |
1170 | ||
1171 | int bpf_btf_get_info_by_fd(int btf_fd, struct bpf_btf_info *info, __u32 *info_len) | |
1172 | { | |
1173 | return bpf_obj_get_info_by_fd(btf_fd, info, info_len); | |
1174 | } | |
1175 | ||
1176 | int bpf_link_get_info_by_fd(int link_fd, struct bpf_link_info *info, __u32 *info_len) | |
1177 | { | |
1178 | return bpf_obj_get_info_by_fd(link_fd, info, info_len); | |
1179 | } | |
1180 | ||
36ffb202 | 1181 | int bpf_raw_tracepoint_open_opts(int prog_fd, struct bpf_raw_tp_opts *opts) |
a0fe3e57 | 1182 | { |
813847a3 | 1183 | const size_t attr_sz = offsetofend(union bpf_attr, raw_tracepoint); |
a0fe3e57 | 1184 | union bpf_attr attr; |
f12b6543 | 1185 | int fd; |
a0fe3e57 | 1186 | |
36ffb202 AN |
1187 | if (!OPTS_VALID(opts, bpf_raw_tp_opts)) |
1188 | return libbpf_err(-EINVAL); | |
1189 | ||
813847a3 | 1190 | memset(&attr, 0, attr_sz); |
a0fe3e57 | 1191 | attr.raw_tracepoint.prog_fd = prog_fd; |
36ffb202 AN |
1192 | attr.raw_tracepoint.name = ptr_to_u64(OPTS_GET(opts, tp_name, NULL)); |
1193 | attr.raw_tracepoint.cookie = OPTS_GET(opts, cookie, 0); | |
a0fe3e57 | 1194 | |
813847a3 | 1195 | fd = sys_bpf_fd(BPF_RAW_TRACEPOINT_OPEN, &attr, attr_sz); |
f12b6543 | 1196 | return libbpf_err_errno(fd); |
a0fe3e57 AS |
1197 | } |
1198 | ||
36ffb202 AN |
1199 | int bpf_raw_tracepoint_open(const char *name, int prog_fd) |
1200 | { | |
1201 | LIBBPF_OPTS(bpf_raw_tp_opts, opts, .tp_name = name); | |
1202 | ||
1203 | return bpf_raw_tracepoint_open_opts(prog_fd, &opts); | |
1204 | } | |
1205 | ||
097d8002 | 1206 | int bpf_btf_load(const void *btf_data, size_t btf_size, struct bpf_btf_load_opts *opts) |
8a138aed | 1207 | { |
a3d63e85 | 1208 | const size_t attr_sz = offsetofend(union bpf_attr, btf_token_fd); |
0ed08d67 AN |
1209 | union bpf_attr attr; |
1210 | char *log_buf; | |
1211 | size_t log_size; | |
1212 | __u32 log_level; | |
8a138aed MKL |
1213 | int fd; |
1214 | ||
e542f2c4 AN |
1215 | bump_rlimit_memlock(); |
1216 | ||
0ed08d67 AN |
1217 | memset(&attr, 0, attr_sz); |
1218 | ||
1219 | if (!OPTS_VALID(opts, bpf_btf_load_opts)) | |
1220 | return libbpf_err(-EINVAL); | |
1221 | ||
1222 | log_buf = OPTS_GET(opts, log_buf, NULL); | |
1223 | log_size = OPTS_GET(opts, log_size, 0); | |
1224 | log_level = OPTS_GET(opts, log_level, 0); | |
1225 | ||
1226 | if (log_size > UINT_MAX) | |
1227 | return libbpf_err(-EINVAL); | |
1228 | if (log_size && !log_buf) | |
1229 | return libbpf_err(-EINVAL); | |
1230 | ||
1231 | attr.btf = ptr_to_u64(btf_data); | |
8a138aed | 1232 | attr.btf_size = btf_size; |
a3d63e85 AN |
1233 | |
1234 | attr.btf_flags = OPTS_GET(opts, btf_flags, 0); | |
1235 | attr.btf_token_fd = OPTS_GET(opts, token_fd, 0); | |
1236 | ||
0ed08d67 AN |
1237 | /* log_level == 0 and log_buf != NULL means "try loading without |
1238 | * log_buf, but retry with log_buf and log_level=1 on error", which is | |
1239 | * consistent across low-level and high-level BTF and program loading | |
1240 | * APIs within libbpf and provides a sensible behavior in practice | |
1241 | */ | |
1242 | if (log_level) { | |
1243 | attr.btf_log_buf = ptr_to_u64(log_buf); | |
1244 | attr.btf_log_size = (__u32)log_size; | |
1245 | attr.btf_log_level = log_level; | |
1246 | } | |
8a138aed | 1247 | |
0ed08d67 AN |
1248 | fd = sys_bpf_fd(BPF_BTF_LOAD, &attr, attr_sz); |
1249 | if (fd < 0 && log_buf && log_level == 0) { | |
8a138aed | 1250 | attr.btf_log_buf = ptr_to_u64(log_buf); |
0ed08d67 AN |
1251 | attr.btf_log_size = (__u32)log_size; |
1252 | attr.btf_log_level = 1; | |
1253 | fd = sys_bpf_fd(BPF_BTF_LOAD, &attr, attr_sz); | |
8a138aed | 1254 | } |
097d8002 AN |
1255 | |
1256 | OPTS_SET(opts, log_true_size, attr.btf_log_true_size); | |
0ed08d67 AN |
1257 | return libbpf_err_errno(fd); |
1258 | } | |
1259 | ||
30687ad9 YS |
1260 | int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len, |
1261 | __u32 *prog_id, __u32 *fd_type, __u64 *probe_offset, | |
1262 | __u64 *probe_addr) | |
1263 | { | |
813847a3 AN |
1264 | const size_t attr_sz = offsetofend(union bpf_attr, task_fd_query); |
1265 | union bpf_attr attr; | |
30687ad9 YS |
1266 | int err; |
1267 | ||
813847a3 | 1268 | memset(&attr, 0, attr_sz); |
30687ad9 YS |
1269 | attr.task_fd_query.pid = pid; |
1270 | attr.task_fd_query.fd = fd; | |
1271 | attr.task_fd_query.flags = flags; | |
1272 | attr.task_fd_query.buf = ptr_to_u64(buf); | |
1273 | attr.task_fd_query.buf_len = *buf_len; | |
1274 | ||
813847a3 | 1275 | err = sys_bpf(BPF_TASK_FD_QUERY, &attr, attr_sz); |
f12b6543 | 1276 | |
30687ad9 YS |
1277 | *buf_len = attr.task_fd_query.buf_len; |
1278 | *prog_id = attr.task_fd_query.prog_id; | |
1279 | *fd_type = attr.task_fd_query.fd_type; | |
1280 | *probe_offset = attr.task_fd_query.probe_offset; | |
1281 | *probe_addr = attr.task_fd_query.probe_addr; | |
1282 | ||
f12b6543 | 1283 | return libbpf_err_errno(err); |
30687ad9 | 1284 | } |
0bee1067 SL |
1285 | |
1286 | int bpf_enable_stats(enum bpf_stats_type type) | |
1287 | { | |
813847a3 | 1288 | const size_t attr_sz = offsetofend(union bpf_attr, enable_stats); |
0bee1067 | 1289 | union bpf_attr attr; |
f12b6543 | 1290 | int fd; |
0bee1067 | 1291 | |
813847a3 | 1292 | memset(&attr, 0, attr_sz); |
0bee1067 SL |
1293 | attr.enable_stats.type = type; |
1294 | ||
813847a3 | 1295 | fd = sys_bpf_fd(BPF_ENABLE_STATS, &attr, attr_sz); |
f12b6543 | 1296 | return libbpf_err_errno(fd); |
0bee1067 | 1297 | } |
5d23328d YZ |
1298 | |
1299 | int bpf_prog_bind_map(int prog_fd, int map_fd, | |
1300 | const struct bpf_prog_bind_opts *opts) | |
1301 | { | |
813847a3 | 1302 | const size_t attr_sz = offsetofend(union bpf_attr, prog_bind_map); |
5d23328d | 1303 | union bpf_attr attr; |
f12b6543 | 1304 | int ret; |
5d23328d YZ |
1305 | |
1306 | if (!OPTS_VALID(opts, bpf_prog_bind_opts)) | |
f12b6543 | 1307 | return libbpf_err(-EINVAL); |
5d23328d | 1308 | |
813847a3 | 1309 | memset(&attr, 0, attr_sz); |
5d23328d YZ |
1310 | attr.prog_bind_map.prog_fd = prog_fd; |
1311 | attr.prog_bind_map.map_fd = map_fd; | |
1312 | attr.prog_bind_map.flags = OPTS_GET(opts, flags, 0); | |
1313 | ||
813847a3 | 1314 | ret = sys_bpf(BPF_PROG_BIND_MAP, &attr, attr_sz); |
f12b6543 | 1315 | return libbpf_err_errno(ret); |
5d23328d | 1316 | } |
639ecd7d AN |
1317 | |
1318 | int bpf_token_create(int bpffs_fd, struct bpf_token_create_opts *opts) | |
1319 | { | |
1320 | const size_t attr_sz = offsetofend(union bpf_attr, token_create); | |
1321 | union bpf_attr attr; | |
1322 | int fd; | |
1323 | ||
1324 | if (!OPTS_VALID(opts, bpf_token_create_opts)) | |
1325 | return libbpf_err(-EINVAL); | |
1326 | ||
1327 | memset(&attr, 0, attr_sz); | |
1328 | attr.token_create.bpffs_fd = bpffs_fd; | |
1329 | attr.token_create.flags = OPTS_GET(opts, flags, 0); | |
1330 | ||
1331 | fd = sys_bpf_fd(BPF_TOKEN_CREATE, &attr, attr_sz); | |
1332 | return libbpf_err_errno(fd); | |
1333 | } |