xref: /openbmc/linux/tools/lib/bpf/bpf.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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