11bc38b8fSAlexei Starovoitov // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
26061a3d6SEric Leblond
3e3ed2fefSWang Nan /*
4e3ed2fefSWang Nan * common eBPF ELF operations.
5e3ed2fefSWang Nan *
6e3ed2fefSWang Nan * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
7e3ed2fefSWang Nan * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
8e3ed2fefSWang Nan * Copyright (C) 2015 Huawei Inc.
9203d1cacSWang Nan *
10203d1cacSWang Nan * This program is free software; you can redistribute it and/or
11203d1cacSWang Nan * modify it under the terms of the GNU Lesser General Public
12203d1cacSWang Nan * License as published by the Free Software Foundation;
13203d1cacSWang Nan * version 2.1 of the License (not later!)
14203d1cacSWang Nan *
15203d1cacSWang Nan * This program is distributed in the hope that it will be useful,
16203d1cacSWang Nan * but WITHOUT ANY WARRANTY; without even the implied warranty of
17203d1cacSWang Nan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18203d1cacSWang Nan * GNU Lesser General Public License for more details.
19203d1cacSWang Nan *
20203d1cacSWang Nan * You should have received a copy of the GNU Lesser General Public
21203d1cacSWang Nan * License along with this program; if not, see <http://www.gnu.org/licenses>
22e3ed2fefSWang Nan */
23e3ed2fefSWang Nan
24e3ed2fefSWang Nan #include <stdlib.h>
251ad9cbb8SAndrii Nakryiko #include <string.h>
26e3ed2fefSWang Nan #include <memory.h>
27e3ed2fefSWang Nan #include <unistd.h>
28e3ed2fefSWang Nan #include <asm/unistd.h>
29d7fe74f9SAndrii Nakryiko #include <errno.h>
30e3ed2fefSWang Nan #include <linux/bpf.h>
31e542f2c4SAndrii Nakryiko #include <linux/filter.h>
3204b6de64SGuo Zhengkui #include <linux/kernel.h>
33d10ef2b8SAndrii Nakryiko #include <limits.h>
34e542f2c4SAndrii Nakryiko #include <sys/resource.h>
35e3ed2fefSWang Nan #include "bpf.h"
36949abbe8SEric Leblond #include "libbpf.h"
37d7fe74f9SAndrii Nakryiko #include "libbpf_internal.h"
38e3ed2fefSWang Nan
39e3ed2fefSWang Nan /*
4003671057SMasahiro Yamada * When building perf, unistd.h is overridden. __NR_bpf is
418f9e05fbSWang Nan * required to be defined explicitly.
42e3ed2fefSWang Nan */
43e3ed2fefSWang Nan #ifndef __NR_bpf
44e3ed2fefSWang Nan # if defined(__i386__)
45e3ed2fefSWang Nan # define __NR_bpf 357
46e3ed2fefSWang Nan # elif defined(__x86_64__)
47e3ed2fefSWang Nan # define __NR_bpf 321
48e3ed2fefSWang Nan # elif defined(__aarch64__)
49e3ed2fefSWang Nan # define __NR_bpf 280
50b0c47807SDavid S. Miller # elif defined(__sparc__)
51b0c47807SDavid S. Miller # define __NR_bpf 349
52bad1926dSDaniel Borkmann # elif defined(__s390__)
53bad1926dSDaniel Borkmann # define __NR_bpf 351
54ca31ca82SVineet Gupta # elif defined(__arc__)
55ca31ca82SVineet Gupta # define __NR_bpf 280
56e32cb12fSTiezhu Yang # elif defined(__mips__) && defined(_ABIO32)
57e32cb12fSTiezhu Yang # define __NR_bpf 4355
58e32cb12fSTiezhu Yang # elif defined(__mips__) && defined(_ABIN32)
59e32cb12fSTiezhu Yang # define __NR_bpf 6319
60e32cb12fSTiezhu Yang # elif defined(__mips__) && defined(_ABI64)
61e32cb12fSTiezhu Yang # define __NR_bpf 5315
62e3ed2fefSWang Nan # else
63e3ed2fefSWang Nan # error __NR_bpf not defined. libbpf does not support your arch.
64e3ed2fefSWang Nan # endif
65e3ed2fefSWang Nan #endif
66e3ed2fefSWang Nan
ptr_to_u64(const void * ptr)67cdc6a4baSMickaël Salaün static inline __u64 ptr_to_u64(const void *ptr)
687bf98369SWang Nan {
697bf98369SWang Nan return (__u64) (unsigned long) ptr;
707bf98369SWang Nan }
717bf98369SWang Nan
sys_bpf(enum bpf_cmd cmd,union bpf_attr * attr,unsigned int size)72cdc6a4baSMickaël Salaün static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
73e3ed2fefSWang Nan unsigned int size)
74e3ed2fefSWang Nan {
75e3ed2fefSWang Nan return syscall(__NR_bpf, cmd, attr, size);
76e3ed2fefSWang Nan }
77e3ed2fefSWang Nan
sys_bpf_fd(enum bpf_cmd cmd,union bpf_attr * attr,unsigned int size)78549a6323SKumar Kartikeya Dwivedi static inline int sys_bpf_fd(enum bpf_cmd cmd, union bpf_attr *attr,
79549a6323SKumar Kartikeya Dwivedi unsigned int size)
80549a6323SKumar Kartikeya Dwivedi {
81549a6323SKumar Kartikeya Dwivedi int fd;
82549a6323SKumar Kartikeya Dwivedi
83549a6323SKumar Kartikeya Dwivedi fd = sys_bpf(cmd, attr, size);
84549a6323SKumar Kartikeya Dwivedi return ensure_good_fd(fd);
85549a6323SKumar Kartikeya Dwivedi }
86549a6323SKumar Kartikeya Dwivedi
sys_bpf_prog_load(union bpf_attr * attr,unsigned int size,int attempts)871f235777SHangbin Liu int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts)
8886edaed3SLorenz Bauer {
8986edaed3SLorenz Bauer int fd;
9086edaed3SLorenz Bauer
9186edaed3SLorenz Bauer do {
92549a6323SKumar Kartikeya Dwivedi fd = sys_bpf_fd(BPF_PROG_LOAD, attr, size);
9345493cbaSAndrii Nakryiko } while (fd < 0 && errno == EAGAIN && --attempts > 0);
9486edaed3SLorenz Bauer
9586edaed3SLorenz Bauer return fd;
9686edaed3SLorenz Bauer }
9786edaed3SLorenz Bauer
98e542f2c4SAndrii Nakryiko /* Probe whether kernel switched from memlock-based (RLIMIT_MEMLOCK) to
99e542f2c4SAndrii Nakryiko * memcg-based memory accounting for BPF maps and progs. This was done in [0].
100e542f2c4SAndrii Nakryiko * We use the support for bpf_ktime_get_coarse_ns() helper, which was added in
101e542f2c4SAndrii Nakryiko * the same 5.11 Linux release ([1]), to detect memcg-based accounting for BPF.
102e542f2c4SAndrii Nakryiko *
103e542f2c4SAndrii Nakryiko * [0] https://lore.kernel.org/bpf/20201201215900.3569844-1-guro@fb.com/
104e542f2c4SAndrii Nakryiko * [1] d05512618056 ("bpf: Add bpf_ktime_get_coarse_ns helper")
105e542f2c4SAndrii Nakryiko */
probe_memcg_account(void)106e542f2c4SAndrii Nakryiko int probe_memcg_account(void)
107e542f2c4SAndrii Nakryiko {
108813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, attach_btf_obj_fd);
109e542f2c4SAndrii Nakryiko struct bpf_insn insns[] = {
110e542f2c4SAndrii Nakryiko BPF_EMIT_CALL(BPF_FUNC_ktime_get_coarse_ns),
111e542f2c4SAndrii Nakryiko BPF_EXIT_INSN(),
112e542f2c4SAndrii Nakryiko };
11304b6de64SGuo Zhengkui size_t insn_cnt = ARRAY_SIZE(insns);
114e542f2c4SAndrii Nakryiko union bpf_attr attr;
115e542f2c4SAndrii Nakryiko int prog_fd;
116e542f2c4SAndrii Nakryiko
117e542f2c4SAndrii Nakryiko /* attempt loading freplace trying to use custom BTF */
118813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
119e542f2c4SAndrii Nakryiko attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
120e542f2c4SAndrii Nakryiko attr.insns = ptr_to_u64(insns);
121e542f2c4SAndrii Nakryiko attr.insn_cnt = insn_cnt;
122e542f2c4SAndrii Nakryiko attr.license = ptr_to_u64("GPL");
123e542f2c4SAndrii Nakryiko
124813847a3SAndrii Nakryiko prog_fd = sys_bpf_fd(BPF_PROG_LOAD, &attr, attr_sz);
125e542f2c4SAndrii Nakryiko if (prog_fd >= 0) {
126e542f2c4SAndrii Nakryiko close(prog_fd);
127e542f2c4SAndrii Nakryiko return 1;
128e542f2c4SAndrii Nakryiko }
129e542f2c4SAndrii Nakryiko return 0;
130e542f2c4SAndrii Nakryiko }
131e542f2c4SAndrii Nakryiko
132e542f2c4SAndrii Nakryiko static bool memlock_bumped;
133e542f2c4SAndrii Nakryiko static rlim_t memlock_rlim = RLIM_INFINITY;
134e542f2c4SAndrii Nakryiko
libbpf_set_memlock_rlim(size_t memlock_bytes)135e542f2c4SAndrii Nakryiko int libbpf_set_memlock_rlim(size_t memlock_bytes)
136e542f2c4SAndrii Nakryiko {
137e542f2c4SAndrii Nakryiko if (memlock_bumped)
138e542f2c4SAndrii Nakryiko return libbpf_err(-EBUSY);
139e542f2c4SAndrii Nakryiko
140e542f2c4SAndrii Nakryiko memlock_rlim = memlock_bytes;
141e542f2c4SAndrii Nakryiko return 0;
142e542f2c4SAndrii Nakryiko }
143e542f2c4SAndrii Nakryiko
bump_rlimit_memlock(void)144e542f2c4SAndrii Nakryiko int bump_rlimit_memlock(void)
145e542f2c4SAndrii Nakryiko {
146e542f2c4SAndrii Nakryiko struct rlimit rlim;
147e542f2c4SAndrii Nakryiko
148e542f2c4SAndrii Nakryiko /* if kernel supports memcg-based accounting, skip bumping RLIMIT_MEMLOCK */
149e542f2c4SAndrii Nakryiko if (memlock_bumped || kernel_supports(NULL, FEAT_MEMCG_ACCOUNT))
150e542f2c4SAndrii Nakryiko return 0;
151e542f2c4SAndrii Nakryiko
152e542f2c4SAndrii Nakryiko memlock_bumped = true;
153e542f2c4SAndrii Nakryiko
154e542f2c4SAndrii Nakryiko /* zero memlock_rlim_max disables auto-bumping RLIMIT_MEMLOCK */
155e542f2c4SAndrii Nakryiko if (memlock_rlim == 0)
156e542f2c4SAndrii Nakryiko return 0;
157e542f2c4SAndrii Nakryiko
158e542f2c4SAndrii Nakryiko rlim.rlim_cur = rlim.rlim_max = memlock_rlim;
159e542f2c4SAndrii Nakryiko if (setrlimit(RLIMIT_MEMLOCK, &rlim))
160e542f2c4SAndrii Nakryiko return -errno;
161e542f2c4SAndrii Nakryiko
162e542f2c4SAndrii Nakryiko return 0;
163e542f2c4SAndrii Nakryiko }
164e542f2c4SAndrii Nakryiko
bpf_map_create(enum bpf_map_type map_type,const char * map_name,__u32 key_size,__u32 value_size,__u32 max_entries,const struct bpf_map_create_opts * opts)165992c4225SAndrii Nakryiko int bpf_map_create(enum bpf_map_type map_type,
166992c4225SAndrii Nakryiko const char *map_name,
167992c4225SAndrii Nakryiko __u32 key_size,
168992c4225SAndrii Nakryiko __u32 value_size,
169992c4225SAndrii Nakryiko __u32 max_entries,
170992c4225SAndrii Nakryiko const struct bpf_map_create_opts *opts)
171e3ed2fefSWang Nan {
172992c4225SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, map_extra);
173e3ed2fefSWang Nan union bpf_attr attr;
174f12b6543SAndrii Nakryiko int fd;
175e3ed2fefSWang Nan
176e542f2c4SAndrii Nakryiko bump_rlimit_memlock();
177e542f2c4SAndrii Nakryiko
178992c4225SAndrii Nakryiko memset(&attr, 0, attr_sz);
179e3ed2fefSWang Nan
180992c4225SAndrii Nakryiko if (!OPTS_VALID(opts, bpf_map_create_opts))
181992c4225SAndrii Nakryiko return libbpf_err(-EINVAL);
182e3ed2fefSWang Nan
183992c4225SAndrii Nakryiko attr.map_type = map_type;
18410b62d6aSHangbin Liu if (map_name && kernel_supports(NULL, FEAT_PROG_NAME))
1859fc205b4SAndrii Nakryiko libbpf_strlcpy(attr.map_name, map_name, sizeof(attr.map_name));
186992c4225SAndrii Nakryiko attr.key_size = key_size;
187992c4225SAndrii Nakryiko attr.value_size = value_size;
188992c4225SAndrii Nakryiko attr.max_entries = max_entries;
189992c4225SAndrii Nakryiko
190992c4225SAndrii Nakryiko attr.btf_fd = OPTS_GET(opts, btf_fd, 0);
191992c4225SAndrii Nakryiko attr.btf_key_type_id = OPTS_GET(opts, btf_key_type_id, 0);
192992c4225SAndrii Nakryiko attr.btf_value_type_id = OPTS_GET(opts, btf_value_type_id, 0);
193992c4225SAndrii Nakryiko attr.btf_vmlinux_value_type_id = OPTS_GET(opts, btf_vmlinux_value_type_id, 0);
194992c4225SAndrii Nakryiko
195992c4225SAndrii Nakryiko attr.inner_map_fd = OPTS_GET(opts, inner_map_fd, 0);
196992c4225SAndrii Nakryiko attr.map_flags = OPTS_GET(opts, map_flags, 0);
197992c4225SAndrii Nakryiko attr.map_extra = OPTS_GET(opts, map_extra, 0);
198992c4225SAndrii Nakryiko attr.numa_node = OPTS_GET(opts, numa_node, 0);
199992c4225SAndrii Nakryiko attr.map_ifindex = OPTS_GET(opts, map_ifindex, 0);
200992c4225SAndrii Nakryiko
201992c4225SAndrii Nakryiko fd = sys_bpf_fd(BPF_MAP_CREATE, &attr, attr_sz);
202f12b6543SAndrii Nakryiko return libbpf_err_errno(fd);
203e3ed2fefSWang Nan }
2047bf98369SWang Nan
2053d650141SMartin KaFai Lau static void *
alloc_zero_tailing_info(const void * orecord,__u32 cnt,__u32 actual_rec_size,__u32 expected_rec_size)2063d650141SMartin KaFai Lau alloc_zero_tailing_info(const void *orecord, __u32 cnt,
2073d650141SMartin KaFai Lau __u32 actual_rec_size, __u32 expected_rec_size)
2083d650141SMartin KaFai Lau {
2094ee11356SAndrii Nakryiko __u64 info_len = (__u64)actual_rec_size * cnt;
2103d650141SMartin KaFai Lau void *info, *nrecord;
2113d650141SMartin KaFai Lau int i;
2123d650141SMartin KaFai Lau
2133d650141SMartin KaFai Lau info = malloc(info_len);
2143d650141SMartin KaFai Lau if (!info)
2153d650141SMartin KaFai Lau return NULL;
2163d650141SMartin KaFai Lau
2173d650141SMartin KaFai Lau /* zero out bytes kernel does not understand */
2183d650141SMartin KaFai Lau nrecord = info;
2193d650141SMartin KaFai Lau for (i = 0; i < cnt; i++) {
2203d650141SMartin KaFai Lau memcpy(nrecord, orecord, expected_rec_size);
2213d650141SMartin KaFai Lau memset(nrecord + expected_rec_size, 0,
2223d650141SMartin KaFai Lau actual_rec_size - expected_rec_size);
2233d650141SMartin KaFai Lau orecord += actual_rec_size;
2243d650141SMartin KaFai Lau nrecord += actual_rec_size;
2253d650141SMartin KaFai Lau }
2263d650141SMartin KaFai Lau
2273d650141SMartin KaFai Lau return info;
2283d650141SMartin KaFai Lau }
2293d650141SMartin KaFai Lau
bpf_prog_load(enum bpf_prog_type prog_type,const char * prog_name,const char * license,const struct bpf_insn * insns,size_t insn_cnt,struct bpf_prog_load_opts * opts)230765a3413SAndrii Nakryiko int bpf_prog_load(enum bpf_prog_type prog_type,
231d10ef2b8SAndrii Nakryiko const char *prog_name, const char *license,
232d10ef2b8SAndrii Nakryiko const struct bpf_insn *insns, size_t insn_cnt,
23394e55c0fSAndrii Nakryiko struct bpf_prog_load_opts *opts)
2347bf98369SWang Nan {
23594e55c0fSAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, log_true_size);
2363d650141SMartin KaFai Lau void *finfo = NULL, *linfo = NULL;
237d10ef2b8SAndrii Nakryiko const char *func_info, *line_info;
238d10ef2b8SAndrii Nakryiko __u32 log_size, log_level, attach_prog_fd, attach_btf_obj_fd;
239d10ef2b8SAndrii Nakryiko __u32 func_info_rec_size, line_info_rec_size;
240d10ef2b8SAndrii Nakryiko int fd, attempts;
2417bf98369SWang Nan union bpf_attr attr;
242d10ef2b8SAndrii Nakryiko char *log_buf;
243d7be143bSAndrey Ignatov
244e542f2c4SAndrii Nakryiko bump_rlimit_memlock();
245e542f2c4SAndrii Nakryiko
246d10ef2b8SAndrii Nakryiko if (!OPTS_VALID(opts, bpf_prog_load_opts))
247f12b6543SAndrii Nakryiko return libbpf_err(-EINVAL);
248a4021a35SYonghong Song
249d10ef2b8SAndrii Nakryiko attempts = OPTS_GET(opts, attempts, 0);
250d10ef2b8SAndrii Nakryiko if (attempts < 0)
251f12b6543SAndrii Nakryiko return libbpf_err(-EINVAL);
252d10ef2b8SAndrii Nakryiko if (attempts == 0)
253d10ef2b8SAndrii Nakryiko attempts = PROG_LOAD_ATTEMPTS;
254d7be143bSAndrey Ignatov
255813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
2566aef10a4SAndrii Nakryiko
257d10ef2b8SAndrii Nakryiko attr.prog_type = prog_type;
258d10ef2b8SAndrii Nakryiko attr.expected_attach_type = OPTS_GET(opts, expected_attach_type, 0);
259d10ef2b8SAndrii Nakryiko
260d10ef2b8SAndrii Nakryiko attr.prog_btf_fd = OPTS_GET(opts, prog_btf_fd, 0);
261d10ef2b8SAndrii Nakryiko attr.prog_flags = OPTS_GET(opts, prog_flags, 0);
262d10ef2b8SAndrii Nakryiko attr.prog_ifindex = OPTS_GET(opts, prog_ifindex, 0);
263d10ef2b8SAndrii Nakryiko attr.kern_version = OPTS_GET(opts, kern_version, 0);
264d10ef2b8SAndrii Nakryiko
2651f235777SHangbin Liu if (prog_name && kernel_supports(NULL, FEAT_PROG_NAME))
2669fc205b4SAndrii Nakryiko libbpf_strlcpy(attr.prog_name, prog_name, sizeof(attr.prog_name));
267d10ef2b8SAndrii Nakryiko attr.license = ptr_to_u64(license);
268d10ef2b8SAndrii Nakryiko
269d10ef2b8SAndrii Nakryiko if (insn_cnt > UINT_MAX)
270d10ef2b8SAndrii Nakryiko return libbpf_err(-E2BIG);
271d10ef2b8SAndrii Nakryiko
272d10ef2b8SAndrii Nakryiko attr.insns = ptr_to_u64(insns);
273d10ef2b8SAndrii Nakryiko attr.insn_cnt = (__u32)insn_cnt;
274d10ef2b8SAndrii Nakryiko
275d10ef2b8SAndrii Nakryiko attach_prog_fd = OPTS_GET(opts, attach_prog_fd, 0);
276d10ef2b8SAndrii Nakryiko attach_btf_obj_fd = OPTS_GET(opts, attach_btf_obj_fd, 0);
277d10ef2b8SAndrii Nakryiko
278d10ef2b8SAndrii Nakryiko if (attach_prog_fd && attach_btf_obj_fd)
279d10ef2b8SAndrii Nakryiko return libbpf_err(-EINVAL);
280d10ef2b8SAndrii Nakryiko
281d10ef2b8SAndrii Nakryiko attr.attach_btf_id = OPTS_GET(opts, attach_btf_id, 0);
282d10ef2b8SAndrii Nakryiko if (attach_prog_fd)
283d10ef2b8SAndrii Nakryiko attr.attach_prog_fd = attach_prog_fd;
28491abb4a6SAndrii Nakryiko else
285d10ef2b8SAndrii Nakryiko attr.attach_btf_obj_fd = attach_btf_obj_fd;
2866aef10a4SAndrii Nakryiko
287d10ef2b8SAndrii Nakryiko log_buf = OPTS_GET(opts, log_buf, NULL);
288d10ef2b8SAndrii Nakryiko log_size = OPTS_GET(opts, log_size, 0);
289d10ef2b8SAndrii Nakryiko log_level = OPTS_GET(opts, log_level, 0);
2906aef10a4SAndrii Nakryiko
291d10ef2b8SAndrii Nakryiko if (!!log_buf != !!log_size)
292d10ef2b8SAndrii Nakryiko return libbpf_err(-EINVAL);
293a4021a35SYonghong Song
294d10ef2b8SAndrii Nakryiko func_info_rec_size = OPTS_GET(opts, func_info_rec_size, 0);
295d10ef2b8SAndrii Nakryiko func_info = OPTS_GET(opts, func_info, NULL);
296d10ef2b8SAndrii Nakryiko attr.func_info_rec_size = func_info_rec_size;
297d10ef2b8SAndrii Nakryiko attr.func_info = ptr_to_u64(func_info);
298d10ef2b8SAndrii Nakryiko attr.func_info_cnt = OPTS_GET(opts, func_info_cnt, 0);
2996aef10a4SAndrii Nakryiko
300d10ef2b8SAndrii Nakryiko line_info_rec_size = OPTS_GET(opts, line_info_rec_size, 0);
301d10ef2b8SAndrii Nakryiko line_info = OPTS_GET(opts, line_info, NULL);
302d10ef2b8SAndrii Nakryiko attr.line_info_rec_size = line_info_rec_size;
303d10ef2b8SAndrii Nakryiko attr.line_info = ptr_to_u64(line_info);
304d10ef2b8SAndrii Nakryiko attr.line_info_cnt = OPTS_GET(opts, line_info_cnt, 0);
3056aef10a4SAndrii Nakryiko
306d10ef2b8SAndrii Nakryiko attr.fd_array = ptr_to_u64(OPTS_GET(opts, fd_array, NULL));
3076aef10a4SAndrii Nakryiko
3084cf23a3cSAndrii Nakryiko if (log_level) {
3094cf23a3cSAndrii Nakryiko attr.log_buf = ptr_to_u64(log_buf);
3104cf23a3cSAndrii Nakryiko attr.log_size = log_size;
3114cf23a3cSAndrii Nakryiko attr.log_level = log_level;
3124cf23a3cSAndrii Nakryiko }
3134cf23a3cSAndrii Nakryiko
314813847a3SAndrii Nakryiko fd = sys_bpf_prog_load(&attr, attr_sz, attempts);
31594e55c0fSAndrii Nakryiko OPTS_SET(opts, log_true_size, attr.log_true_size);
316f0187f0bSMartin KaFai Lau if (fd >= 0)
3177bf98369SWang Nan return fd;
3187bf98369SWang Nan
3192993e051SYonghong Song /* After bpf_prog_load, the kernel may modify certain attributes
3202993e051SYonghong Song * to give user space a hint how to deal with loading failure.
3212993e051SYonghong Song * Check to see whether we can make some changes and load again.
3222993e051SYonghong Song */
3233d650141SMartin KaFai Lau while (errno == E2BIG && (!finfo || !linfo)) {
3243d650141SMartin KaFai Lau if (!finfo && attr.func_info_cnt &&
325d10ef2b8SAndrii Nakryiko attr.func_info_rec_size < func_info_rec_size) {
3262993e051SYonghong Song /* try with corrected func info records */
327d10ef2b8SAndrii Nakryiko finfo = alloc_zero_tailing_info(func_info,
328d10ef2b8SAndrii Nakryiko attr.func_info_cnt,
329d10ef2b8SAndrii Nakryiko func_info_rec_size,
3303d650141SMartin KaFai Lau attr.func_info_rec_size);
331f12b6543SAndrii Nakryiko if (!finfo) {
332f12b6543SAndrii Nakryiko errno = E2BIG;
3333d650141SMartin KaFai Lau goto done;
334f12b6543SAndrii Nakryiko }
3353d650141SMartin KaFai Lau
3362993e051SYonghong Song attr.func_info = ptr_to_u64(finfo);
337d10ef2b8SAndrii Nakryiko attr.func_info_rec_size = func_info_rec_size;
3383d650141SMartin KaFai Lau } else if (!linfo && attr.line_info_cnt &&
339d10ef2b8SAndrii Nakryiko attr.line_info_rec_size < line_info_rec_size) {
340d10ef2b8SAndrii Nakryiko linfo = alloc_zero_tailing_info(line_info,
341d10ef2b8SAndrii Nakryiko attr.line_info_cnt,
342d10ef2b8SAndrii Nakryiko line_info_rec_size,
3433d650141SMartin KaFai Lau attr.line_info_rec_size);
344f12b6543SAndrii Nakryiko if (!linfo) {
345f12b6543SAndrii Nakryiko errno = E2BIG;
3463d650141SMartin KaFai Lau goto done;
347f12b6543SAndrii Nakryiko }
3483d650141SMartin KaFai Lau
3493d650141SMartin KaFai Lau attr.line_info = ptr_to_u64(linfo);
350d10ef2b8SAndrii Nakryiko attr.line_info_rec_size = line_info_rec_size;
3513d650141SMartin KaFai Lau } else {
3523d650141SMartin KaFai Lau break;
3533d650141SMartin KaFai Lau }
3542993e051SYonghong Song
355813847a3SAndrii Nakryiko fd = sys_bpf_prog_load(&attr, attr_sz, attempts);
35694e55c0fSAndrii Nakryiko OPTS_SET(opts, log_true_size, attr.log_true_size);
357f0187f0bSMartin KaFai Lau if (fd >= 0)
3582993e051SYonghong Song goto done;
3592993e051SYonghong Song }
3602993e051SYonghong Song
3614cf23a3cSAndrii Nakryiko if (log_level == 0 && log_buf) {
3624cf23a3cSAndrii Nakryiko /* log_level == 0 with non-NULL log_buf requires retrying on error
3634cf23a3cSAndrii Nakryiko * with log_level == 1 and log_buf/log_buf_size set, to get details of
3644cf23a3cSAndrii Nakryiko * failure
3654cf23a3cSAndrii Nakryiko */
366d10ef2b8SAndrii Nakryiko attr.log_buf = ptr_to_u64(log_buf);
367d10ef2b8SAndrii Nakryiko attr.log_size = log_size;
3687bf98369SWang Nan attr.log_level = 1;
3696aef10a4SAndrii Nakryiko
370813847a3SAndrii Nakryiko fd = sys_bpf_prog_load(&attr, attr_sz, attempts);
37194e55c0fSAndrii Nakryiko OPTS_SET(opts, log_true_size, attr.log_true_size);
3724cf23a3cSAndrii Nakryiko }
3732993e051SYonghong Song done:
374f12b6543SAndrii Nakryiko /* free() doesn't affect errno, so we don't need to restore it */
3752993e051SYonghong Song free(finfo);
3763d650141SMartin KaFai Lau free(linfo);
377f12b6543SAndrii Nakryiko return libbpf_err_errno(fd);
3787bf98369SWang Nan }
37943798bf3SHe Kuang
bpf_map_update_elem(int fd,const void * key,const void * value,__u64 flags)38010ecc728SMickaël Salaün int bpf_map_update_elem(int fd, const void *key, const void *value,
38183d994d0SJoe Stringer __u64 flags)
38243798bf3SHe Kuang {
383813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, flags);
38443798bf3SHe Kuang union bpf_attr attr;
385f12b6543SAndrii Nakryiko int ret;
38643798bf3SHe Kuang
387813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
38843798bf3SHe Kuang attr.map_fd = fd;
38943798bf3SHe Kuang attr.key = ptr_to_u64(key);
39043798bf3SHe Kuang attr.value = ptr_to_u64(value);
39143798bf3SHe Kuang attr.flags = flags;
39243798bf3SHe Kuang
393813847a3SAndrii Nakryiko ret = sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, attr_sz);
394f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
39543798bf3SHe Kuang }
3969742da01SWang Nan
bpf_map_lookup_elem(int fd,const void * key,void * value)397e5ff7c40SMickaël Salaün int bpf_map_lookup_elem(int fd, const void *key, void *value)
3989742da01SWang Nan {
399813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, flags);
4009742da01SWang Nan union bpf_attr attr;
401f12b6543SAndrii Nakryiko int ret;
4029742da01SWang Nan
403813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
4049742da01SWang Nan attr.map_fd = fd;
4059742da01SWang Nan attr.key = ptr_to_u64(key);
4069742da01SWang Nan attr.value = ptr_to_u64(value);
4079742da01SWang Nan
408813847a3SAndrii Nakryiko ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, attr_sz);
409f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
4109742da01SWang Nan }
4119742da01SWang Nan
bpf_map_lookup_elem_flags(int fd,const void * key,void * value,__u64 flags)412df5d22faSAlexei Starovoitov int bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags)
413df5d22faSAlexei Starovoitov {
414813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, flags);
415df5d22faSAlexei Starovoitov union bpf_attr attr;
416f12b6543SAndrii Nakryiko int ret;
417df5d22faSAlexei Starovoitov
418813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
419df5d22faSAlexei Starovoitov attr.map_fd = fd;
420df5d22faSAlexei Starovoitov attr.key = ptr_to_u64(key);
421df5d22faSAlexei Starovoitov attr.value = ptr_to_u64(value);
422df5d22faSAlexei Starovoitov attr.flags = flags;
423df5d22faSAlexei Starovoitov
424813847a3SAndrii Nakryiko ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, attr_sz);
425f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
426df5d22faSAlexei Starovoitov }
427df5d22faSAlexei Starovoitov
bpf_map_lookup_and_delete_elem(int fd,const void * key,void * value)42843b987d2SMauricio Vasquez B int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value)
42943b987d2SMauricio Vasquez B {
430813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, flags);
43143b987d2SMauricio Vasquez B union bpf_attr attr;
432f12b6543SAndrii Nakryiko int ret;
43343b987d2SMauricio Vasquez B
434813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
43543b987d2SMauricio Vasquez B attr.map_fd = fd;
43643b987d2SMauricio Vasquez B attr.key = ptr_to_u64(key);
43743b987d2SMauricio Vasquez B attr.value = ptr_to_u64(value);
43843b987d2SMauricio Vasquez B
439813847a3SAndrii Nakryiko ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, attr_sz);
440f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
44143b987d2SMauricio Vasquez B }
44243b987d2SMauricio Vasquez B
bpf_map_lookup_and_delete_elem_flags(int fd,const void * key,void * value,__u64 flags)443d59b9f2dSDenis Salopek int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key, void *value, __u64 flags)
444d59b9f2dSDenis Salopek {
445813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, flags);
446d59b9f2dSDenis Salopek union bpf_attr attr;
44764165ddfSMehrdad Arshad Rad int ret;
448d59b9f2dSDenis Salopek
449813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
450d59b9f2dSDenis Salopek attr.map_fd = fd;
451d59b9f2dSDenis Salopek attr.key = ptr_to_u64(key);
452d59b9f2dSDenis Salopek attr.value = ptr_to_u64(value);
453d59b9f2dSDenis Salopek attr.flags = flags;
454d59b9f2dSDenis Salopek
455813847a3SAndrii Nakryiko ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, attr_sz);
45664165ddfSMehrdad Arshad Rad return libbpf_err_errno(ret);
457d59b9f2dSDenis Salopek }
458d59b9f2dSDenis Salopek
bpf_map_delete_elem(int fd,const void * key)459e58383b8SMickaël Salaün int bpf_map_delete_elem(int fd, const void *key)
4609742da01SWang Nan {
461813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, flags);
4629742da01SWang Nan union bpf_attr attr;
463f12b6543SAndrii Nakryiko int ret;
4649742da01SWang Nan
465813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
4669742da01SWang Nan attr.map_fd = fd;
4679742da01SWang Nan attr.key = ptr_to_u64(key);
4689742da01SWang Nan
469813847a3SAndrii Nakryiko ret = sys_bpf(BPF_MAP_DELETE_ELEM, &attr, attr_sz);
470f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
4719742da01SWang Nan }
4729742da01SWang Nan
bpf_map_delete_elem_flags(int fd,const void * key,__u64 flags)473737d0646SAndrii Nakryiko int bpf_map_delete_elem_flags(int fd, const void *key, __u64 flags)
474737d0646SAndrii Nakryiko {
475813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, flags);
476737d0646SAndrii Nakryiko union bpf_attr attr;
477737d0646SAndrii Nakryiko int ret;
478737d0646SAndrii Nakryiko
479813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
480737d0646SAndrii Nakryiko attr.map_fd = fd;
481737d0646SAndrii Nakryiko attr.key = ptr_to_u64(key);
482737d0646SAndrii Nakryiko attr.flags = flags;
483737d0646SAndrii Nakryiko
484813847a3SAndrii Nakryiko ret = sys_bpf(BPF_MAP_DELETE_ELEM, &attr, attr_sz);
485737d0646SAndrii Nakryiko return libbpf_err_errno(ret);
486737d0646SAndrii Nakryiko }
487737d0646SAndrii Nakryiko
bpf_map_get_next_key(int fd,const void * key,void * next_key)4885f155c25SMickaël Salaün int bpf_map_get_next_key(int fd, const void *key, void *next_key)
4899742da01SWang Nan {
490813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, next_key);
4919742da01SWang Nan union bpf_attr attr;
492f12b6543SAndrii Nakryiko int ret;
4939742da01SWang Nan
494813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
4959742da01SWang Nan attr.map_fd = fd;
4969742da01SWang Nan attr.key = ptr_to_u64(key);
4979742da01SWang Nan attr.next_key = ptr_to_u64(next_key);
4989742da01SWang Nan
499813847a3SAndrii Nakryiko ret = sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, attr_sz);
500f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
5019742da01SWang Nan }
5029742da01SWang Nan
bpf_map_freeze(int fd)503d859900cSDaniel Borkmann int bpf_map_freeze(int fd)
504d859900cSDaniel Borkmann {
505813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, map_fd);
506d859900cSDaniel Borkmann union bpf_attr attr;
507f12b6543SAndrii Nakryiko int ret;
508d859900cSDaniel Borkmann
509813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
510d859900cSDaniel Borkmann attr.map_fd = fd;
511d859900cSDaniel Borkmann
512813847a3SAndrii Nakryiko ret = sys_bpf(BPF_MAP_FREEZE, &attr, attr_sz);
513f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
514d859900cSDaniel Borkmann }
515d859900cSDaniel Borkmann
bpf_map_batch_common(int cmd,int fd,void * in_batch,void * out_batch,void * keys,void * values,__u32 * count,const struct bpf_map_batch_opts * opts)5162ab3d86eSYonghong Song static int bpf_map_batch_common(int cmd, int fd, void *in_batch,
5172ab3d86eSYonghong Song void *out_batch, void *keys, void *values,
5182ab3d86eSYonghong Song __u32 *count,
5192ab3d86eSYonghong Song const struct bpf_map_batch_opts *opts)
5202ab3d86eSYonghong Song {
521813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, batch);
522858e284fSBrian Vazquez union bpf_attr attr;
5232ab3d86eSYonghong Song int ret;
5242ab3d86eSYonghong Song
5252ab3d86eSYonghong Song if (!OPTS_VALID(opts, bpf_map_batch_opts))
526f12b6543SAndrii Nakryiko return libbpf_err(-EINVAL);
5272ab3d86eSYonghong Song
528813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
5292ab3d86eSYonghong Song attr.batch.map_fd = fd;
5302ab3d86eSYonghong Song attr.batch.in_batch = ptr_to_u64(in_batch);
5312ab3d86eSYonghong Song attr.batch.out_batch = ptr_to_u64(out_batch);
5322ab3d86eSYonghong Song attr.batch.keys = ptr_to_u64(keys);
5332ab3d86eSYonghong Song attr.batch.values = ptr_to_u64(values);
5342ab3d86eSYonghong Song attr.batch.count = *count;
5352ab3d86eSYonghong Song attr.batch.elem_flags = OPTS_GET(opts, elem_flags, 0);
5362ab3d86eSYonghong Song attr.batch.flags = OPTS_GET(opts, flags, 0);
5372ab3d86eSYonghong Song
538813847a3SAndrii Nakryiko ret = sys_bpf(cmd, &attr, attr_sz);
5392ab3d86eSYonghong Song *count = attr.batch.count;
5402ab3d86eSYonghong Song
541f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
5422ab3d86eSYonghong Song }
5432ab3d86eSYonghong Song
bpf_map_delete_batch(int fd,const void * keys,__u32 * count,const struct bpf_map_batch_opts * opts)544e59618f0SGrant Seltzer int bpf_map_delete_batch(int fd, const void *keys, __u32 *count,
5452ab3d86eSYonghong Song const struct bpf_map_batch_opts *opts)
5462ab3d86eSYonghong Song {
5472ab3d86eSYonghong Song return bpf_map_batch_common(BPF_MAP_DELETE_BATCH, fd, NULL,
548e59618f0SGrant Seltzer NULL, (void *)keys, NULL, count, opts);
5492ab3d86eSYonghong Song }
5502ab3d86eSYonghong Song
bpf_map_lookup_batch(int fd,void * in_batch,void * out_batch,void * keys,void * values,__u32 * count,const struct bpf_map_batch_opts * opts)5512ab3d86eSYonghong Song int bpf_map_lookup_batch(int fd, void *in_batch, void *out_batch, void *keys,
5522ab3d86eSYonghong Song void *values, __u32 *count,
5532ab3d86eSYonghong Song const struct bpf_map_batch_opts *opts)
5542ab3d86eSYonghong Song {
5552ab3d86eSYonghong Song return bpf_map_batch_common(BPF_MAP_LOOKUP_BATCH, fd, in_batch,
5562ab3d86eSYonghong Song out_batch, keys, values, count, opts);
5572ab3d86eSYonghong Song }
5582ab3d86eSYonghong Song
bpf_map_lookup_and_delete_batch(int fd,void * in_batch,void * out_batch,void * keys,void * values,__u32 * count,const struct bpf_map_batch_opts * opts)5592ab3d86eSYonghong Song int bpf_map_lookup_and_delete_batch(int fd, void *in_batch, void *out_batch,
5602ab3d86eSYonghong Song void *keys, void *values, __u32 *count,
5612ab3d86eSYonghong Song const struct bpf_map_batch_opts *opts)
5622ab3d86eSYonghong Song {
5632ab3d86eSYonghong Song return bpf_map_batch_common(BPF_MAP_LOOKUP_AND_DELETE_BATCH,
5642ab3d86eSYonghong Song fd, in_batch, out_batch, keys, values,
5652ab3d86eSYonghong Song count, opts);
5662ab3d86eSYonghong Song }
5672ab3d86eSYonghong Song
bpf_map_update_batch(int fd,const void * keys,const void * values,__u32 * count,const struct bpf_map_batch_opts * opts)568e59618f0SGrant Seltzer int bpf_map_update_batch(int fd, const void *keys, const void *values, __u32 *count,
5692ab3d86eSYonghong Song const struct bpf_map_batch_opts *opts)
5702ab3d86eSYonghong Song {
5712ab3d86eSYonghong Song return bpf_map_batch_common(BPF_MAP_UPDATE_BATCH, fd, NULL, NULL,
572e59618f0SGrant Seltzer (void *)keys, (void *)values, count, opts);
5732ab3d86eSYonghong Song }
5742ab3d86eSYonghong Song
bpf_obj_pin_opts(int fd,const char * pathname,const struct bpf_obj_pin_opts * opts)575f1674dc7SAndrii Nakryiko int bpf_obj_pin_opts(int fd, const char *pathname, const struct bpf_obj_pin_opts *opts)
5769742da01SWang Nan {
577f1674dc7SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, path_fd);
5789742da01SWang Nan union bpf_attr attr;
579f12b6543SAndrii Nakryiko int ret;
5809742da01SWang Nan
581f1674dc7SAndrii Nakryiko if (!OPTS_VALID(opts, bpf_obj_pin_opts))
582f1674dc7SAndrii Nakryiko return libbpf_err(-EINVAL);
583f1674dc7SAndrii Nakryiko
584813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
585f1674dc7SAndrii Nakryiko attr.path_fd = OPTS_GET(opts, path_fd, 0);
5869742da01SWang Nan attr.pathname = ptr_to_u64((void *)pathname);
587f1674dc7SAndrii Nakryiko attr.file_flags = OPTS_GET(opts, file_flags, 0);
5889742da01SWang Nan attr.bpf_fd = fd;
5899742da01SWang Nan
590813847a3SAndrii Nakryiko ret = sys_bpf(BPF_OBJ_PIN, &attr, attr_sz);
591f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
5929742da01SWang Nan }
5939742da01SWang Nan
bpf_obj_pin(int fd,const char * pathname)594f1674dc7SAndrii Nakryiko int bpf_obj_pin(int fd, const char *pathname)
595f1674dc7SAndrii Nakryiko {
596f1674dc7SAndrii Nakryiko return bpf_obj_pin_opts(fd, pathname, NULL);
597f1674dc7SAndrii Nakryiko }
598f1674dc7SAndrii Nakryiko
bpf_obj_get(const char * pathname)5999742da01SWang Nan int bpf_obj_get(const char *pathname)
6009742da01SWang Nan {
601395fc4faSJoe Burton return bpf_obj_get_opts(pathname, NULL);
602395fc4faSJoe Burton }
603395fc4faSJoe Burton
bpf_obj_get_opts(const char * pathname,const struct bpf_obj_get_opts * opts)604395fc4faSJoe Burton int bpf_obj_get_opts(const char *pathname, const struct bpf_obj_get_opts *opts)
605395fc4faSJoe Burton {
606f1674dc7SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, path_fd);
6079742da01SWang Nan union bpf_attr attr;
608f12b6543SAndrii Nakryiko int fd;
6099742da01SWang Nan
610395fc4faSJoe Burton if (!OPTS_VALID(opts, bpf_obj_get_opts))
611395fc4faSJoe Burton return libbpf_err(-EINVAL);
612395fc4faSJoe Burton
613813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
614f1674dc7SAndrii Nakryiko attr.path_fd = OPTS_GET(opts, path_fd, 0);
6159742da01SWang Nan attr.pathname = ptr_to_u64((void *)pathname);
616395fc4faSJoe Burton attr.file_flags = OPTS_GET(opts, file_flags, 0);
6179742da01SWang Nan
618813847a3SAndrii Nakryiko fd = sys_bpf_fd(BPF_OBJ_GET, &attr, attr_sz);
619f12b6543SAndrii Nakryiko return libbpf_err_errno(fd);
6209742da01SWang Nan }
6215dc880deSJoe Stringer
bpf_prog_attach(int prog_fd,int target_fd,enum bpf_attach_type type,unsigned int flags)622464bc0fdSJohn Fastabend int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type,
6237f677633SAlexei Starovoitov unsigned int flags)
6245dc880deSJoe Stringer {
625cdbee383SAndrey Ignatov DECLARE_LIBBPF_OPTS(bpf_prog_attach_opts, opts,
626cdbee383SAndrey Ignatov .flags = flags,
627cdbee383SAndrey Ignatov );
628cdbee383SAndrey Ignatov
629d6c9c24eSChristy Lee return bpf_prog_attach_opts(prog_fd, target_fd, type, &opts);
630cdbee383SAndrey Ignatov }
631cdbee383SAndrey Ignatov
bpf_prog_attach_opts(int prog_fd,int target,enum bpf_attach_type type,const struct bpf_prog_attach_opts * opts)632fe20ce3aSDaniel Borkmann int bpf_prog_attach_opts(int prog_fd, int target, enum bpf_attach_type type,
633cdbee383SAndrey Ignatov const struct bpf_prog_attach_opts *opts)
634cdbee383SAndrey Ignatov {
635fe20ce3aSDaniel Borkmann const size_t attr_sz = offsetofend(union bpf_attr, expected_revision);
636fe20ce3aSDaniel Borkmann __u32 relative_id, flags;
637fe20ce3aSDaniel Borkmann int ret, relative_fd;
6385dc880deSJoe Stringer union bpf_attr attr;
6395dc880deSJoe Stringer
640cdbee383SAndrey Ignatov if (!OPTS_VALID(opts, bpf_prog_attach_opts))
641f12b6543SAndrii Nakryiko return libbpf_err(-EINVAL);
642cdbee383SAndrey Ignatov
643fe20ce3aSDaniel Borkmann relative_id = OPTS_GET(opts, relative_id, 0);
644fe20ce3aSDaniel Borkmann relative_fd = OPTS_GET(opts, relative_fd, 0);
645fe20ce3aSDaniel Borkmann flags = OPTS_GET(opts, flags, 0);
646fe20ce3aSDaniel Borkmann
647fe20ce3aSDaniel Borkmann /* validate we don't have unexpected combinations of non-zero fields */
648fe20ce3aSDaniel Borkmann if (relative_fd && relative_id)
649fe20ce3aSDaniel Borkmann return libbpf_err(-EINVAL);
650fe20ce3aSDaniel Borkmann
651813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
652fe20ce3aSDaniel Borkmann attr.target_fd = target;
653464bc0fdSJohn Fastabend attr.attach_bpf_fd = prog_fd;
6545dc880deSJoe Stringer attr.attach_type = type;
655fe20ce3aSDaniel Borkmann attr.replace_bpf_fd = OPTS_GET(opts, replace_fd, 0);
656fe20ce3aSDaniel Borkmann attr.expected_revision = OPTS_GET(opts, expected_revision, 0);
657fe20ce3aSDaniel Borkmann
658fe20ce3aSDaniel Borkmann if (relative_id) {
659fe20ce3aSDaniel Borkmann attr.attach_flags = flags | BPF_F_ID;
660fe20ce3aSDaniel Borkmann attr.relative_id = relative_id;
661fe20ce3aSDaniel Borkmann } else {
662fe20ce3aSDaniel Borkmann attr.attach_flags = flags;
663fe20ce3aSDaniel Borkmann attr.relative_fd = relative_fd;
664fe20ce3aSDaniel Borkmann }
6655dc880deSJoe Stringer
666813847a3SAndrii Nakryiko ret = sys_bpf(BPF_PROG_ATTACH, &attr, attr_sz);
667f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
6685dc880deSJoe Stringer }
6695dc880deSJoe Stringer
bpf_prog_detach_opts(int prog_fd,int target,enum bpf_attach_type type,const struct bpf_prog_detach_opts * opts)670fe20ce3aSDaniel Borkmann int bpf_prog_detach_opts(int prog_fd, int target, enum bpf_attach_type type,
671fe20ce3aSDaniel Borkmann const struct bpf_prog_detach_opts *opts)
6725dc880deSJoe Stringer {
673fe20ce3aSDaniel Borkmann const size_t attr_sz = offsetofend(union bpf_attr, expected_revision);
674fe20ce3aSDaniel Borkmann __u32 relative_id, flags;
675fe20ce3aSDaniel Borkmann int ret, relative_fd;
6765dc880deSJoe Stringer union bpf_attr attr;
677fe20ce3aSDaniel Borkmann
678fe20ce3aSDaniel Borkmann if (!OPTS_VALID(opts, bpf_prog_detach_opts))
679fe20ce3aSDaniel Borkmann return libbpf_err(-EINVAL);
680fe20ce3aSDaniel Borkmann
681fe20ce3aSDaniel Borkmann relative_id = OPTS_GET(opts, relative_id, 0);
682fe20ce3aSDaniel Borkmann relative_fd = OPTS_GET(opts, relative_fd, 0);
683fe20ce3aSDaniel Borkmann flags = OPTS_GET(opts, flags, 0);
684fe20ce3aSDaniel Borkmann
685fe20ce3aSDaniel Borkmann /* validate we don't have unexpected combinations of non-zero fields */
686fe20ce3aSDaniel Borkmann if (relative_fd && relative_id)
687fe20ce3aSDaniel Borkmann return libbpf_err(-EINVAL);
6885dc880deSJoe Stringer
689813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
690fe20ce3aSDaniel Borkmann attr.target_fd = target;
691fe20ce3aSDaniel Borkmann attr.attach_bpf_fd = prog_fd;
6925dc880deSJoe Stringer attr.attach_type = type;
693fe20ce3aSDaniel Borkmann attr.expected_revision = OPTS_GET(opts, expected_revision, 0);
694fe20ce3aSDaniel Borkmann
695fe20ce3aSDaniel Borkmann if (relative_id) {
696fe20ce3aSDaniel Borkmann attr.attach_flags = flags | BPF_F_ID;
697fe20ce3aSDaniel Borkmann attr.relative_id = relative_id;
698fe20ce3aSDaniel Borkmann } else {
699fe20ce3aSDaniel Borkmann attr.attach_flags = flags;
700fe20ce3aSDaniel Borkmann attr.relative_fd = relative_fd;
701fe20ce3aSDaniel Borkmann }
7025dc880deSJoe Stringer
703813847a3SAndrii Nakryiko ret = sys_bpf(BPF_PROG_DETACH, &attr, attr_sz);
704f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
7055dc880deSJoe Stringer }
70630848873SAlexei Starovoitov
bpf_prog_detach(int target_fd,enum bpf_attach_type type)707fe20ce3aSDaniel Borkmann int bpf_prog_detach(int target_fd, enum bpf_attach_type type)
708fe20ce3aSDaniel Borkmann {
709fe20ce3aSDaniel Borkmann return bpf_prog_detach_opts(0, target_fd, type, NULL);
710fe20ce3aSDaniel Borkmann }
711fe20ce3aSDaniel Borkmann
bpf_prog_detach2(int prog_fd,int target_fd,enum bpf_attach_type type)712244d20efSAlexei Starovoitov int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type)
713244d20efSAlexei Starovoitov {
714fe20ce3aSDaniel Borkmann return bpf_prog_detach_opts(prog_fd, target_fd, type, NULL);
715244d20efSAlexei Starovoitov }
716244d20efSAlexei Starovoitov
bpf_link_create(int prog_fd,int target_fd,enum bpf_attach_type attach_type,const struct bpf_link_create_opts * opts)717cc4f864bSAndrii Nakryiko int bpf_link_create(int prog_fd, int target_fd,
718cc4f864bSAndrii Nakryiko enum bpf_attach_type attach_type,
719cc4f864bSAndrii Nakryiko const struct bpf_link_create_opts *opts)
720cc4f864bSAndrii Nakryiko {
721813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, link_create);
72255cc3768SDaniel Borkmann __u32 target_btf_id, iter_info_len, relative_id;
72355cc3768SDaniel Borkmann int fd, err, relative_fd;
724cc4f864bSAndrii Nakryiko union bpf_attr attr;
725cc4f864bSAndrii Nakryiko
726cc4f864bSAndrii Nakryiko if (!OPTS_VALID(opts, bpf_link_create_opts))
727f12b6543SAndrii Nakryiko return libbpf_err(-EINVAL);
728cc4f864bSAndrii Nakryiko
729a5359091SToke Høiland-Jørgensen iter_info_len = OPTS_GET(opts, iter_info_len, 0);
730a5359091SToke Høiland-Jørgensen target_btf_id = OPTS_GET(opts, target_btf_id, 0);
731a5359091SToke Høiland-Jørgensen
7323ec84f4bSAndrii Nakryiko /* validate we don't have unexpected combinations of non-zero fields */
7333ec84f4bSAndrii Nakryiko if (iter_info_len || target_btf_id) {
734a5359091SToke Høiland-Jørgensen if (iter_info_len && target_btf_id)
735f12b6543SAndrii Nakryiko return libbpf_err(-EINVAL);
7363ec84f4bSAndrii Nakryiko if (!OPTS_ZEROED(opts, target_btf_id))
7373ec84f4bSAndrii Nakryiko return libbpf_err(-EINVAL);
7383ec84f4bSAndrii Nakryiko }
739a5359091SToke Høiland-Jørgensen
740813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
741cc4f864bSAndrii Nakryiko attr.link_create.prog_fd = prog_fd;
742cc4f864bSAndrii Nakryiko attr.link_create.target_fd = target_fd;
743cc4f864bSAndrii Nakryiko attr.link_create.attach_type = attach_type;
744cd31039aSYonghong Song attr.link_create.flags = OPTS_GET(opts, flags, 0);
745a5359091SToke Høiland-Jørgensen
7463ec84f4bSAndrii Nakryiko if (target_btf_id) {
747a5359091SToke Høiland-Jørgensen attr.link_create.target_btf_id = target_btf_id;
7483ec84f4bSAndrii Nakryiko goto proceed;
749a5359091SToke Høiland-Jørgensen }
750cc4f864bSAndrii Nakryiko
7513ec84f4bSAndrii Nakryiko switch (attach_type) {
7523ec84f4bSAndrii Nakryiko case BPF_TRACE_ITER:
7533ec84f4bSAndrii Nakryiko attr.link_create.iter_info = ptr_to_u64(OPTS_GET(opts, iter_info, (void *)0));
7543ec84f4bSAndrii Nakryiko attr.link_create.iter_info_len = iter_info_len;
7553ec84f4bSAndrii Nakryiko break;
7563ec84f4bSAndrii Nakryiko case BPF_PERF_EVENT:
7573ec84f4bSAndrii Nakryiko attr.link_create.perf_event.bpf_cookie = OPTS_GET(opts, perf_event.bpf_cookie, 0);
7583ec84f4bSAndrii Nakryiko if (!OPTS_ZEROED(opts, perf_event))
7593ec84f4bSAndrii Nakryiko return libbpf_err(-EINVAL);
7603ec84f4bSAndrii Nakryiko break;
7615117c26eSJiri Olsa case BPF_TRACE_KPROBE_MULTI:
7625117c26eSJiri Olsa attr.link_create.kprobe_multi.flags = OPTS_GET(opts, kprobe_multi.flags, 0);
7635117c26eSJiri Olsa attr.link_create.kprobe_multi.cnt = OPTS_GET(opts, kprobe_multi.cnt, 0);
7645117c26eSJiri Olsa attr.link_create.kprobe_multi.syms = ptr_to_u64(OPTS_GET(opts, kprobe_multi.syms, 0));
7655117c26eSJiri Olsa attr.link_create.kprobe_multi.addrs = ptr_to_u64(OPTS_GET(opts, kprobe_multi.addrs, 0));
7665117c26eSJiri Olsa attr.link_create.kprobe_multi.cookies = ptr_to_u64(OPTS_GET(opts, kprobe_multi.cookies, 0));
7675117c26eSJiri Olsa if (!OPTS_ZEROED(opts, kprobe_multi))
7685117c26eSJiri Olsa return libbpf_err(-EINVAL);
7695117c26eSJiri Olsa break;
770*5054a303SJiri Olsa case BPF_TRACE_UPROBE_MULTI:
771*5054a303SJiri Olsa attr.link_create.uprobe_multi.flags = OPTS_GET(opts, uprobe_multi.flags, 0);
772*5054a303SJiri Olsa attr.link_create.uprobe_multi.cnt = OPTS_GET(opts, uprobe_multi.cnt, 0);
773*5054a303SJiri Olsa attr.link_create.uprobe_multi.path = ptr_to_u64(OPTS_GET(opts, uprobe_multi.path, 0));
774*5054a303SJiri Olsa attr.link_create.uprobe_multi.offsets = ptr_to_u64(OPTS_GET(opts, uprobe_multi.offsets, 0));
775*5054a303SJiri Olsa attr.link_create.uprobe_multi.ref_ctr_offsets = ptr_to_u64(OPTS_GET(opts, uprobe_multi.ref_ctr_offsets, 0));
776*5054a303SJiri Olsa attr.link_create.uprobe_multi.cookies = ptr_to_u64(OPTS_GET(opts, uprobe_multi.cookies, 0));
777*5054a303SJiri Olsa attr.link_create.uprobe_multi.pid = OPTS_GET(opts, uprobe_multi.pid, 0);
778*5054a303SJiri Olsa if (!OPTS_ZEROED(opts, uprobe_multi))
779*5054a303SJiri Olsa return libbpf_err(-EINVAL);
780*5054a303SJiri Olsa break;
781129b9c5eSKui-Feng Lee case BPF_TRACE_FENTRY:
782129b9c5eSKui-Feng Lee case BPF_TRACE_FEXIT:
783129b9c5eSKui-Feng Lee case BPF_MODIFY_RETURN:
784129b9c5eSKui-Feng Lee case BPF_LSM_MAC:
785129b9c5eSKui-Feng Lee attr.link_create.tracing.cookie = OPTS_GET(opts, tracing.cookie, 0);
786129b9c5eSKui-Feng Lee if (!OPTS_ZEROED(opts, tracing))
787129b9c5eSKui-Feng Lee return libbpf_err(-EINVAL);
788129b9c5eSKui-Feng Lee break;
78952364abbSFlorian Westphal case BPF_NETFILTER:
79052364abbSFlorian Westphal attr.link_create.netfilter.pf = OPTS_GET(opts, netfilter.pf, 0);
79152364abbSFlorian Westphal attr.link_create.netfilter.hooknum = OPTS_GET(opts, netfilter.hooknum, 0);
79252364abbSFlorian Westphal attr.link_create.netfilter.priority = OPTS_GET(opts, netfilter.priority, 0);
79352364abbSFlorian Westphal attr.link_create.netfilter.flags = OPTS_GET(opts, netfilter.flags, 0);
79452364abbSFlorian Westphal if (!OPTS_ZEROED(opts, netfilter))
79552364abbSFlorian Westphal return libbpf_err(-EINVAL);
79652364abbSFlorian Westphal break;
79755cc3768SDaniel Borkmann case BPF_TCX_INGRESS:
79855cc3768SDaniel Borkmann case BPF_TCX_EGRESS:
79955cc3768SDaniel Borkmann relative_fd = OPTS_GET(opts, tcx.relative_fd, 0);
80055cc3768SDaniel Borkmann relative_id = OPTS_GET(opts, tcx.relative_id, 0);
80155cc3768SDaniel Borkmann if (relative_fd && relative_id)
80255cc3768SDaniel Borkmann return libbpf_err(-EINVAL);
80355cc3768SDaniel Borkmann if (relative_id) {
80455cc3768SDaniel Borkmann attr.link_create.tcx.relative_id = relative_id;
80555cc3768SDaniel Borkmann attr.link_create.flags |= BPF_F_ID;
80655cc3768SDaniel Borkmann } else {
80755cc3768SDaniel Borkmann attr.link_create.tcx.relative_fd = relative_fd;
80855cc3768SDaniel Borkmann }
80955cc3768SDaniel Borkmann attr.link_create.tcx.expected_revision = OPTS_GET(opts, tcx.expected_revision, 0);
81055cc3768SDaniel Borkmann if (!OPTS_ZEROED(opts, tcx))
81155cc3768SDaniel Borkmann return libbpf_err(-EINVAL);
81255cc3768SDaniel Borkmann break;
8133ec84f4bSAndrii Nakryiko default:
8143ec84f4bSAndrii Nakryiko if (!OPTS_ZEROED(opts, flags))
8153ec84f4bSAndrii Nakryiko return libbpf_err(-EINVAL);
8163ec84f4bSAndrii Nakryiko break;
8173ec84f4bSAndrii Nakryiko }
8183ec84f4bSAndrii Nakryiko proceed:
819813847a3SAndrii Nakryiko fd = sys_bpf_fd(BPF_LINK_CREATE, &attr, attr_sz);
8208462e0b4SAndrii Nakryiko if (fd >= 0)
8218462e0b4SAndrii Nakryiko return fd;
8228462e0b4SAndrii Nakryiko /* we'll get EINVAL if LINK_CREATE doesn't support attaching fentry
8238462e0b4SAndrii Nakryiko * and other similar programs
8248462e0b4SAndrii Nakryiko */
8258462e0b4SAndrii Nakryiko err = -errno;
8268462e0b4SAndrii Nakryiko if (err != -EINVAL)
8278462e0b4SAndrii Nakryiko return libbpf_err(err);
8288462e0b4SAndrii Nakryiko
8298462e0b4SAndrii Nakryiko /* if user used features not supported by
8308462e0b4SAndrii Nakryiko * BPF_RAW_TRACEPOINT_OPEN command, then just give up immediately
8318462e0b4SAndrii Nakryiko */
8328462e0b4SAndrii Nakryiko if (attr.link_create.target_fd || attr.link_create.target_btf_id)
8338462e0b4SAndrii Nakryiko return libbpf_err(err);
8348462e0b4SAndrii Nakryiko if (!OPTS_ZEROED(opts, sz))
8358462e0b4SAndrii Nakryiko return libbpf_err(err);
8368462e0b4SAndrii Nakryiko
8378462e0b4SAndrii Nakryiko /* otherwise, for few select kinds of programs that can be
8388462e0b4SAndrii Nakryiko * attached using BPF_RAW_TRACEPOINT_OPEN command, try that as
8398462e0b4SAndrii Nakryiko * a fallback for older kernels
8408462e0b4SAndrii Nakryiko */
8418462e0b4SAndrii Nakryiko switch (attach_type) {
8428462e0b4SAndrii Nakryiko case BPF_TRACE_RAW_TP:
8438462e0b4SAndrii Nakryiko case BPF_LSM_MAC:
8448462e0b4SAndrii Nakryiko case BPF_TRACE_FENTRY:
8458462e0b4SAndrii Nakryiko case BPF_TRACE_FEXIT:
8468462e0b4SAndrii Nakryiko case BPF_MODIFY_RETURN:
8478462e0b4SAndrii Nakryiko return bpf_raw_tracepoint_open(NULL, prog_fd);
8488462e0b4SAndrii Nakryiko default:
8498462e0b4SAndrii Nakryiko return libbpf_err(err);
8508462e0b4SAndrii Nakryiko }
851cc4f864bSAndrii Nakryiko }
852cc4f864bSAndrii Nakryiko
bpf_link_detach(int link_fd)8532e49527eSAndrii Nakryiko int bpf_link_detach(int link_fd)
8542e49527eSAndrii Nakryiko {
855813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, link_detach);
8562e49527eSAndrii Nakryiko union bpf_attr attr;
857f12b6543SAndrii Nakryiko int ret;
8582e49527eSAndrii Nakryiko
859813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
8602e49527eSAndrii Nakryiko attr.link_detach.link_fd = link_fd;
8612e49527eSAndrii Nakryiko
862813847a3SAndrii Nakryiko ret = sys_bpf(BPF_LINK_DETACH, &attr, attr_sz);
863f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
8642e49527eSAndrii Nakryiko }
8652e49527eSAndrii Nakryiko
bpf_link_update(int link_fd,int new_prog_fd,const struct bpf_link_update_opts * opts)866cc4f864bSAndrii Nakryiko int bpf_link_update(int link_fd, int new_prog_fd,
867cc4f864bSAndrii Nakryiko const struct bpf_link_update_opts *opts)
868cc4f864bSAndrii Nakryiko {
869813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, link_update);
870cc4f864bSAndrii Nakryiko union bpf_attr attr;
871f12b6543SAndrii Nakryiko int ret;
872cc4f864bSAndrii Nakryiko
873cc4f864bSAndrii Nakryiko if (!OPTS_VALID(opts, bpf_link_update_opts))
874f12b6543SAndrii Nakryiko return libbpf_err(-EINVAL);
875cc4f864bSAndrii Nakryiko
876912dd4b0SKui-Feng Lee if (OPTS_GET(opts, old_prog_fd, 0) && OPTS_GET(opts, old_map_fd, 0))
877912dd4b0SKui-Feng Lee return libbpf_err(-EINVAL);
878912dd4b0SKui-Feng Lee
879813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
880cc4f864bSAndrii Nakryiko attr.link_update.link_fd = link_fd;
881cc4f864bSAndrii Nakryiko attr.link_update.new_prog_fd = new_prog_fd;
882cc4f864bSAndrii Nakryiko attr.link_update.flags = OPTS_GET(opts, flags, 0);
883912dd4b0SKui-Feng Lee if (OPTS_GET(opts, old_prog_fd, 0))
884cc4f864bSAndrii Nakryiko attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0);
885912dd4b0SKui-Feng Lee else if (OPTS_GET(opts, old_map_fd, 0))
886912dd4b0SKui-Feng Lee attr.link_update.old_map_fd = OPTS_GET(opts, old_map_fd, 0);
887cc4f864bSAndrii Nakryiko
888813847a3SAndrii Nakryiko ret = sys_bpf(BPF_LINK_UPDATE, &attr, attr_sz);
889f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
890cc4f864bSAndrii Nakryiko }
891cc4f864bSAndrii Nakryiko
bpf_iter_create(int link_fd)892c09add2fSYonghong Song int bpf_iter_create(int link_fd)
893c09add2fSYonghong Song {
894813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, iter_create);
895c09add2fSYonghong Song union bpf_attr attr;
896f12b6543SAndrii Nakryiko int fd;
897c09add2fSYonghong Song
898813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
899c09add2fSYonghong Song attr.iter_create.link_fd = link_fd;
900c09add2fSYonghong Song
901813847a3SAndrii Nakryiko fd = sys_bpf_fd(BPF_ITER_CREATE, &attr, attr_sz);
902f12b6543SAndrii Nakryiko return libbpf_err_errno(fd);
903c09add2fSYonghong Song }
904c09add2fSYonghong Song
bpf_prog_query_opts(int target,enum bpf_attach_type type,struct bpf_prog_query_opts * opts)905fe20ce3aSDaniel Borkmann int bpf_prog_query_opts(int target, enum bpf_attach_type type,
906a4b2f3cfSStanislav Fomichev struct bpf_prog_query_opts *opts)
9075d0cbf9bSAlexei Starovoitov {
908813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, query);
9095d0cbf9bSAlexei Starovoitov union bpf_attr attr;
9105d0cbf9bSAlexei Starovoitov int ret;
9115d0cbf9bSAlexei Starovoitov
912a4b2f3cfSStanislav Fomichev if (!OPTS_VALID(opts, bpf_prog_query_opts))
913a4b2f3cfSStanislav Fomichev return libbpf_err(-EINVAL);
914a4b2f3cfSStanislav Fomichev
915813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
916fe20ce3aSDaniel Borkmann attr.query.target_fd = target;
9175d0cbf9bSAlexei Starovoitov attr.query.attach_type = type;
918a4b2f3cfSStanislav Fomichev attr.query.query_flags = OPTS_GET(opts, query_flags, 0);
919fe20ce3aSDaniel Borkmann attr.query.count = OPTS_GET(opts, count, 0);
920a4b2f3cfSStanislav Fomichev attr.query.prog_ids = ptr_to_u64(OPTS_GET(opts, prog_ids, NULL));
921fe20ce3aSDaniel Borkmann attr.query.link_ids = ptr_to_u64(OPTS_GET(opts, link_ids, NULL));
922a4b2f3cfSStanislav Fomichev attr.query.prog_attach_flags = ptr_to_u64(OPTS_GET(opts, prog_attach_flags, NULL));
923fe20ce3aSDaniel Borkmann attr.query.link_attach_flags = ptr_to_u64(OPTS_GET(opts, link_attach_flags, NULL));
9245d0cbf9bSAlexei Starovoitov
925813847a3SAndrii Nakryiko ret = sys_bpf(BPF_PROG_QUERY, &attr, attr_sz);
926f12b6543SAndrii Nakryiko
927a4b2f3cfSStanislav Fomichev OPTS_SET(opts, attach_flags, attr.query.attach_flags);
928fe20ce3aSDaniel Borkmann OPTS_SET(opts, revision, attr.query.revision);
929fe20ce3aSDaniel Borkmann OPTS_SET(opts, count, attr.query.count);
930a4b2f3cfSStanislav Fomichev
931a4b2f3cfSStanislav Fomichev return libbpf_err_errno(ret);
932a4b2f3cfSStanislav Fomichev }
933a4b2f3cfSStanislav Fomichev
bpf_prog_query(int target_fd,enum bpf_attach_type type,__u32 query_flags,__u32 * attach_flags,__u32 * prog_ids,__u32 * prog_cnt)934a4b2f3cfSStanislav Fomichev int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
935a4b2f3cfSStanislav Fomichev __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt)
936a4b2f3cfSStanislav Fomichev {
937a4b2f3cfSStanislav Fomichev LIBBPF_OPTS(bpf_prog_query_opts, opts);
938a4b2f3cfSStanislav Fomichev int ret;
939a4b2f3cfSStanislav Fomichev
940a4b2f3cfSStanislav Fomichev opts.query_flags = query_flags;
941a4b2f3cfSStanislav Fomichev opts.prog_ids = prog_ids;
942a4b2f3cfSStanislav Fomichev opts.prog_cnt = *prog_cnt;
943a4b2f3cfSStanislav Fomichev
944a4b2f3cfSStanislav Fomichev ret = bpf_prog_query_opts(target_fd, type, &opts);
945a4b2f3cfSStanislav Fomichev
9465d0cbf9bSAlexei Starovoitov if (attach_flags)
947a4b2f3cfSStanislav Fomichev *attach_flags = opts.attach_flags;
948a4b2f3cfSStanislav Fomichev *prog_cnt = opts.prog_cnt;
949f12b6543SAndrii Nakryiko
950f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
9515d0cbf9bSAlexei Starovoitov }
9525d0cbf9bSAlexei Starovoitov
bpf_prog_test_run_opts(int prog_fd,struct bpf_test_run_opts * opts)95388f7fe72SSong Liu int bpf_prog_test_run_opts(int prog_fd, struct bpf_test_run_opts *opts)
95488f7fe72SSong Liu {
955813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, test);
95688f7fe72SSong Liu union bpf_attr attr;
95788f7fe72SSong Liu int ret;
95888f7fe72SSong Liu
95988f7fe72SSong Liu if (!OPTS_VALID(opts, bpf_test_run_opts))
960f12b6543SAndrii Nakryiko return libbpf_err(-EINVAL);
96188f7fe72SSong Liu
962813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
96388f7fe72SSong Liu attr.test.prog_fd = prog_fd;
96424592ad1SToke Høiland-Jørgensen attr.test.batch_size = OPTS_GET(opts, batch_size, 0);
96588f7fe72SSong Liu attr.test.cpu = OPTS_GET(opts, cpu, 0);
96688f7fe72SSong Liu attr.test.flags = OPTS_GET(opts, flags, 0);
96788f7fe72SSong Liu attr.test.repeat = OPTS_GET(opts, repeat, 0);
96888f7fe72SSong Liu attr.test.duration = OPTS_GET(opts, duration, 0);
96988f7fe72SSong Liu attr.test.ctx_size_in = OPTS_GET(opts, ctx_size_in, 0);
97088f7fe72SSong Liu attr.test.ctx_size_out = OPTS_GET(opts, ctx_size_out, 0);
97188f7fe72SSong Liu attr.test.data_size_in = OPTS_GET(opts, data_size_in, 0);
97288f7fe72SSong Liu attr.test.data_size_out = OPTS_GET(opts, data_size_out, 0);
97388f7fe72SSong Liu attr.test.ctx_in = ptr_to_u64(OPTS_GET(opts, ctx_in, NULL));
97488f7fe72SSong Liu attr.test.ctx_out = ptr_to_u64(OPTS_GET(opts, ctx_out, NULL));
97588f7fe72SSong Liu attr.test.data_in = ptr_to_u64(OPTS_GET(opts, data_in, NULL));
97688f7fe72SSong Liu attr.test.data_out = ptr_to_u64(OPTS_GET(opts, data_out, NULL));
97788f7fe72SSong Liu
978813847a3SAndrii Nakryiko ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, attr_sz);
979f12b6543SAndrii Nakryiko
98088f7fe72SSong Liu OPTS_SET(opts, data_size_out, attr.test.data_size_out);
98188f7fe72SSong Liu OPTS_SET(opts, ctx_size_out, attr.test.ctx_size_out);
98288f7fe72SSong Liu OPTS_SET(opts, duration, attr.test.duration);
98388f7fe72SSong Liu OPTS_SET(opts, retval, attr.test.retval);
984f12b6543SAndrii Nakryiko
985f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
98688f7fe72SSong Liu }
98788f7fe72SSong Liu
bpf_obj_get_next_id(__u32 start_id,__u32 * next_id,int cmd)988a6e130c4SQuentin Monnet static int bpf_obj_get_next_id(__u32 start_id, __u32 *next_id, int cmd)
98995b9afd3SMartin KaFai Lau {
990813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
99195b9afd3SMartin KaFai Lau union bpf_attr attr;
99295b9afd3SMartin KaFai Lau int err;
99395b9afd3SMartin KaFai Lau
994813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
99595b9afd3SMartin KaFai Lau attr.start_id = start_id;
99695b9afd3SMartin KaFai Lau
997813847a3SAndrii Nakryiko err = sys_bpf(cmd, &attr, attr_sz);
99895b9afd3SMartin KaFai Lau if (!err)
99995b9afd3SMartin KaFai Lau *next_id = attr.next_id;
100095b9afd3SMartin KaFai Lau
1001f12b6543SAndrii Nakryiko return libbpf_err_errno(err);
100295b9afd3SMartin KaFai Lau }
100395b9afd3SMartin KaFai Lau
bpf_prog_get_next_id(__u32 start_id,__u32 * next_id)1004a6e130c4SQuentin Monnet int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id)
1005a6e130c4SQuentin Monnet {
1006a6e130c4SQuentin Monnet return bpf_obj_get_next_id(start_id, next_id, BPF_PROG_GET_NEXT_ID);
1007a6e130c4SQuentin Monnet }
1008a6e130c4SQuentin Monnet
bpf_map_get_next_id(__u32 start_id,__u32 * next_id)100995b9afd3SMartin KaFai Lau int bpf_map_get_next_id(__u32 start_id, __u32 *next_id)
101095b9afd3SMartin KaFai Lau {
1011a6e130c4SQuentin Monnet return bpf_obj_get_next_id(start_id, next_id, BPF_MAP_GET_NEXT_ID);
101295b9afd3SMartin KaFai Lau }
101395b9afd3SMartin KaFai Lau
bpf_btf_get_next_id(__u32 start_id,__u32 * next_id)101409d7c2e3SQuentin Monnet int bpf_btf_get_next_id(__u32 start_id, __u32 *next_id)
101509d7c2e3SQuentin Monnet {
101609d7c2e3SQuentin Monnet return bpf_obj_get_next_id(start_id, next_id, BPF_BTF_GET_NEXT_ID);
101709d7c2e3SQuentin Monnet }
101809d7c2e3SQuentin Monnet
bpf_link_get_next_id(__u32 start_id,__u32 * next_id)10190dbc8668SAndrii Nakryiko int bpf_link_get_next_id(__u32 start_id, __u32 *next_id)
10200dbc8668SAndrii Nakryiko {
10210dbc8668SAndrii Nakryiko return bpf_obj_get_next_id(start_id, next_id, BPF_LINK_GET_NEXT_ID);
10220dbc8668SAndrii Nakryiko }
10230dbc8668SAndrii Nakryiko
bpf_prog_get_fd_by_id_opts(__u32 id,const struct bpf_get_fd_by_id_opts * opts)10248f13f168SRoberto Sassu int bpf_prog_get_fd_by_id_opts(__u32 id,
10258f13f168SRoberto Sassu const struct bpf_get_fd_by_id_opts *opts)
102695b9afd3SMartin KaFai Lau {
1027813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
102895b9afd3SMartin KaFai Lau union bpf_attr attr;
1029f12b6543SAndrii Nakryiko int fd;
103095b9afd3SMartin KaFai Lau
10318f13f168SRoberto Sassu if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
10328f13f168SRoberto Sassu return libbpf_err(-EINVAL);
10338f13f168SRoberto Sassu
1034813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
103595b9afd3SMartin KaFai Lau attr.prog_id = id;
10368f13f168SRoberto Sassu attr.open_flags = OPTS_GET(opts, open_flags, 0);
103795b9afd3SMartin KaFai Lau
1038813847a3SAndrii Nakryiko fd = sys_bpf_fd(BPF_PROG_GET_FD_BY_ID, &attr, attr_sz);
1039f12b6543SAndrii Nakryiko return libbpf_err_errno(fd);
104095b9afd3SMartin KaFai Lau }
104195b9afd3SMartin KaFai Lau
bpf_prog_get_fd_by_id(__u32 id)10428f13f168SRoberto Sassu int bpf_prog_get_fd_by_id(__u32 id)
10438f13f168SRoberto Sassu {
10448f13f168SRoberto Sassu return bpf_prog_get_fd_by_id_opts(id, NULL);
10458f13f168SRoberto Sassu }
10468f13f168SRoberto Sassu
bpf_map_get_fd_by_id_opts(__u32 id,const struct bpf_get_fd_by_id_opts * opts)1047243e3005SRoberto Sassu int bpf_map_get_fd_by_id_opts(__u32 id,
1048243e3005SRoberto Sassu const struct bpf_get_fd_by_id_opts *opts)
104995b9afd3SMartin KaFai Lau {
1050813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
105195b9afd3SMartin KaFai Lau union bpf_attr attr;
1052f12b6543SAndrii Nakryiko int fd;
105395b9afd3SMartin KaFai Lau
1054243e3005SRoberto Sassu if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
1055243e3005SRoberto Sassu return libbpf_err(-EINVAL);
1056243e3005SRoberto Sassu
1057813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
105895b9afd3SMartin KaFai Lau attr.map_id = id;
1059243e3005SRoberto Sassu attr.open_flags = OPTS_GET(opts, open_flags, 0);
106095b9afd3SMartin KaFai Lau
1061813847a3SAndrii Nakryiko fd = sys_bpf_fd(BPF_MAP_GET_FD_BY_ID, &attr, attr_sz);
1062f12b6543SAndrii Nakryiko return libbpf_err_errno(fd);
106395b9afd3SMartin KaFai Lau }
106495b9afd3SMartin KaFai Lau
bpf_map_get_fd_by_id(__u32 id)1065243e3005SRoberto Sassu int bpf_map_get_fd_by_id(__u32 id)
1066243e3005SRoberto Sassu {
1067243e3005SRoberto Sassu return bpf_map_get_fd_by_id_opts(id, NULL);
1068243e3005SRoberto Sassu }
1069243e3005SRoberto Sassu
bpf_btf_get_fd_by_id_opts(__u32 id,const struct bpf_get_fd_by_id_opts * opts)10702ce7cbf2SRoberto Sassu int bpf_btf_get_fd_by_id_opts(__u32 id,
10712ce7cbf2SRoberto Sassu const struct bpf_get_fd_by_id_opts *opts)
1072cd8b8928SMartin KaFai Lau {
1073813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
1074cd8b8928SMartin KaFai Lau union bpf_attr attr;
1075f12b6543SAndrii Nakryiko int fd;
1076cd8b8928SMartin KaFai Lau
10772ce7cbf2SRoberto Sassu if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
10782ce7cbf2SRoberto Sassu return libbpf_err(-EINVAL);
10792ce7cbf2SRoberto Sassu
1080813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
1081cd8b8928SMartin KaFai Lau attr.btf_id = id;
10822ce7cbf2SRoberto Sassu attr.open_flags = OPTS_GET(opts, open_flags, 0);
1083cd8b8928SMartin KaFai Lau
1084813847a3SAndrii Nakryiko fd = sys_bpf_fd(BPF_BTF_GET_FD_BY_ID, &attr, attr_sz);
1085f12b6543SAndrii Nakryiko return libbpf_err_errno(fd);
1086cd8b8928SMartin KaFai Lau }
1087cd8b8928SMartin KaFai Lau
bpf_btf_get_fd_by_id(__u32 id)10882ce7cbf2SRoberto Sassu int bpf_btf_get_fd_by_id(__u32 id)
10892ce7cbf2SRoberto Sassu {
10902ce7cbf2SRoberto Sassu return bpf_btf_get_fd_by_id_opts(id, NULL);
10912ce7cbf2SRoberto Sassu }
10922ce7cbf2SRoberto Sassu
bpf_link_get_fd_by_id_opts(__u32 id,const struct bpf_get_fd_by_id_opts * opts)109397c8f9ddSRoberto Sassu int bpf_link_get_fd_by_id_opts(__u32 id,
109497c8f9ddSRoberto Sassu const struct bpf_get_fd_by_id_opts *opts)
10950dbc8668SAndrii Nakryiko {
1096813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
10970dbc8668SAndrii Nakryiko union bpf_attr attr;
1098f12b6543SAndrii Nakryiko int fd;
10990dbc8668SAndrii Nakryiko
110097c8f9ddSRoberto Sassu if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
110197c8f9ddSRoberto Sassu return libbpf_err(-EINVAL);
110297c8f9ddSRoberto Sassu
1103813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
11040dbc8668SAndrii Nakryiko attr.link_id = id;
110597c8f9ddSRoberto Sassu attr.open_flags = OPTS_GET(opts, open_flags, 0);
11060dbc8668SAndrii Nakryiko
1107813847a3SAndrii Nakryiko fd = sys_bpf_fd(BPF_LINK_GET_FD_BY_ID, &attr, attr_sz);
1108f12b6543SAndrii Nakryiko return libbpf_err_errno(fd);
11090dbc8668SAndrii Nakryiko }
11100dbc8668SAndrii Nakryiko
bpf_link_get_fd_by_id(__u32 id)111197c8f9ddSRoberto Sassu int bpf_link_get_fd_by_id(__u32 id)
111297c8f9ddSRoberto Sassu {
111397c8f9ddSRoberto Sassu return bpf_link_get_fd_by_id_opts(id, NULL);
111497c8f9ddSRoberto Sassu }
111597c8f9ddSRoberto Sassu
bpf_obj_get_info_by_fd(int bpf_fd,void * info,__u32 * info_len)11160dbc8668SAndrii Nakryiko int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len)
111795b9afd3SMartin KaFai Lau {
1118813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, info);
111995b9afd3SMartin KaFai Lau union bpf_attr attr;
112095b9afd3SMartin KaFai Lau int err;
112195b9afd3SMartin KaFai Lau
1122813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
11230dbc8668SAndrii Nakryiko attr.info.bpf_fd = bpf_fd;
112495b9afd3SMartin KaFai Lau attr.info.info_len = *info_len;
112595b9afd3SMartin KaFai Lau attr.info.info = ptr_to_u64(info);
112695b9afd3SMartin KaFai Lau
1127813847a3SAndrii Nakryiko err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, attr_sz);
112895b9afd3SMartin KaFai Lau if (!err)
112995b9afd3SMartin KaFai Lau *info_len = attr.info.info_len;
1130f12b6543SAndrii Nakryiko return libbpf_err_errno(err);
113195b9afd3SMartin KaFai Lau }
1132949abbe8SEric Leblond
bpf_prog_get_info_by_fd(int prog_fd,struct bpf_prog_info * info,__u32 * info_len)113355a9ed0eSIlya Leoshkevich int bpf_prog_get_info_by_fd(int prog_fd, struct bpf_prog_info *info, __u32 *info_len)
113455a9ed0eSIlya Leoshkevich {
113555a9ed0eSIlya Leoshkevich return bpf_obj_get_info_by_fd(prog_fd, info, info_len);
113655a9ed0eSIlya Leoshkevich }
113755a9ed0eSIlya Leoshkevich
bpf_map_get_info_by_fd(int map_fd,struct bpf_map_info * info,__u32 * info_len)113855a9ed0eSIlya Leoshkevich int bpf_map_get_info_by_fd(int map_fd, struct bpf_map_info *info, __u32 *info_len)
113955a9ed0eSIlya Leoshkevich {
114055a9ed0eSIlya Leoshkevich return bpf_obj_get_info_by_fd(map_fd, info, info_len);
114155a9ed0eSIlya Leoshkevich }
114255a9ed0eSIlya Leoshkevich
bpf_btf_get_info_by_fd(int btf_fd,struct bpf_btf_info * info,__u32 * info_len)114355a9ed0eSIlya Leoshkevich int bpf_btf_get_info_by_fd(int btf_fd, struct bpf_btf_info *info, __u32 *info_len)
114455a9ed0eSIlya Leoshkevich {
114555a9ed0eSIlya Leoshkevich return bpf_obj_get_info_by_fd(btf_fd, info, info_len);
114655a9ed0eSIlya Leoshkevich }
114755a9ed0eSIlya Leoshkevich
bpf_link_get_info_by_fd(int link_fd,struct bpf_link_info * info,__u32 * info_len)114855a9ed0eSIlya Leoshkevich int bpf_link_get_info_by_fd(int link_fd, struct bpf_link_info *info, __u32 *info_len)
114955a9ed0eSIlya Leoshkevich {
115055a9ed0eSIlya Leoshkevich return bpf_obj_get_info_by_fd(link_fd, info, info_len);
115155a9ed0eSIlya Leoshkevich }
115255a9ed0eSIlya Leoshkevich
bpf_raw_tracepoint_open(const char * name,int prog_fd)1153a0fe3e57SAlexei Starovoitov int bpf_raw_tracepoint_open(const char *name, int prog_fd)
1154a0fe3e57SAlexei Starovoitov {
1155813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, raw_tracepoint);
1156a0fe3e57SAlexei Starovoitov union bpf_attr attr;
1157f12b6543SAndrii Nakryiko int fd;
1158a0fe3e57SAlexei Starovoitov
1159813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
1160a0fe3e57SAlexei Starovoitov attr.raw_tracepoint.name = ptr_to_u64(name);
1161a0fe3e57SAlexei Starovoitov attr.raw_tracepoint.prog_fd = prog_fd;
1162a0fe3e57SAlexei Starovoitov
1163813847a3SAndrii Nakryiko fd = sys_bpf_fd(BPF_RAW_TRACEPOINT_OPEN, &attr, attr_sz);
1164f12b6543SAndrii Nakryiko return libbpf_err_errno(fd);
1165a0fe3e57SAlexei Starovoitov }
1166a0fe3e57SAlexei Starovoitov
bpf_btf_load(const void * btf_data,size_t btf_size,struct bpf_btf_load_opts * opts)1167097d8002SAndrii Nakryiko int bpf_btf_load(const void *btf_data, size_t btf_size, struct bpf_btf_load_opts *opts)
11688a138aedSMartin KaFai Lau {
1169097d8002SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, btf_log_true_size);
11700ed08d67SAndrii Nakryiko union bpf_attr attr;
11710ed08d67SAndrii Nakryiko char *log_buf;
11720ed08d67SAndrii Nakryiko size_t log_size;
11730ed08d67SAndrii Nakryiko __u32 log_level;
11748a138aedSMartin KaFai Lau int fd;
11758a138aedSMartin KaFai Lau
1176e542f2c4SAndrii Nakryiko bump_rlimit_memlock();
1177e542f2c4SAndrii Nakryiko
11780ed08d67SAndrii Nakryiko memset(&attr, 0, attr_sz);
11790ed08d67SAndrii Nakryiko
11800ed08d67SAndrii Nakryiko if (!OPTS_VALID(opts, bpf_btf_load_opts))
11810ed08d67SAndrii Nakryiko return libbpf_err(-EINVAL);
11820ed08d67SAndrii Nakryiko
11830ed08d67SAndrii Nakryiko log_buf = OPTS_GET(opts, log_buf, NULL);
11840ed08d67SAndrii Nakryiko log_size = OPTS_GET(opts, log_size, 0);
11850ed08d67SAndrii Nakryiko log_level = OPTS_GET(opts, log_level, 0);
11860ed08d67SAndrii Nakryiko
11870ed08d67SAndrii Nakryiko if (log_size > UINT_MAX)
11880ed08d67SAndrii Nakryiko return libbpf_err(-EINVAL);
11890ed08d67SAndrii Nakryiko if (log_size && !log_buf)
11900ed08d67SAndrii Nakryiko return libbpf_err(-EINVAL);
11910ed08d67SAndrii Nakryiko
11920ed08d67SAndrii Nakryiko attr.btf = ptr_to_u64(btf_data);
11938a138aedSMartin KaFai Lau attr.btf_size = btf_size;
11940ed08d67SAndrii Nakryiko /* log_level == 0 and log_buf != NULL means "try loading without
11950ed08d67SAndrii Nakryiko * log_buf, but retry with log_buf and log_level=1 on error", which is
11960ed08d67SAndrii Nakryiko * consistent across low-level and high-level BTF and program loading
11970ed08d67SAndrii Nakryiko * APIs within libbpf and provides a sensible behavior in practice
11980ed08d67SAndrii Nakryiko */
11990ed08d67SAndrii Nakryiko if (log_level) {
12000ed08d67SAndrii Nakryiko attr.btf_log_buf = ptr_to_u64(log_buf);
12010ed08d67SAndrii Nakryiko attr.btf_log_size = (__u32)log_size;
12020ed08d67SAndrii Nakryiko attr.btf_log_level = log_level;
12030ed08d67SAndrii Nakryiko }
12040ed08d67SAndrii Nakryiko
12050ed08d67SAndrii Nakryiko fd = sys_bpf_fd(BPF_BTF_LOAD, &attr, attr_sz);
12060ed08d67SAndrii Nakryiko if (fd < 0 && log_buf && log_level == 0) {
12070ed08d67SAndrii Nakryiko attr.btf_log_buf = ptr_to_u64(log_buf);
12080ed08d67SAndrii Nakryiko attr.btf_log_size = (__u32)log_size;
12090ed08d67SAndrii Nakryiko attr.btf_log_level = 1;
12100ed08d67SAndrii Nakryiko fd = sys_bpf_fd(BPF_BTF_LOAD, &attr, attr_sz);
12110ed08d67SAndrii Nakryiko }
1212097d8002SAndrii Nakryiko
1213097d8002SAndrii Nakryiko OPTS_SET(opts, log_true_size, attr.btf_log_true_size);
12140ed08d67SAndrii Nakryiko return libbpf_err_errno(fd);
12150ed08d67SAndrii Nakryiko }
12160ed08d67SAndrii Nakryiko
bpf_task_fd_query(int pid,int fd,__u32 flags,char * buf,__u32 * buf_len,__u32 * prog_id,__u32 * fd_type,__u64 * probe_offset,__u64 * probe_addr)121730687ad9SYonghong Song int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len,
121830687ad9SYonghong Song __u32 *prog_id, __u32 *fd_type, __u64 *probe_offset,
121930687ad9SYonghong Song __u64 *probe_addr)
122030687ad9SYonghong Song {
1221813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, task_fd_query);
1222813847a3SAndrii Nakryiko union bpf_attr attr;
122330687ad9SYonghong Song int err;
122430687ad9SYonghong Song
1225813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
122630687ad9SYonghong Song attr.task_fd_query.pid = pid;
122730687ad9SYonghong Song attr.task_fd_query.fd = fd;
122830687ad9SYonghong Song attr.task_fd_query.flags = flags;
122930687ad9SYonghong Song attr.task_fd_query.buf = ptr_to_u64(buf);
123030687ad9SYonghong Song attr.task_fd_query.buf_len = *buf_len;
123130687ad9SYonghong Song
1232813847a3SAndrii Nakryiko err = sys_bpf(BPF_TASK_FD_QUERY, &attr, attr_sz);
1233f12b6543SAndrii Nakryiko
123430687ad9SYonghong Song *buf_len = attr.task_fd_query.buf_len;
123530687ad9SYonghong Song *prog_id = attr.task_fd_query.prog_id;
123630687ad9SYonghong Song *fd_type = attr.task_fd_query.fd_type;
123730687ad9SYonghong Song *probe_offset = attr.task_fd_query.probe_offset;
123830687ad9SYonghong Song *probe_addr = attr.task_fd_query.probe_addr;
123930687ad9SYonghong Song
1240f12b6543SAndrii Nakryiko return libbpf_err_errno(err);
124130687ad9SYonghong Song }
12420bee1067SSong Liu
bpf_enable_stats(enum bpf_stats_type type)12430bee1067SSong Liu int bpf_enable_stats(enum bpf_stats_type type)
12440bee1067SSong Liu {
1245813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, enable_stats);
12460bee1067SSong Liu union bpf_attr attr;
1247f12b6543SAndrii Nakryiko int fd;
12480bee1067SSong Liu
1249813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
12500bee1067SSong Liu attr.enable_stats.type = type;
12510bee1067SSong Liu
1252813847a3SAndrii Nakryiko fd = sys_bpf_fd(BPF_ENABLE_STATS, &attr, attr_sz);
1253f12b6543SAndrii Nakryiko return libbpf_err_errno(fd);
12540bee1067SSong Liu }
12555d23328dSYiFei Zhu
bpf_prog_bind_map(int prog_fd,int map_fd,const struct bpf_prog_bind_opts * opts)12565d23328dSYiFei Zhu int bpf_prog_bind_map(int prog_fd, int map_fd,
12575d23328dSYiFei Zhu const struct bpf_prog_bind_opts *opts)
12585d23328dSYiFei Zhu {
1259813847a3SAndrii Nakryiko const size_t attr_sz = offsetofend(union bpf_attr, prog_bind_map);
12605d23328dSYiFei Zhu union bpf_attr attr;
1261f12b6543SAndrii Nakryiko int ret;
12625d23328dSYiFei Zhu
12635d23328dSYiFei Zhu if (!OPTS_VALID(opts, bpf_prog_bind_opts))
1264f12b6543SAndrii Nakryiko return libbpf_err(-EINVAL);
12655d23328dSYiFei Zhu
1266813847a3SAndrii Nakryiko memset(&attr, 0, attr_sz);
12675d23328dSYiFei Zhu attr.prog_bind_map.prog_fd = prog_fd;
12685d23328dSYiFei Zhu attr.prog_bind_map.map_fd = map_fd;
12695d23328dSYiFei Zhu attr.prog_bind_map.flags = OPTS_GET(opts, flags, 0);
12705d23328dSYiFei Zhu
1271813847a3SAndrii Nakryiko ret = sys_bpf(BPF_PROG_BIND_MAP, &attr, attr_sz);
1272f12b6543SAndrii Nakryiko return libbpf_err_errno(ret);
12735d23328dSYiFei Zhu }
1274