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 | { |
404cbc14 | 241 | const size_t attr_sz = offsetofend(union bpf_attr, prog_token_fd); |
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)); |
7bf98369 | 314 | |
4cf23a3c AN |
315 | if (log_level) { |
316 | attr.log_buf = ptr_to_u64(log_buf); | |
317 | attr.log_size = log_size; | |
318 | attr.log_level = log_level; | |
319 | } | |
320 | ||
813847a3 | 321 | fd = sys_bpf_prog_load(&attr, attr_sz, attempts); |
94e55c0f | 322 | OPTS_SET(opts, log_true_size, attr.log_true_size); |
f0187f0b | 323 | if (fd >= 0) |
7bf98369 WN |
324 | return fd; |
325 | ||
2993e051 YS |
326 | /* After bpf_prog_load, the kernel may modify certain attributes |
327 | * to give user space a hint how to deal with loading failure. | |
328 | * Check to see whether we can make some changes and load again. | |
329 | */ | |
3d650141 MKL |
330 | while (errno == E2BIG && (!finfo || !linfo)) { |
331 | if (!finfo && attr.func_info_cnt && | |
d10ef2b8 | 332 | attr.func_info_rec_size < func_info_rec_size) { |
3d650141 | 333 | /* try with corrected func info records */ |
d10ef2b8 AN |
334 | finfo = alloc_zero_tailing_info(func_info, |
335 | attr.func_info_cnt, | |
336 | func_info_rec_size, | |
3d650141 | 337 | attr.func_info_rec_size); |
f12b6543 AN |
338 | if (!finfo) { |
339 | errno = E2BIG; | |
3d650141 | 340 | goto done; |
f12b6543 | 341 | } |
3d650141 MKL |
342 | |
343 | attr.func_info = ptr_to_u64(finfo); | |
d10ef2b8 | 344 | attr.func_info_rec_size = func_info_rec_size; |
3d650141 | 345 | } else if (!linfo && attr.line_info_cnt && |
d10ef2b8 AN |
346 | attr.line_info_rec_size < line_info_rec_size) { |
347 | linfo = alloc_zero_tailing_info(line_info, | |
348 | attr.line_info_cnt, | |
349 | line_info_rec_size, | |
3d650141 | 350 | attr.line_info_rec_size); |
f12b6543 AN |
351 | if (!linfo) { |
352 | errno = E2BIG; | |
3d650141 | 353 | goto done; |
f12b6543 | 354 | } |
3d650141 MKL |
355 | |
356 | attr.line_info = ptr_to_u64(linfo); | |
d10ef2b8 | 357 | attr.line_info_rec_size = line_info_rec_size; |
3d650141 MKL |
358 | } else { |
359 | break; | |
2993e051 YS |
360 | } |
361 | ||
813847a3 | 362 | fd = sys_bpf_prog_load(&attr, attr_sz, attempts); |
94e55c0f | 363 | OPTS_SET(opts, log_true_size, attr.log_true_size); |
f0187f0b | 364 | if (fd >= 0) |
2993e051 YS |
365 | goto done; |
366 | } | |
367 | ||
4cf23a3c AN |
368 | if (log_level == 0 && log_buf) { |
369 | /* log_level == 0 with non-NULL log_buf requires retrying on error | |
370 | * with log_level == 1 and log_buf/log_buf_size set, to get details of | |
371 | * failure | |
372 | */ | |
373 | attr.log_buf = ptr_to_u64(log_buf); | |
374 | attr.log_size = log_size; | |
375 | attr.log_level = 1; | |
6aef10a4 | 376 | |
813847a3 | 377 | fd = sys_bpf_prog_load(&attr, attr_sz, attempts); |
94e55c0f | 378 | OPTS_SET(opts, log_true_size, attr.log_true_size); |
4cf23a3c | 379 | } |
2993e051 | 380 | done: |
f12b6543 | 381 | /* free() doesn't affect errno, so we don't need to restore it */ |
2993e051 | 382 | free(finfo); |
3d650141 | 383 | free(linfo); |
f12b6543 | 384 | return libbpf_err_errno(fd); |
7bf98369 | 385 | } |
43798bf3 | 386 | |
10ecc728 | 387 | int bpf_map_update_elem(int fd, const void *key, const void *value, |
83d994d0 | 388 | __u64 flags) |
43798bf3 | 389 | { |
813847a3 | 390 | const size_t attr_sz = offsetofend(union bpf_attr, flags); |
43798bf3 | 391 | union bpf_attr attr; |
f12b6543 | 392 | int ret; |
43798bf3 | 393 | |
813847a3 | 394 | memset(&attr, 0, attr_sz); |
43798bf3 HK |
395 | attr.map_fd = fd; |
396 | attr.key = ptr_to_u64(key); | |
397 | attr.value = ptr_to_u64(value); | |
398 | attr.flags = flags; | |
399 | ||
813847a3 | 400 | ret = sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, attr_sz); |
f12b6543 | 401 | return libbpf_err_errno(ret); |
43798bf3 | 402 | } |
9742da01 | 403 | |
e5ff7c40 | 404 | int bpf_map_lookup_elem(int fd, const void *key, void *value) |
9742da01 | 405 | { |
813847a3 | 406 | const size_t attr_sz = offsetofend(union bpf_attr, flags); |
9742da01 | 407 | union bpf_attr attr; |
f12b6543 | 408 | int ret; |
9742da01 | 409 | |
813847a3 | 410 | memset(&attr, 0, attr_sz); |
9742da01 WN |
411 | attr.map_fd = fd; |
412 | attr.key = ptr_to_u64(key); | |
413 | attr.value = ptr_to_u64(value); | |
414 | ||
813847a3 | 415 | ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, attr_sz); |
f12b6543 | 416 | return libbpf_err_errno(ret); |
9742da01 WN |
417 | } |
418 | ||
df5d22fa AS |
419 | int bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags) |
420 | { | |
813847a3 | 421 | const size_t attr_sz = offsetofend(union bpf_attr, flags); |
df5d22fa | 422 | union bpf_attr attr; |
f12b6543 | 423 | int ret; |
df5d22fa | 424 | |
813847a3 | 425 | memset(&attr, 0, attr_sz); |
df5d22fa AS |
426 | attr.map_fd = fd; |
427 | attr.key = ptr_to_u64(key); | |
428 | attr.value = ptr_to_u64(value); | |
429 | attr.flags = flags; | |
430 | ||
813847a3 | 431 | ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, attr_sz); |
f12b6543 | 432 | return libbpf_err_errno(ret); |
df5d22fa AS |
433 | } |
434 | ||
43b987d2 MV |
435 | int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value) |
436 | { | |
813847a3 | 437 | const size_t attr_sz = offsetofend(union bpf_attr, flags); |
43b987d2 | 438 | union bpf_attr attr; |
f12b6543 | 439 | int ret; |
43b987d2 | 440 | |
813847a3 | 441 | memset(&attr, 0, attr_sz); |
43b987d2 MV |
442 | attr.map_fd = fd; |
443 | attr.key = ptr_to_u64(key); | |
444 | attr.value = ptr_to_u64(value); | |
445 | ||
813847a3 | 446 | ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, attr_sz); |
f12b6543 | 447 | return libbpf_err_errno(ret); |
43b987d2 MV |
448 | } |
449 | ||
d59b9f2d DS |
450 | int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key, void *value, __u64 flags) |
451 | { | |
813847a3 | 452 | const size_t attr_sz = offsetofend(union bpf_attr, flags); |
d59b9f2d | 453 | union bpf_attr attr; |
64165ddf | 454 | int ret; |
d59b9f2d | 455 | |
813847a3 | 456 | memset(&attr, 0, attr_sz); |
d59b9f2d DS |
457 | attr.map_fd = fd; |
458 | attr.key = ptr_to_u64(key); | |
459 | attr.value = ptr_to_u64(value); | |
460 | attr.flags = flags; | |
461 | ||
813847a3 | 462 | ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, attr_sz); |
64165ddf | 463 | return libbpf_err_errno(ret); |
d59b9f2d DS |
464 | } |
465 | ||
e58383b8 | 466 | int bpf_map_delete_elem(int fd, const void *key) |
9742da01 | 467 | { |
813847a3 | 468 | const size_t attr_sz = offsetofend(union bpf_attr, flags); |
9742da01 | 469 | union bpf_attr attr; |
f12b6543 | 470 | int ret; |
9742da01 | 471 | |
813847a3 | 472 | memset(&attr, 0, attr_sz); |
9742da01 WN |
473 | attr.map_fd = fd; |
474 | attr.key = ptr_to_u64(key); | |
475 | ||
813847a3 | 476 | ret = sys_bpf(BPF_MAP_DELETE_ELEM, &attr, attr_sz); |
f12b6543 | 477 | return libbpf_err_errno(ret); |
9742da01 WN |
478 | } |
479 | ||
737d0646 AN |
480 | int bpf_map_delete_elem_flags(int fd, const void *key, __u64 flags) |
481 | { | |
813847a3 | 482 | const size_t attr_sz = offsetofend(union bpf_attr, flags); |
737d0646 AN |
483 | union bpf_attr attr; |
484 | int ret; | |
485 | ||
813847a3 | 486 | memset(&attr, 0, attr_sz); |
737d0646 AN |
487 | attr.map_fd = fd; |
488 | attr.key = ptr_to_u64(key); | |
489 | attr.flags = flags; | |
490 | ||
813847a3 | 491 | ret = sys_bpf(BPF_MAP_DELETE_ELEM, &attr, attr_sz); |
737d0646 AN |
492 | return libbpf_err_errno(ret); |
493 | } | |
494 | ||
5f155c25 | 495 | int bpf_map_get_next_key(int fd, const void *key, void *next_key) |
9742da01 | 496 | { |
813847a3 | 497 | const size_t attr_sz = offsetofend(union bpf_attr, next_key); |
9742da01 | 498 | union bpf_attr attr; |
f12b6543 | 499 | int ret; |
9742da01 | 500 | |
813847a3 | 501 | memset(&attr, 0, attr_sz); |
9742da01 WN |
502 | attr.map_fd = fd; |
503 | attr.key = ptr_to_u64(key); | |
504 | attr.next_key = ptr_to_u64(next_key); | |
505 | ||
813847a3 | 506 | ret = sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, attr_sz); |
f12b6543 | 507 | return libbpf_err_errno(ret); |
9742da01 WN |
508 | } |
509 | ||
d859900c DB |
510 | int bpf_map_freeze(int fd) |
511 | { | |
813847a3 | 512 | const size_t attr_sz = offsetofend(union bpf_attr, map_fd); |
d859900c | 513 | union bpf_attr attr; |
f12b6543 | 514 | int ret; |
d859900c | 515 | |
813847a3 | 516 | memset(&attr, 0, attr_sz); |
d859900c DB |
517 | attr.map_fd = fd; |
518 | ||
813847a3 | 519 | ret = sys_bpf(BPF_MAP_FREEZE, &attr, attr_sz); |
f12b6543 | 520 | return libbpf_err_errno(ret); |
d859900c DB |
521 | } |
522 | ||
2ab3d86e YS |
523 | static int bpf_map_batch_common(int cmd, int fd, void *in_batch, |
524 | void *out_batch, void *keys, void *values, | |
525 | __u32 *count, | |
526 | const struct bpf_map_batch_opts *opts) | |
527 | { | |
813847a3 | 528 | const size_t attr_sz = offsetofend(union bpf_attr, batch); |
858e284f | 529 | union bpf_attr attr; |
2ab3d86e YS |
530 | int ret; |
531 | ||
532 | if (!OPTS_VALID(opts, bpf_map_batch_opts)) | |
f12b6543 | 533 | return libbpf_err(-EINVAL); |
2ab3d86e | 534 | |
813847a3 | 535 | memset(&attr, 0, attr_sz); |
2ab3d86e YS |
536 | attr.batch.map_fd = fd; |
537 | attr.batch.in_batch = ptr_to_u64(in_batch); | |
538 | attr.batch.out_batch = ptr_to_u64(out_batch); | |
539 | attr.batch.keys = ptr_to_u64(keys); | |
540 | attr.batch.values = ptr_to_u64(values); | |
541 | attr.batch.count = *count; | |
542 | attr.batch.elem_flags = OPTS_GET(opts, elem_flags, 0); | |
543 | attr.batch.flags = OPTS_GET(opts, flags, 0); | |
544 | ||
813847a3 | 545 | ret = sys_bpf(cmd, &attr, attr_sz); |
2ab3d86e YS |
546 | *count = attr.batch.count; |
547 | ||
f12b6543 | 548 | return libbpf_err_errno(ret); |
2ab3d86e YS |
549 | } |
550 | ||
e59618f0 | 551 | int bpf_map_delete_batch(int fd, const void *keys, __u32 *count, |
2ab3d86e YS |
552 | const struct bpf_map_batch_opts *opts) |
553 | { | |
554 | return bpf_map_batch_common(BPF_MAP_DELETE_BATCH, fd, NULL, | |
e59618f0 | 555 | NULL, (void *)keys, NULL, count, opts); |
2ab3d86e YS |
556 | } |
557 | ||
558 | int bpf_map_lookup_batch(int fd, void *in_batch, void *out_batch, void *keys, | |
559 | void *values, __u32 *count, | |
560 | const struct bpf_map_batch_opts *opts) | |
561 | { | |
562 | return bpf_map_batch_common(BPF_MAP_LOOKUP_BATCH, fd, in_batch, | |
563 | out_batch, keys, values, count, opts); | |
564 | } | |
565 | ||
566 | int bpf_map_lookup_and_delete_batch(int fd, void *in_batch, void *out_batch, | |
567 | void *keys, void *values, __u32 *count, | |
568 | const struct bpf_map_batch_opts *opts) | |
569 | { | |
570 | return bpf_map_batch_common(BPF_MAP_LOOKUP_AND_DELETE_BATCH, | |
571 | fd, in_batch, out_batch, keys, values, | |
572 | count, opts); | |
573 | } | |
574 | ||
e59618f0 | 575 | int bpf_map_update_batch(int fd, const void *keys, const void *values, __u32 *count, |
2ab3d86e YS |
576 | const struct bpf_map_batch_opts *opts) |
577 | { | |
578 | return bpf_map_batch_common(BPF_MAP_UPDATE_BATCH, fd, NULL, NULL, | |
e59618f0 | 579 | (void *)keys, (void *)values, count, opts); |
2ab3d86e YS |
580 | } |
581 | ||
f1674dc7 | 582 | int bpf_obj_pin_opts(int fd, const char *pathname, const struct bpf_obj_pin_opts *opts) |
9742da01 | 583 | { |
f1674dc7 | 584 | const size_t attr_sz = offsetofend(union bpf_attr, path_fd); |
9742da01 | 585 | union bpf_attr attr; |
f12b6543 | 586 | int ret; |
9742da01 | 587 | |
f1674dc7 AN |
588 | if (!OPTS_VALID(opts, bpf_obj_pin_opts)) |
589 | return libbpf_err(-EINVAL); | |
590 | ||
813847a3 | 591 | memset(&attr, 0, attr_sz); |
f1674dc7 | 592 | attr.path_fd = OPTS_GET(opts, path_fd, 0); |
9742da01 | 593 | attr.pathname = ptr_to_u64((void *)pathname); |
f1674dc7 | 594 | attr.file_flags = OPTS_GET(opts, file_flags, 0); |
9742da01 WN |
595 | attr.bpf_fd = fd; |
596 | ||
813847a3 | 597 | ret = sys_bpf(BPF_OBJ_PIN, &attr, attr_sz); |
f12b6543 | 598 | return libbpf_err_errno(ret); |
9742da01 WN |
599 | } |
600 | ||
f1674dc7 AN |
601 | int bpf_obj_pin(int fd, const char *pathname) |
602 | { | |
603 | return bpf_obj_pin_opts(fd, pathname, NULL); | |
604 | } | |
605 | ||
9742da01 | 606 | int bpf_obj_get(const char *pathname) |
395fc4fa JB |
607 | { |
608 | return bpf_obj_get_opts(pathname, NULL); | |
609 | } | |
610 | ||
611 | int bpf_obj_get_opts(const char *pathname, const struct bpf_obj_get_opts *opts) | |
9742da01 | 612 | { |
f1674dc7 | 613 | const size_t attr_sz = offsetofend(union bpf_attr, path_fd); |
9742da01 | 614 | union bpf_attr attr; |
f12b6543 | 615 | int fd; |
9742da01 | 616 | |
395fc4fa JB |
617 | if (!OPTS_VALID(opts, bpf_obj_get_opts)) |
618 | return libbpf_err(-EINVAL); | |
619 | ||
813847a3 | 620 | memset(&attr, 0, attr_sz); |
f1674dc7 | 621 | attr.path_fd = OPTS_GET(opts, path_fd, 0); |
9742da01 | 622 | attr.pathname = ptr_to_u64((void *)pathname); |
395fc4fa | 623 | attr.file_flags = OPTS_GET(opts, file_flags, 0); |
9742da01 | 624 | |
813847a3 | 625 | fd = sys_bpf_fd(BPF_OBJ_GET, &attr, attr_sz); |
f12b6543 | 626 | return libbpf_err_errno(fd); |
9742da01 | 627 | } |
5dc880de | 628 | |
464bc0fd JF |
629 | int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type, |
630 | unsigned int flags) | |
cdbee383 AI |
631 | { |
632 | DECLARE_LIBBPF_OPTS(bpf_prog_attach_opts, opts, | |
633 | .flags = flags, | |
634 | ); | |
635 | ||
d6c9c24e | 636 | return bpf_prog_attach_opts(prog_fd, target_fd, type, &opts); |
cdbee383 AI |
637 | } |
638 | ||
fe20ce3a DB |
639 | int bpf_prog_attach_opts(int prog_fd, int target, enum bpf_attach_type type, |
640 | const struct bpf_prog_attach_opts *opts) | |
5dc880de | 641 | { |
fe20ce3a DB |
642 | const size_t attr_sz = offsetofend(union bpf_attr, expected_revision); |
643 | __u32 relative_id, flags; | |
644 | int ret, relative_fd; | |
5dc880de JS |
645 | union bpf_attr attr; |
646 | ||
cdbee383 | 647 | if (!OPTS_VALID(opts, bpf_prog_attach_opts)) |
f12b6543 | 648 | return libbpf_err(-EINVAL); |
cdbee383 | 649 | |
fe20ce3a DB |
650 | relative_id = OPTS_GET(opts, relative_id, 0); |
651 | relative_fd = OPTS_GET(opts, relative_fd, 0); | |
652 | flags = OPTS_GET(opts, flags, 0); | |
653 | ||
654 | /* validate we don't have unexpected combinations of non-zero fields */ | |
655 | if (relative_fd && relative_id) | |
656 | return libbpf_err(-EINVAL); | |
657 | ||
813847a3 | 658 | memset(&attr, 0, attr_sz); |
fe20ce3a DB |
659 | attr.target_fd = target; |
660 | attr.attach_bpf_fd = prog_fd; | |
661 | attr.attach_type = type; | |
662 | attr.replace_bpf_fd = OPTS_GET(opts, replace_fd, 0); | |
663 | attr.expected_revision = OPTS_GET(opts, expected_revision, 0); | |
664 | ||
665 | if (relative_id) { | |
666 | attr.attach_flags = flags | BPF_F_ID; | |
667 | attr.relative_id = relative_id; | |
668 | } else { | |
669 | attr.attach_flags = flags; | |
670 | attr.relative_fd = relative_fd; | |
671 | } | |
5dc880de | 672 | |
813847a3 | 673 | ret = sys_bpf(BPF_PROG_ATTACH, &attr, attr_sz); |
f12b6543 | 674 | return libbpf_err_errno(ret); |
5dc880de JS |
675 | } |
676 | ||
fe20ce3a DB |
677 | int bpf_prog_detach_opts(int prog_fd, int target, enum bpf_attach_type type, |
678 | const struct bpf_prog_detach_opts *opts) | |
5dc880de | 679 | { |
fe20ce3a DB |
680 | const size_t attr_sz = offsetofend(union bpf_attr, expected_revision); |
681 | __u32 relative_id, flags; | |
682 | int ret, relative_fd; | |
5dc880de | 683 | union bpf_attr attr; |
fe20ce3a DB |
684 | |
685 | if (!OPTS_VALID(opts, bpf_prog_detach_opts)) | |
686 | return libbpf_err(-EINVAL); | |
687 | ||
688 | relative_id = OPTS_GET(opts, relative_id, 0); | |
689 | relative_fd = OPTS_GET(opts, relative_fd, 0); | |
690 | flags = OPTS_GET(opts, flags, 0); | |
691 | ||
692 | /* validate we don't have unexpected combinations of non-zero fields */ | |
693 | if (relative_fd && relative_id) | |
694 | return libbpf_err(-EINVAL); | |
5dc880de | 695 | |
813847a3 | 696 | memset(&attr, 0, attr_sz); |
fe20ce3a DB |
697 | attr.target_fd = target; |
698 | attr.attach_bpf_fd = prog_fd; | |
699 | attr.attach_type = type; | |
700 | attr.expected_revision = OPTS_GET(opts, expected_revision, 0); | |
701 | ||
702 | if (relative_id) { | |
703 | attr.attach_flags = flags | BPF_F_ID; | |
704 | attr.relative_id = relative_id; | |
705 | } else { | |
706 | attr.attach_flags = flags; | |
707 | attr.relative_fd = relative_fd; | |
708 | } | |
5dc880de | 709 | |
813847a3 | 710 | ret = sys_bpf(BPF_PROG_DETACH, &attr, attr_sz); |
f12b6543 | 711 | return libbpf_err_errno(ret); |
5dc880de | 712 | } |
30848873 | 713 | |
fe20ce3a | 714 | int bpf_prog_detach(int target_fd, enum bpf_attach_type type) |
244d20ef | 715 | { |
fe20ce3a DB |
716 | return bpf_prog_detach_opts(0, target_fd, type, NULL); |
717 | } | |
244d20ef | 718 | |
fe20ce3a DB |
719 | int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type) |
720 | { | |
721 | return bpf_prog_detach_opts(prog_fd, target_fd, type, NULL); | |
244d20ef AS |
722 | } |
723 | ||
cc4f864b AN |
724 | int bpf_link_create(int prog_fd, int target_fd, |
725 | enum bpf_attach_type attach_type, | |
726 | const struct bpf_link_create_opts *opts) | |
727 | { | |
813847a3 | 728 | const size_t attr_sz = offsetofend(union bpf_attr, link_create); |
55cc3768 DB |
729 | __u32 target_btf_id, iter_info_len, relative_id; |
730 | int fd, err, relative_fd; | |
cc4f864b AN |
731 | union bpf_attr attr; |
732 | ||
733 | if (!OPTS_VALID(opts, bpf_link_create_opts)) | |
f12b6543 | 734 | return libbpf_err(-EINVAL); |
cc4f864b | 735 | |
a5359091 THJ |
736 | iter_info_len = OPTS_GET(opts, iter_info_len, 0); |
737 | target_btf_id = OPTS_GET(opts, target_btf_id, 0); | |
738 | ||
3ec84f4b AN |
739 | /* validate we don't have unexpected combinations of non-zero fields */ |
740 | if (iter_info_len || target_btf_id) { | |
741 | if (iter_info_len && target_btf_id) | |
742 | return libbpf_err(-EINVAL); | |
743 | if (!OPTS_ZEROED(opts, target_btf_id)) | |
744 | return libbpf_err(-EINVAL); | |
745 | } | |
a5359091 | 746 | |
813847a3 | 747 | memset(&attr, 0, attr_sz); |
cc4f864b AN |
748 | attr.link_create.prog_fd = prog_fd; |
749 | attr.link_create.target_fd = target_fd; | |
750 | attr.link_create.attach_type = attach_type; | |
cd31039a | 751 | attr.link_create.flags = OPTS_GET(opts, flags, 0); |
a5359091 | 752 | |
3ec84f4b | 753 | if (target_btf_id) { |
a5359091 | 754 | attr.link_create.target_btf_id = target_btf_id; |
3ec84f4b | 755 | goto proceed; |
a5359091 | 756 | } |
cc4f864b | 757 | |
3ec84f4b AN |
758 | switch (attach_type) { |
759 | case BPF_TRACE_ITER: | |
760 | attr.link_create.iter_info = ptr_to_u64(OPTS_GET(opts, iter_info, (void *)0)); | |
761 | attr.link_create.iter_info_len = iter_info_len; | |
762 | break; | |
763 | case BPF_PERF_EVENT: | |
764 | attr.link_create.perf_event.bpf_cookie = OPTS_GET(opts, perf_event.bpf_cookie, 0); | |
765 | if (!OPTS_ZEROED(opts, perf_event)) | |
766 | return libbpf_err(-EINVAL); | |
5117c26e JO |
767 | break; |
768 | case BPF_TRACE_KPROBE_MULTI: | |
2ca178f0 | 769 | case BPF_TRACE_KPROBE_SESSION: |
5117c26e JO |
770 | attr.link_create.kprobe_multi.flags = OPTS_GET(opts, kprobe_multi.flags, 0); |
771 | attr.link_create.kprobe_multi.cnt = OPTS_GET(opts, kprobe_multi.cnt, 0); | |
772 | attr.link_create.kprobe_multi.syms = ptr_to_u64(OPTS_GET(opts, kprobe_multi.syms, 0)); | |
773 | attr.link_create.kprobe_multi.addrs = ptr_to_u64(OPTS_GET(opts, kprobe_multi.addrs, 0)); | |
774 | attr.link_create.kprobe_multi.cookies = ptr_to_u64(OPTS_GET(opts, kprobe_multi.cookies, 0)); | |
775 | if (!OPTS_ZEROED(opts, kprobe_multi)) | |
776 | return libbpf_err(-EINVAL); | |
3ec84f4b | 777 | break; |
5054a303 JO |
778 | case BPF_TRACE_UPROBE_MULTI: |
779 | attr.link_create.uprobe_multi.flags = OPTS_GET(opts, uprobe_multi.flags, 0); | |
780 | attr.link_create.uprobe_multi.cnt = OPTS_GET(opts, uprobe_multi.cnt, 0); | |
781 | attr.link_create.uprobe_multi.path = ptr_to_u64(OPTS_GET(opts, uprobe_multi.path, 0)); | |
782 | attr.link_create.uprobe_multi.offsets = ptr_to_u64(OPTS_GET(opts, uprobe_multi.offsets, 0)); | |
783 | attr.link_create.uprobe_multi.ref_ctr_offsets = ptr_to_u64(OPTS_GET(opts, uprobe_multi.ref_ctr_offsets, 0)); | |
784 | attr.link_create.uprobe_multi.cookies = ptr_to_u64(OPTS_GET(opts, uprobe_multi.cookies, 0)); | |
785 | attr.link_create.uprobe_multi.pid = OPTS_GET(opts, uprobe_multi.pid, 0); | |
786 | if (!OPTS_ZEROED(opts, uprobe_multi)) | |
787 | return libbpf_err(-EINVAL); | |
788 | break; | |
36ffb202 | 789 | case BPF_TRACE_RAW_TP: |
129b9c5e KFL |
790 | case BPF_TRACE_FENTRY: |
791 | case BPF_TRACE_FEXIT: | |
792 | case BPF_MODIFY_RETURN: | |
793 | case BPF_LSM_MAC: | |
794 | attr.link_create.tracing.cookie = OPTS_GET(opts, tracing.cookie, 0); | |
795 | if (!OPTS_ZEROED(opts, tracing)) | |
796 | return libbpf_err(-EINVAL); | |
797 | break; | |
52364abb FW |
798 | case BPF_NETFILTER: |
799 | attr.link_create.netfilter.pf = OPTS_GET(opts, netfilter.pf, 0); | |
800 | attr.link_create.netfilter.hooknum = OPTS_GET(opts, netfilter.hooknum, 0); | |
801 | attr.link_create.netfilter.priority = OPTS_GET(opts, netfilter.priority, 0); | |
802 | attr.link_create.netfilter.flags = OPTS_GET(opts, netfilter.flags, 0); | |
803 | if (!OPTS_ZEROED(opts, netfilter)) | |
804 | return libbpf_err(-EINVAL); | |
805 | break; | |
55cc3768 DB |
806 | case BPF_TCX_INGRESS: |
807 | case BPF_TCX_EGRESS: | |
808 | relative_fd = OPTS_GET(opts, tcx.relative_fd, 0); | |
809 | relative_id = OPTS_GET(opts, tcx.relative_id, 0); | |
810 | if (relative_fd && relative_id) | |
811 | return libbpf_err(-EINVAL); | |
812 | if (relative_id) { | |
813 | attr.link_create.tcx.relative_id = relative_id; | |
814 | attr.link_create.flags |= BPF_F_ID; | |
815 | } else { | |
816 | attr.link_create.tcx.relative_fd = relative_fd; | |
817 | } | |
818 | attr.link_create.tcx.expected_revision = OPTS_GET(opts, tcx.expected_revision, 0); | |
819 | if (!OPTS_ZEROED(opts, tcx)) | |
820 | return libbpf_err(-EINVAL); | |
821 | break; | |
05c31b4a DB |
822 | case BPF_NETKIT_PRIMARY: |
823 | case BPF_NETKIT_PEER: | |
824 | relative_fd = OPTS_GET(opts, netkit.relative_fd, 0); | |
825 | relative_id = OPTS_GET(opts, netkit.relative_id, 0); | |
826 | if (relative_fd && relative_id) | |
827 | return libbpf_err(-EINVAL); | |
828 | if (relative_id) { | |
829 | attr.link_create.netkit.relative_id = relative_id; | |
830 | attr.link_create.flags |= BPF_F_ID; | |
831 | } else { | |
832 | attr.link_create.netkit.relative_fd = relative_fd; | |
833 | } | |
834 | attr.link_create.netkit.expected_revision = OPTS_GET(opts, netkit.expected_revision, 0); | |
835 | if (!OPTS_ZEROED(opts, netkit)) | |
836 | return libbpf_err(-EINVAL); | |
837 | break; | |
3ec84f4b AN |
838 | default: |
839 | if (!OPTS_ZEROED(opts, flags)) | |
840 | return libbpf_err(-EINVAL); | |
841 | break; | |
842 | } | |
843 | proceed: | |
813847a3 | 844 | fd = sys_bpf_fd(BPF_LINK_CREATE, &attr, attr_sz); |
8462e0b4 AN |
845 | if (fd >= 0) |
846 | return fd; | |
847 | /* we'll get EINVAL if LINK_CREATE doesn't support attaching fentry | |
848 | * and other similar programs | |
849 | */ | |
850 | err = -errno; | |
851 | if (err != -EINVAL) | |
852 | return libbpf_err(err); | |
853 | ||
854 | /* if user used features not supported by | |
855 | * BPF_RAW_TRACEPOINT_OPEN command, then just give up immediately | |
856 | */ | |
857 | if (attr.link_create.target_fd || attr.link_create.target_btf_id) | |
858 | return libbpf_err(err); | |
859 | if (!OPTS_ZEROED(opts, sz)) | |
860 | return libbpf_err(err); | |
861 | ||
862 | /* otherwise, for few select kinds of programs that can be | |
863 | * attached using BPF_RAW_TRACEPOINT_OPEN command, try that as | |
864 | * a fallback for older kernels | |
865 | */ | |
866 | switch (attach_type) { | |
867 | case BPF_TRACE_RAW_TP: | |
868 | case BPF_LSM_MAC: | |
869 | case BPF_TRACE_FENTRY: | |
870 | case BPF_TRACE_FEXIT: | |
871 | case BPF_MODIFY_RETURN: | |
872 | return bpf_raw_tracepoint_open(NULL, prog_fd); | |
873 | default: | |
874 | return libbpf_err(err); | |
875 | } | |
cc4f864b AN |
876 | } |
877 | ||
2e49527e AN |
878 | int bpf_link_detach(int link_fd) |
879 | { | |
813847a3 | 880 | const size_t attr_sz = offsetofend(union bpf_attr, link_detach); |
2e49527e | 881 | union bpf_attr attr; |
f12b6543 | 882 | int ret; |
2e49527e | 883 | |
813847a3 | 884 | memset(&attr, 0, attr_sz); |
2e49527e AN |
885 | attr.link_detach.link_fd = link_fd; |
886 | ||
813847a3 | 887 | ret = sys_bpf(BPF_LINK_DETACH, &attr, attr_sz); |
f12b6543 | 888 | return libbpf_err_errno(ret); |
2e49527e AN |
889 | } |
890 | ||
cc4f864b AN |
891 | int bpf_link_update(int link_fd, int new_prog_fd, |
892 | const struct bpf_link_update_opts *opts) | |
893 | { | |
813847a3 | 894 | const size_t attr_sz = offsetofend(union bpf_attr, link_update); |
cc4f864b | 895 | union bpf_attr attr; |
f12b6543 | 896 | int ret; |
cc4f864b AN |
897 | |
898 | if (!OPTS_VALID(opts, bpf_link_update_opts)) | |
f12b6543 | 899 | return libbpf_err(-EINVAL); |
cc4f864b | 900 | |
912dd4b0 KFL |
901 | if (OPTS_GET(opts, old_prog_fd, 0) && OPTS_GET(opts, old_map_fd, 0)) |
902 | return libbpf_err(-EINVAL); | |
903 | ||
813847a3 | 904 | memset(&attr, 0, attr_sz); |
cc4f864b AN |
905 | attr.link_update.link_fd = link_fd; |
906 | attr.link_update.new_prog_fd = new_prog_fd; | |
907 | attr.link_update.flags = OPTS_GET(opts, flags, 0); | |
912dd4b0 KFL |
908 | if (OPTS_GET(opts, old_prog_fd, 0)) |
909 | attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0); | |
910 | else if (OPTS_GET(opts, old_map_fd, 0)) | |
911 | attr.link_update.old_map_fd = OPTS_GET(opts, old_map_fd, 0); | |
cc4f864b | 912 | |
813847a3 | 913 | ret = sys_bpf(BPF_LINK_UPDATE, &attr, attr_sz); |
f12b6543 | 914 | return libbpf_err_errno(ret); |
cc4f864b AN |
915 | } |
916 | ||
c09add2f YS |
917 | int bpf_iter_create(int link_fd) |
918 | { | |
813847a3 | 919 | const size_t attr_sz = offsetofend(union bpf_attr, iter_create); |
c09add2f | 920 | union bpf_attr attr; |
f12b6543 | 921 | int fd; |
c09add2f | 922 | |
813847a3 | 923 | memset(&attr, 0, attr_sz); |
c09add2f YS |
924 | attr.iter_create.link_fd = link_fd; |
925 | ||
813847a3 | 926 | fd = sys_bpf_fd(BPF_ITER_CREATE, &attr, attr_sz); |
f12b6543 | 927 | return libbpf_err_errno(fd); |
c09add2f YS |
928 | } |
929 | ||
fe20ce3a | 930 | int bpf_prog_query_opts(int target, enum bpf_attach_type type, |
a4b2f3cf | 931 | struct bpf_prog_query_opts *opts) |
5d0cbf9b | 932 | { |
813847a3 | 933 | const size_t attr_sz = offsetofend(union bpf_attr, query); |
5d0cbf9b AS |
934 | union bpf_attr attr; |
935 | int ret; | |
936 | ||
a4b2f3cf SF |
937 | if (!OPTS_VALID(opts, bpf_prog_query_opts)) |
938 | return libbpf_err(-EINVAL); | |
939 | ||
813847a3 | 940 | memset(&attr, 0, attr_sz); |
fe20ce3a DB |
941 | attr.query.target_fd = target; |
942 | attr.query.attach_type = type; | |
943 | attr.query.query_flags = OPTS_GET(opts, query_flags, 0); | |
944 | attr.query.count = OPTS_GET(opts, count, 0); | |
945 | attr.query.prog_ids = ptr_to_u64(OPTS_GET(opts, prog_ids, NULL)); | |
946 | attr.query.link_ids = ptr_to_u64(OPTS_GET(opts, link_ids, NULL)); | |
947 | attr.query.prog_attach_flags = ptr_to_u64(OPTS_GET(opts, prog_attach_flags, NULL)); | |
948 | attr.query.link_attach_flags = ptr_to_u64(OPTS_GET(opts, link_attach_flags, NULL)); | |
5d0cbf9b | 949 | |
813847a3 | 950 | ret = sys_bpf(BPF_PROG_QUERY, &attr, attr_sz); |
f12b6543 | 951 | |
a4b2f3cf | 952 | OPTS_SET(opts, attach_flags, attr.query.attach_flags); |
fe20ce3a DB |
953 | OPTS_SET(opts, revision, attr.query.revision); |
954 | OPTS_SET(opts, count, attr.query.count); | |
a4b2f3cf SF |
955 | |
956 | return libbpf_err_errno(ret); | |
957 | } | |
958 | ||
959 | int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags, | |
960 | __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt) | |
961 | { | |
962 | LIBBPF_OPTS(bpf_prog_query_opts, opts); | |
963 | int ret; | |
964 | ||
965 | opts.query_flags = query_flags; | |
966 | opts.prog_ids = prog_ids; | |
967 | opts.prog_cnt = *prog_cnt; | |
968 | ||
969 | ret = bpf_prog_query_opts(target_fd, type, &opts); | |
970 | ||
5d0cbf9b | 971 | if (attach_flags) |
a4b2f3cf SF |
972 | *attach_flags = opts.attach_flags; |
973 | *prog_cnt = opts.prog_cnt; | |
f12b6543 AN |
974 | |
975 | return libbpf_err_errno(ret); | |
5d0cbf9b AS |
976 | } |
977 | ||
88f7fe72 SL |
978 | int bpf_prog_test_run_opts(int prog_fd, struct bpf_test_run_opts *opts) |
979 | { | |
813847a3 | 980 | const size_t attr_sz = offsetofend(union bpf_attr, test); |
88f7fe72 SL |
981 | union bpf_attr attr; |
982 | int ret; | |
983 | ||
984 | if (!OPTS_VALID(opts, bpf_test_run_opts)) | |
f12b6543 | 985 | return libbpf_err(-EINVAL); |
88f7fe72 | 986 | |
813847a3 | 987 | memset(&attr, 0, attr_sz); |
88f7fe72 | 988 | attr.test.prog_fd = prog_fd; |
24592ad1 | 989 | attr.test.batch_size = OPTS_GET(opts, batch_size, 0); |
88f7fe72 SL |
990 | attr.test.cpu = OPTS_GET(opts, cpu, 0); |
991 | attr.test.flags = OPTS_GET(opts, flags, 0); | |
992 | attr.test.repeat = OPTS_GET(opts, repeat, 0); | |
993 | attr.test.duration = OPTS_GET(opts, duration, 0); | |
994 | attr.test.ctx_size_in = OPTS_GET(opts, ctx_size_in, 0); | |
995 | attr.test.ctx_size_out = OPTS_GET(opts, ctx_size_out, 0); | |
996 | attr.test.data_size_in = OPTS_GET(opts, data_size_in, 0); | |
997 | attr.test.data_size_out = OPTS_GET(opts, data_size_out, 0); | |
998 | attr.test.ctx_in = ptr_to_u64(OPTS_GET(opts, ctx_in, NULL)); | |
999 | attr.test.ctx_out = ptr_to_u64(OPTS_GET(opts, ctx_out, NULL)); | |
1000 | attr.test.data_in = ptr_to_u64(OPTS_GET(opts, data_in, NULL)); | |
1001 | attr.test.data_out = ptr_to_u64(OPTS_GET(opts, data_out, NULL)); | |
1002 | ||
813847a3 | 1003 | ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, attr_sz); |
f12b6543 | 1004 | |
88f7fe72 SL |
1005 | OPTS_SET(opts, data_size_out, attr.test.data_size_out); |
1006 | OPTS_SET(opts, ctx_size_out, attr.test.ctx_size_out); | |
1007 | OPTS_SET(opts, duration, attr.test.duration); | |
1008 | OPTS_SET(opts, retval, attr.test.retval); | |
f12b6543 AN |
1009 | |
1010 | return libbpf_err_errno(ret); | |
88f7fe72 SL |
1011 | } |
1012 | ||
a6e130c4 | 1013 | static int bpf_obj_get_next_id(__u32 start_id, __u32 *next_id, int cmd) |
95b9afd3 | 1014 | { |
813847a3 | 1015 | const size_t attr_sz = offsetofend(union bpf_attr, open_flags); |
95b9afd3 MKL |
1016 | union bpf_attr attr; |
1017 | int err; | |
1018 | ||
813847a3 | 1019 | memset(&attr, 0, attr_sz); |
95b9afd3 MKL |
1020 | attr.start_id = start_id; |
1021 | ||
813847a3 | 1022 | err = sys_bpf(cmd, &attr, attr_sz); |
95b9afd3 MKL |
1023 | if (!err) |
1024 | *next_id = attr.next_id; | |
1025 | ||
f12b6543 | 1026 | return libbpf_err_errno(err); |
95b9afd3 MKL |
1027 | } |
1028 | ||
a6e130c4 | 1029 | int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id) |
95b9afd3 | 1030 | { |
a6e130c4 QM |
1031 | return bpf_obj_get_next_id(start_id, next_id, BPF_PROG_GET_NEXT_ID); |
1032 | } | |
95b9afd3 | 1033 | |
a6e130c4 QM |
1034 | int bpf_map_get_next_id(__u32 start_id, __u32 *next_id) |
1035 | { | |
1036 | return bpf_obj_get_next_id(start_id, next_id, BPF_MAP_GET_NEXT_ID); | |
95b9afd3 MKL |
1037 | } |
1038 | ||
09d7c2e3 QM |
1039 | int bpf_btf_get_next_id(__u32 start_id, __u32 *next_id) |
1040 | { | |
1041 | return bpf_obj_get_next_id(start_id, next_id, BPF_BTF_GET_NEXT_ID); | |
1042 | } | |
1043 | ||
0dbc8668 AN |
1044 | int bpf_link_get_next_id(__u32 start_id, __u32 *next_id) |
1045 | { | |
1046 | return bpf_obj_get_next_id(start_id, next_id, BPF_LINK_GET_NEXT_ID); | |
1047 | } | |
1048 | ||
8f13f168 RS |
1049 | int bpf_prog_get_fd_by_id_opts(__u32 id, |
1050 | const struct bpf_get_fd_by_id_opts *opts) | |
95b9afd3 | 1051 | { |
813847a3 | 1052 | const size_t attr_sz = offsetofend(union bpf_attr, open_flags); |
95b9afd3 | 1053 | union bpf_attr attr; |
f12b6543 | 1054 | int fd; |
95b9afd3 | 1055 | |
8f13f168 RS |
1056 | if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts)) |
1057 | return libbpf_err(-EINVAL); | |
1058 | ||
813847a3 | 1059 | memset(&attr, 0, attr_sz); |
95b9afd3 | 1060 | attr.prog_id = id; |
8f13f168 | 1061 | attr.open_flags = OPTS_GET(opts, open_flags, 0); |
95b9afd3 | 1062 | |
813847a3 | 1063 | fd = sys_bpf_fd(BPF_PROG_GET_FD_BY_ID, &attr, attr_sz); |
f12b6543 | 1064 | return libbpf_err_errno(fd); |
95b9afd3 MKL |
1065 | } |
1066 | ||
8f13f168 RS |
1067 | int bpf_prog_get_fd_by_id(__u32 id) |
1068 | { | |
1069 | return bpf_prog_get_fd_by_id_opts(id, NULL); | |
1070 | } | |
1071 | ||
243e3005 RS |
1072 | int bpf_map_get_fd_by_id_opts(__u32 id, |
1073 | const struct bpf_get_fd_by_id_opts *opts) | |
95b9afd3 | 1074 | { |
813847a3 | 1075 | const size_t attr_sz = offsetofend(union bpf_attr, open_flags); |
95b9afd3 | 1076 | union bpf_attr attr; |
f12b6543 | 1077 | int fd; |
95b9afd3 | 1078 | |
243e3005 RS |
1079 | if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts)) |
1080 | return libbpf_err(-EINVAL); | |
1081 | ||
813847a3 | 1082 | memset(&attr, 0, attr_sz); |
95b9afd3 | 1083 | attr.map_id = id; |
243e3005 | 1084 | attr.open_flags = OPTS_GET(opts, open_flags, 0); |
95b9afd3 | 1085 | |
813847a3 | 1086 | fd = sys_bpf_fd(BPF_MAP_GET_FD_BY_ID, &attr, attr_sz); |
f12b6543 | 1087 | return libbpf_err_errno(fd); |
95b9afd3 MKL |
1088 | } |
1089 | ||
243e3005 RS |
1090 | int bpf_map_get_fd_by_id(__u32 id) |
1091 | { | |
1092 | return bpf_map_get_fd_by_id_opts(id, NULL); | |
1093 | } | |
1094 | ||
2ce7cbf2 RS |
1095 | int bpf_btf_get_fd_by_id_opts(__u32 id, |
1096 | const struct bpf_get_fd_by_id_opts *opts) | |
cd8b8928 | 1097 | { |
813847a3 | 1098 | const size_t attr_sz = offsetofend(union bpf_attr, open_flags); |
cd8b8928 | 1099 | union bpf_attr attr; |
f12b6543 | 1100 | int fd; |
cd8b8928 | 1101 | |
2ce7cbf2 RS |
1102 | if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts)) |
1103 | return libbpf_err(-EINVAL); | |
1104 | ||
813847a3 | 1105 | memset(&attr, 0, attr_sz); |
cd8b8928 | 1106 | attr.btf_id = id; |
2ce7cbf2 | 1107 | attr.open_flags = OPTS_GET(opts, open_flags, 0); |
cd8b8928 | 1108 | |
813847a3 | 1109 | fd = sys_bpf_fd(BPF_BTF_GET_FD_BY_ID, &attr, attr_sz); |
f12b6543 | 1110 | return libbpf_err_errno(fd); |
cd8b8928 MKL |
1111 | } |
1112 | ||
2ce7cbf2 RS |
1113 | int bpf_btf_get_fd_by_id(__u32 id) |
1114 | { | |
1115 | return bpf_btf_get_fd_by_id_opts(id, NULL); | |
1116 | } | |
1117 | ||
97c8f9dd RS |
1118 | int bpf_link_get_fd_by_id_opts(__u32 id, |
1119 | const struct bpf_get_fd_by_id_opts *opts) | |
0dbc8668 | 1120 | { |
813847a3 | 1121 | const size_t attr_sz = offsetofend(union bpf_attr, open_flags); |
0dbc8668 | 1122 | union bpf_attr attr; |
f12b6543 | 1123 | int fd; |
0dbc8668 | 1124 | |
97c8f9dd RS |
1125 | if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts)) |
1126 | return libbpf_err(-EINVAL); | |
1127 | ||
813847a3 | 1128 | memset(&attr, 0, attr_sz); |
0dbc8668 | 1129 | attr.link_id = id; |
97c8f9dd | 1130 | attr.open_flags = OPTS_GET(opts, open_flags, 0); |
0dbc8668 | 1131 | |
813847a3 | 1132 | fd = sys_bpf_fd(BPF_LINK_GET_FD_BY_ID, &attr, attr_sz); |
f12b6543 | 1133 | return libbpf_err_errno(fd); |
0dbc8668 AN |
1134 | } |
1135 | ||
97c8f9dd RS |
1136 | int bpf_link_get_fd_by_id(__u32 id) |
1137 | { | |
1138 | return bpf_link_get_fd_by_id_opts(id, NULL); | |
1139 | } | |
1140 | ||
0dbc8668 | 1141 | int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len) |
95b9afd3 | 1142 | { |
813847a3 | 1143 | const size_t attr_sz = offsetofend(union bpf_attr, info); |
95b9afd3 MKL |
1144 | union bpf_attr attr; |
1145 | int err; | |
1146 | ||
813847a3 | 1147 | memset(&attr, 0, attr_sz); |
0dbc8668 | 1148 | attr.info.bpf_fd = bpf_fd; |
95b9afd3 MKL |
1149 | attr.info.info_len = *info_len; |
1150 | attr.info.info = ptr_to_u64(info); | |
1151 | ||
813847a3 | 1152 | err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, attr_sz); |
95b9afd3 MKL |
1153 | if (!err) |
1154 | *info_len = attr.info.info_len; | |
f12b6543 | 1155 | return libbpf_err_errno(err); |
95b9afd3 | 1156 | } |
949abbe8 | 1157 | |
55a9ed0e IL |
1158 | int bpf_prog_get_info_by_fd(int prog_fd, struct bpf_prog_info *info, __u32 *info_len) |
1159 | { | |
1160 | return bpf_obj_get_info_by_fd(prog_fd, info, info_len); | |
1161 | } | |
1162 | ||
1163 | int bpf_map_get_info_by_fd(int map_fd, struct bpf_map_info *info, __u32 *info_len) | |
1164 | { | |
1165 | return bpf_obj_get_info_by_fd(map_fd, info, info_len); | |
1166 | } | |
1167 | ||
1168 | int bpf_btf_get_info_by_fd(int btf_fd, struct bpf_btf_info *info, __u32 *info_len) | |
1169 | { | |
1170 | return bpf_obj_get_info_by_fd(btf_fd, info, info_len); | |
1171 | } | |
1172 | ||
1173 | int bpf_link_get_info_by_fd(int link_fd, struct bpf_link_info *info, __u32 *info_len) | |
1174 | { | |
1175 | return bpf_obj_get_info_by_fd(link_fd, info, info_len); | |
1176 | } | |
1177 | ||
36ffb202 | 1178 | int bpf_raw_tracepoint_open_opts(int prog_fd, struct bpf_raw_tp_opts *opts) |
a0fe3e57 | 1179 | { |
813847a3 | 1180 | const size_t attr_sz = offsetofend(union bpf_attr, raw_tracepoint); |
a0fe3e57 | 1181 | union bpf_attr attr; |
f12b6543 | 1182 | int fd; |
a0fe3e57 | 1183 | |
36ffb202 AN |
1184 | if (!OPTS_VALID(opts, bpf_raw_tp_opts)) |
1185 | return libbpf_err(-EINVAL); | |
1186 | ||
813847a3 | 1187 | memset(&attr, 0, attr_sz); |
a0fe3e57 | 1188 | attr.raw_tracepoint.prog_fd = prog_fd; |
36ffb202 AN |
1189 | attr.raw_tracepoint.name = ptr_to_u64(OPTS_GET(opts, tp_name, NULL)); |
1190 | attr.raw_tracepoint.cookie = OPTS_GET(opts, cookie, 0); | |
a0fe3e57 | 1191 | |
813847a3 | 1192 | fd = sys_bpf_fd(BPF_RAW_TRACEPOINT_OPEN, &attr, attr_sz); |
f12b6543 | 1193 | return libbpf_err_errno(fd); |
a0fe3e57 AS |
1194 | } |
1195 | ||
36ffb202 AN |
1196 | int bpf_raw_tracepoint_open(const char *name, int prog_fd) |
1197 | { | |
1198 | LIBBPF_OPTS(bpf_raw_tp_opts, opts, .tp_name = name); | |
1199 | ||
1200 | return bpf_raw_tracepoint_open_opts(prog_fd, &opts); | |
1201 | } | |
1202 | ||
097d8002 | 1203 | int bpf_btf_load(const void *btf_data, size_t btf_size, struct bpf_btf_load_opts *opts) |
8a138aed | 1204 | { |
a3d63e85 | 1205 | const size_t attr_sz = offsetofend(union bpf_attr, btf_token_fd); |
0ed08d67 AN |
1206 | union bpf_attr attr; |
1207 | char *log_buf; | |
1208 | size_t log_size; | |
1209 | __u32 log_level; | |
8a138aed MKL |
1210 | int fd; |
1211 | ||
e542f2c4 AN |
1212 | bump_rlimit_memlock(); |
1213 | ||
0ed08d67 AN |
1214 | memset(&attr, 0, attr_sz); |
1215 | ||
1216 | if (!OPTS_VALID(opts, bpf_btf_load_opts)) | |
1217 | return libbpf_err(-EINVAL); | |
1218 | ||
1219 | log_buf = OPTS_GET(opts, log_buf, NULL); | |
1220 | log_size = OPTS_GET(opts, log_size, 0); | |
1221 | log_level = OPTS_GET(opts, log_level, 0); | |
1222 | ||
1223 | if (log_size > UINT_MAX) | |
1224 | return libbpf_err(-EINVAL); | |
1225 | if (log_size && !log_buf) | |
1226 | return libbpf_err(-EINVAL); | |
1227 | ||
1228 | attr.btf = ptr_to_u64(btf_data); | |
8a138aed | 1229 | attr.btf_size = btf_size; |
a3d63e85 AN |
1230 | |
1231 | attr.btf_flags = OPTS_GET(opts, btf_flags, 0); | |
1232 | attr.btf_token_fd = OPTS_GET(opts, token_fd, 0); | |
1233 | ||
0ed08d67 AN |
1234 | /* log_level == 0 and log_buf != NULL means "try loading without |
1235 | * log_buf, but retry with log_buf and log_level=1 on error", which is | |
1236 | * consistent across low-level and high-level BTF and program loading | |
1237 | * APIs within libbpf and provides a sensible behavior in practice | |
1238 | */ | |
1239 | if (log_level) { | |
1240 | attr.btf_log_buf = ptr_to_u64(log_buf); | |
1241 | attr.btf_log_size = (__u32)log_size; | |
1242 | attr.btf_log_level = log_level; | |
1243 | } | |
8a138aed | 1244 | |
0ed08d67 AN |
1245 | fd = sys_bpf_fd(BPF_BTF_LOAD, &attr, attr_sz); |
1246 | if (fd < 0 && log_buf && log_level == 0) { | |
8a138aed | 1247 | attr.btf_log_buf = ptr_to_u64(log_buf); |
0ed08d67 AN |
1248 | attr.btf_log_size = (__u32)log_size; |
1249 | attr.btf_log_level = 1; | |
1250 | fd = sys_bpf_fd(BPF_BTF_LOAD, &attr, attr_sz); | |
8a138aed | 1251 | } |
097d8002 AN |
1252 | |
1253 | OPTS_SET(opts, log_true_size, attr.btf_log_true_size); | |
0ed08d67 AN |
1254 | return libbpf_err_errno(fd); |
1255 | } | |
1256 | ||
30687ad9 YS |
1257 | int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len, |
1258 | __u32 *prog_id, __u32 *fd_type, __u64 *probe_offset, | |
1259 | __u64 *probe_addr) | |
1260 | { | |
813847a3 AN |
1261 | const size_t attr_sz = offsetofend(union bpf_attr, task_fd_query); |
1262 | union bpf_attr attr; | |
30687ad9 YS |
1263 | int err; |
1264 | ||
813847a3 | 1265 | memset(&attr, 0, attr_sz); |
30687ad9 YS |
1266 | attr.task_fd_query.pid = pid; |
1267 | attr.task_fd_query.fd = fd; | |
1268 | attr.task_fd_query.flags = flags; | |
1269 | attr.task_fd_query.buf = ptr_to_u64(buf); | |
1270 | attr.task_fd_query.buf_len = *buf_len; | |
1271 | ||
813847a3 | 1272 | err = sys_bpf(BPF_TASK_FD_QUERY, &attr, attr_sz); |
f12b6543 | 1273 | |
30687ad9 YS |
1274 | *buf_len = attr.task_fd_query.buf_len; |
1275 | *prog_id = attr.task_fd_query.prog_id; | |
1276 | *fd_type = attr.task_fd_query.fd_type; | |
1277 | *probe_offset = attr.task_fd_query.probe_offset; | |
1278 | *probe_addr = attr.task_fd_query.probe_addr; | |
1279 | ||
f12b6543 | 1280 | return libbpf_err_errno(err); |
30687ad9 | 1281 | } |
0bee1067 SL |
1282 | |
1283 | int bpf_enable_stats(enum bpf_stats_type type) | |
1284 | { | |
813847a3 | 1285 | const size_t attr_sz = offsetofend(union bpf_attr, enable_stats); |
0bee1067 | 1286 | union bpf_attr attr; |
f12b6543 | 1287 | int fd; |
0bee1067 | 1288 | |
813847a3 | 1289 | memset(&attr, 0, attr_sz); |
0bee1067 SL |
1290 | attr.enable_stats.type = type; |
1291 | ||
813847a3 | 1292 | fd = sys_bpf_fd(BPF_ENABLE_STATS, &attr, attr_sz); |
f12b6543 | 1293 | return libbpf_err_errno(fd); |
0bee1067 | 1294 | } |
5d23328d YZ |
1295 | |
1296 | int bpf_prog_bind_map(int prog_fd, int map_fd, | |
1297 | const struct bpf_prog_bind_opts *opts) | |
1298 | { | |
813847a3 | 1299 | const size_t attr_sz = offsetofend(union bpf_attr, prog_bind_map); |
5d23328d | 1300 | union bpf_attr attr; |
f12b6543 | 1301 | int ret; |
5d23328d YZ |
1302 | |
1303 | if (!OPTS_VALID(opts, bpf_prog_bind_opts)) | |
f12b6543 | 1304 | return libbpf_err(-EINVAL); |
5d23328d | 1305 | |
813847a3 | 1306 | memset(&attr, 0, attr_sz); |
5d23328d YZ |
1307 | attr.prog_bind_map.prog_fd = prog_fd; |
1308 | attr.prog_bind_map.map_fd = map_fd; | |
1309 | attr.prog_bind_map.flags = OPTS_GET(opts, flags, 0); | |
1310 | ||
813847a3 | 1311 | ret = sys_bpf(BPF_PROG_BIND_MAP, &attr, attr_sz); |
f12b6543 | 1312 | return libbpf_err_errno(ret); |
5d23328d | 1313 | } |
639ecd7d AN |
1314 | |
1315 | int bpf_token_create(int bpffs_fd, struct bpf_token_create_opts *opts) | |
1316 | { | |
1317 | const size_t attr_sz = offsetofend(union bpf_attr, token_create); | |
1318 | union bpf_attr attr; | |
1319 | int fd; | |
1320 | ||
1321 | if (!OPTS_VALID(opts, bpf_token_create_opts)) | |
1322 | return libbpf_err(-EINVAL); | |
1323 | ||
1324 | memset(&attr, 0, attr_sz); | |
1325 | attr.token_create.bpffs_fd = bpffs_fd; | |
1326 | attr.token_create.flags = OPTS_GET(opts, flags, 0); | |
1327 | ||
1328 | fd = sys_bpf_fd(BPF_TOKEN_CREATE, &attr, attr_sz); | |
1329 | return libbpf_err_errno(fd); | |
1330 | } |