17c2aad20Sopenharmony_ci// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
27c2aad20Sopenharmony_ci
37c2aad20Sopenharmony_ci/*
47c2aad20Sopenharmony_ci * common eBPF ELF operations.
57c2aad20Sopenharmony_ci *
67c2aad20Sopenharmony_ci * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
77c2aad20Sopenharmony_ci * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
87c2aad20Sopenharmony_ci * Copyright (C) 2015 Huawei Inc.
97c2aad20Sopenharmony_ci *
107c2aad20Sopenharmony_ci * This program is free software; you can redistribute it and/or
117c2aad20Sopenharmony_ci * modify it under the terms of the GNU Lesser General Public
127c2aad20Sopenharmony_ci * License as published by the Free Software Foundation;
137c2aad20Sopenharmony_ci * version 2.1 of the License (not later!)
147c2aad20Sopenharmony_ci *
157c2aad20Sopenharmony_ci * This program is distributed in the hope that it will be useful,
167c2aad20Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
177c2aad20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
187c2aad20Sopenharmony_ci * GNU Lesser General Public License for more details.
197c2aad20Sopenharmony_ci *
207c2aad20Sopenharmony_ci * You should have received a copy of the GNU Lesser General Public
217c2aad20Sopenharmony_ci * License along with this program; if not,  see <http://www.gnu.org/licenses>
227c2aad20Sopenharmony_ci */
237c2aad20Sopenharmony_ci
247c2aad20Sopenharmony_ci#include <stdlib.h>
257c2aad20Sopenharmony_ci#include <string.h>
267c2aad20Sopenharmony_ci#include <memory.h>
277c2aad20Sopenharmony_ci#include <unistd.h>
287c2aad20Sopenharmony_ci#include <asm/unistd.h>
297c2aad20Sopenharmony_ci#include <errno.h>
307c2aad20Sopenharmony_ci#include <linux/bpf.h>
317c2aad20Sopenharmony_ci#include <linux/filter.h>
327c2aad20Sopenharmony_ci#include <linux/kernel.h>
337c2aad20Sopenharmony_ci#include <limits.h>
347c2aad20Sopenharmony_ci#include <sys/resource.h>
357c2aad20Sopenharmony_ci#include "bpf.h"
367c2aad20Sopenharmony_ci#include "libbpf.h"
377c2aad20Sopenharmony_ci#include "libbpf_internal.h"
387c2aad20Sopenharmony_ci
397c2aad20Sopenharmony_ci/*
407c2aad20Sopenharmony_ci * When building perf, unistd.h is overridden. __NR_bpf is
417c2aad20Sopenharmony_ci * required to be defined explicitly.
427c2aad20Sopenharmony_ci */
437c2aad20Sopenharmony_ci#ifndef __NR_bpf
447c2aad20Sopenharmony_ci# if defined(__i386__)
457c2aad20Sopenharmony_ci#  define __NR_bpf 357
467c2aad20Sopenharmony_ci# elif defined(__x86_64__)
477c2aad20Sopenharmony_ci#  define __NR_bpf 321
487c2aad20Sopenharmony_ci# elif defined(__aarch64__)
497c2aad20Sopenharmony_ci#  define __NR_bpf 280
507c2aad20Sopenharmony_ci# elif defined(__sparc__)
517c2aad20Sopenharmony_ci#  define __NR_bpf 349
527c2aad20Sopenharmony_ci# elif defined(__s390__)
537c2aad20Sopenharmony_ci#  define __NR_bpf 351
547c2aad20Sopenharmony_ci# elif defined(__arc__)
557c2aad20Sopenharmony_ci#  define __NR_bpf 280
567c2aad20Sopenharmony_ci# elif defined(__mips__) && defined(_ABIO32)
577c2aad20Sopenharmony_ci#  define __NR_bpf 4355
587c2aad20Sopenharmony_ci# elif defined(__mips__) && defined(_ABIN32)
597c2aad20Sopenharmony_ci#  define __NR_bpf 6319
607c2aad20Sopenharmony_ci# elif defined(__mips__) && defined(_ABI64)
617c2aad20Sopenharmony_ci#  define __NR_bpf 5315
627c2aad20Sopenharmony_ci# else
637c2aad20Sopenharmony_ci#  error __NR_bpf not defined. libbpf does not support your arch.
647c2aad20Sopenharmony_ci# endif
657c2aad20Sopenharmony_ci#endif
667c2aad20Sopenharmony_ci
677c2aad20Sopenharmony_cistatic inline __u64 ptr_to_u64(const void *ptr)
687c2aad20Sopenharmony_ci{
697c2aad20Sopenharmony_ci	return (__u64) (unsigned long) ptr;
707c2aad20Sopenharmony_ci}
717c2aad20Sopenharmony_ci
727c2aad20Sopenharmony_cistatic inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
737c2aad20Sopenharmony_ci			  unsigned int size)
747c2aad20Sopenharmony_ci{
757c2aad20Sopenharmony_ci	return syscall(__NR_bpf, cmd, attr, size);
767c2aad20Sopenharmony_ci}
777c2aad20Sopenharmony_ci
787c2aad20Sopenharmony_cistatic inline int sys_bpf_fd(enum bpf_cmd cmd, union bpf_attr *attr,
797c2aad20Sopenharmony_ci			     unsigned int size)
807c2aad20Sopenharmony_ci{
817c2aad20Sopenharmony_ci	int fd;
827c2aad20Sopenharmony_ci
837c2aad20Sopenharmony_ci	fd = sys_bpf(cmd, attr, size);
847c2aad20Sopenharmony_ci	return ensure_good_fd(fd);
857c2aad20Sopenharmony_ci}
867c2aad20Sopenharmony_ci
877c2aad20Sopenharmony_ciint sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts)
887c2aad20Sopenharmony_ci{
897c2aad20Sopenharmony_ci	int fd;
907c2aad20Sopenharmony_ci
917c2aad20Sopenharmony_ci	do {
927c2aad20Sopenharmony_ci		fd = sys_bpf_fd(BPF_PROG_LOAD, attr, size);
937c2aad20Sopenharmony_ci	} while (fd < 0 && errno == EAGAIN && --attempts > 0);
947c2aad20Sopenharmony_ci
957c2aad20Sopenharmony_ci	return fd;
967c2aad20Sopenharmony_ci}
977c2aad20Sopenharmony_ci
987c2aad20Sopenharmony_ci/* Probe whether kernel switched from memlock-based (RLIMIT_MEMLOCK) to
997c2aad20Sopenharmony_ci * memcg-based memory accounting for BPF maps and progs. This was done in [0].
1007c2aad20Sopenharmony_ci * We use the support for bpf_ktime_get_coarse_ns() helper, which was added in
1017c2aad20Sopenharmony_ci * the same 5.11 Linux release ([1]), to detect memcg-based accounting for BPF.
1027c2aad20Sopenharmony_ci *
1037c2aad20Sopenharmony_ci *   [0] https://lore.kernel.org/bpf/20201201215900.3569844-1-guro@fb.com/
1047c2aad20Sopenharmony_ci *   [1] d05512618056 ("bpf: Add bpf_ktime_get_coarse_ns helper")
1057c2aad20Sopenharmony_ci */
1067c2aad20Sopenharmony_ciint probe_memcg_account(void)
1077c2aad20Sopenharmony_ci{
1087c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, attach_btf_obj_fd);
1097c2aad20Sopenharmony_ci	struct bpf_insn insns[] = {
1107c2aad20Sopenharmony_ci		BPF_EMIT_CALL(BPF_FUNC_ktime_get_coarse_ns),
1117c2aad20Sopenharmony_ci		BPF_EXIT_INSN(),
1127c2aad20Sopenharmony_ci	};
1137c2aad20Sopenharmony_ci	size_t insn_cnt = ARRAY_SIZE(insns);
1147c2aad20Sopenharmony_ci	union bpf_attr attr;
1157c2aad20Sopenharmony_ci	int prog_fd;
1167c2aad20Sopenharmony_ci
1177c2aad20Sopenharmony_ci	/* attempt loading freplace trying to use custom BTF */
1187c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
1197c2aad20Sopenharmony_ci	attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
1207c2aad20Sopenharmony_ci	attr.insns = ptr_to_u64(insns);
1217c2aad20Sopenharmony_ci	attr.insn_cnt = insn_cnt;
1227c2aad20Sopenharmony_ci	attr.license = ptr_to_u64("GPL");
1237c2aad20Sopenharmony_ci
1247c2aad20Sopenharmony_ci	prog_fd = sys_bpf_fd(BPF_PROG_LOAD, &attr, attr_sz);
1257c2aad20Sopenharmony_ci	if (prog_fd >= 0) {
1267c2aad20Sopenharmony_ci		close(prog_fd);
1277c2aad20Sopenharmony_ci		return 1;
1287c2aad20Sopenharmony_ci	}
1297c2aad20Sopenharmony_ci	return 0;
1307c2aad20Sopenharmony_ci}
1317c2aad20Sopenharmony_ci
1327c2aad20Sopenharmony_cistatic bool memlock_bumped;
1337c2aad20Sopenharmony_cistatic rlim_t memlock_rlim = RLIM_INFINITY;
1347c2aad20Sopenharmony_ci
1357c2aad20Sopenharmony_ciint libbpf_set_memlock_rlim(size_t memlock_bytes)
1367c2aad20Sopenharmony_ci{
1377c2aad20Sopenharmony_ci	if (memlock_bumped)
1387c2aad20Sopenharmony_ci		return libbpf_err(-EBUSY);
1397c2aad20Sopenharmony_ci
1407c2aad20Sopenharmony_ci	memlock_rlim = memlock_bytes;
1417c2aad20Sopenharmony_ci	return 0;
1427c2aad20Sopenharmony_ci}
1437c2aad20Sopenharmony_ci
1447c2aad20Sopenharmony_ciint bump_rlimit_memlock(void)
1457c2aad20Sopenharmony_ci{
1467c2aad20Sopenharmony_ci	struct rlimit rlim;
1477c2aad20Sopenharmony_ci
1487c2aad20Sopenharmony_ci	/* if kernel supports memcg-based accounting, skip bumping RLIMIT_MEMLOCK */
1497c2aad20Sopenharmony_ci	if (memlock_bumped || kernel_supports(NULL, FEAT_MEMCG_ACCOUNT))
1507c2aad20Sopenharmony_ci		return 0;
1517c2aad20Sopenharmony_ci
1527c2aad20Sopenharmony_ci	memlock_bumped = true;
1537c2aad20Sopenharmony_ci
1547c2aad20Sopenharmony_ci	/* zero memlock_rlim_max disables auto-bumping RLIMIT_MEMLOCK */
1557c2aad20Sopenharmony_ci	if (memlock_rlim == 0)
1567c2aad20Sopenharmony_ci		return 0;
1577c2aad20Sopenharmony_ci
1587c2aad20Sopenharmony_ci	rlim.rlim_cur = rlim.rlim_max = memlock_rlim;
1597c2aad20Sopenharmony_ci	if (setrlimit(RLIMIT_MEMLOCK, &rlim))
1607c2aad20Sopenharmony_ci		return -errno;
1617c2aad20Sopenharmony_ci
1627c2aad20Sopenharmony_ci	return 0;
1637c2aad20Sopenharmony_ci}
1647c2aad20Sopenharmony_ci
1657c2aad20Sopenharmony_ciint bpf_map_create(enum bpf_map_type map_type,
1667c2aad20Sopenharmony_ci		   const char *map_name,
1677c2aad20Sopenharmony_ci		   __u32 key_size,
1687c2aad20Sopenharmony_ci		   __u32 value_size,
1697c2aad20Sopenharmony_ci		   __u32 max_entries,
1707c2aad20Sopenharmony_ci		   const struct bpf_map_create_opts *opts)
1717c2aad20Sopenharmony_ci{
1727c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, map_extra);
1737c2aad20Sopenharmony_ci	union bpf_attr attr;
1747c2aad20Sopenharmony_ci	int fd;
1757c2aad20Sopenharmony_ci
1767c2aad20Sopenharmony_ci	bump_rlimit_memlock();
1777c2aad20Sopenharmony_ci
1787c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
1797c2aad20Sopenharmony_ci
1807c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_map_create_opts))
1817c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
1827c2aad20Sopenharmony_ci
1837c2aad20Sopenharmony_ci	attr.map_type = map_type;
1847c2aad20Sopenharmony_ci	if (map_name && kernel_supports(NULL, FEAT_PROG_NAME))
1857c2aad20Sopenharmony_ci		libbpf_strlcpy(attr.map_name, map_name, sizeof(attr.map_name));
1867c2aad20Sopenharmony_ci	attr.key_size = key_size;
1877c2aad20Sopenharmony_ci	attr.value_size = value_size;
1887c2aad20Sopenharmony_ci	attr.max_entries = max_entries;
1897c2aad20Sopenharmony_ci
1907c2aad20Sopenharmony_ci	attr.btf_fd = OPTS_GET(opts, btf_fd, 0);
1917c2aad20Sopenharmony_ci	attr.btf_key_type_id = OPTS_GET(opts, btf_key_type_id, 0);
1927c2aad20Sopenharmony_ci	attr.btf_value_type_id = OPTS_GET(opts, btf_value_type_id, 0);
1937c2aad20Sopenharmony_ci	attr.btf_vmlinux_value_type_id = OPTS_GET(opts, btf_vmlinux_value_type_id, 0);
1947c2aad20Sopenharmony_ci
1957c2aad20Sopenharmony_ci	attr.inner_map_fd = OPTS_GET(opts, inner_map_fd, 0);
1967c2aad20Sopenharmony_ci	attr.map_flags = OPTS_GET(opts, map_flags, 0);
1977c2aad20Sopenharmony_ci	attr.map_extra = OPTS_GET(opts, map_extra, 0);
1987c2aad20Sopenharmony_ci	attr.numa_node = OPTS_GET(opts, numa_node, 0);
1997c2aad20Sopenharmony_ci	attr.map_ifindex = OPTS_GET(opts, map_ifindex, 0);
2007c2aad20Sopenharmony_ci
2017c2aad20Sopenharmony_ci	fd = sys_bpf_fd(BPF_MAP_CREATE, &attr, attr_sz);
2027c2aad20Sopenharmony_ci	return libbpf_err_errno(fd);
2037c2aad20Sopenharmony_ci}
2047c2aad20Sopenharmony_ci
2057c2aad20Sopenharmony_cistatic void *
2067c2aad20Sopenharmony_cialloc_zero_tailing_info(const void *orecord, __u32 cnt,
2077c2aad20Sopenharmony_ci			__u32 actual_rec_size, __u32 expected_rec_size)
2087c2aad20Sopenharmony_ci{
2097c2aad20Sopenharmony_ci	__u64 info_len = (__u64)actual_rec_size * cnt;
2107c2aad20Sopenharmony_ci	void *info, *nrecord;
2117c2aad20Sopenharmony_ci	int i;
2127c2aad20Sopenharmony_ci
2137c2aad20Sopenharmony_ci	info = malloc(info_len);
2147c2aad20Sopenharmony_ci	if (!info)
2157c2aad20Sopenharmony_ci		return NULL;
2167c2aad20Sopenharmony_ci
2177c2aad20Sopenharmony_ci	/* zero out bytes kernel does not understand */
2187c2aad20Sopenharmony_ci	nrecord = info;
2197c2aad20Sopenharmony_ci	for (i = 0; i < cnt; i++) {
2207c2aad20Sopenharmony_ci		memcpy(nrecord, orecord, expected_rec_size);
2217c2aad20Sopenharmony_ci		memset(nrecord + expected_rec_size, 0,
2227c2aad20Sopenharmony_ci		       actual_rec_size - expected_rec_size);
2237c2aad20Sopenharmony_ci		orecord += actual_rec_size;
2247c2aad20Sopenharmony_ci		nrecord += actual_rec_size;
2257c2aad20Sopenharmony_ci	}
2267c2aad20Sopenharmony_ci
2277c2aad20Sopenharmony_ci	return info;
2287c2aad20Sopenharmony_ci}
2297c2aad20Sopenharmony_ci
2307c2aad20Sopenharmony_ciint bpf_prog_load(enum bpf_prog_type prog_type,
2317c2aad20Sopenharmony_ci		  const char *prog_name, const char *license,
2327c2aad20Sopenharmony_ci		  const struct bpf_insn *insns, size_t insn_cnt,
2337c2aad20Sopenharmony_ci		  struct bpf_prog_load_opts *opts)
2347c2aad20Sopenharmony_ci{
2357c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, log_true_size);
2367c2aad20Sopenharmony_ci	void *finfo = NULL, *linfo = NULL;
2377c2aad20Sopenharmony_ci	const char *func_info, *line_info;
2387c2aad20Sopenharmony_ci	__u32 log_size, log_level, attach_prog_fd, attach_btf_obj_fd;
2397c2aad20Sopenharmony_ci	__u32 func_info_rec_size, line_info_rec_size;
2407c2aad20Sopenharmony_ci	int fd, attempts;
2417c2aad20Sopenharmony_ci	union bpf_attr attr;
2427c2aad20Sopenharmony_ci	char *log_buf;
2437c2aad20Sopenharmony_ci
2447c2aad20Sopenharmony_ci	bump_rlimit_memlock();
2457c2aad20Sopenharmony_ci
2467c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_prog_load_opts))
2477c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
2487c2aad20Sopenharmony_ci
2497c2aad20Sopenharmony_ci	attempts = OPTS_GET(opts, attempts, 0);
2507c2aad20Sopenharmony_ci	if (attempts < 0)
2517c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
2527c2aad20Sopenharmony_ci	if (attempts == 0)
2537c2aad20Sopenharmony_ci		attempts = PROG_LOAD_ATTEMPTS;
2547c2aad20Sopenharmony_ci
2557c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
2567c2aad20Sopenharmony_ci
2577c2aad20Sopenharmony_ci	attr.prog_type = prog_type;
2587c2aad20Sopenharmony_ci	attr.expected_attach_type = OPTS_GET(opts, expected_attach_type, 0);
2597c2aad20Sopenharmony_ci
2607c2aad20Sopenharmony_ci	attr.prog_btf_fd = OPTS_GET(opts, prog_btf_fd, 0);
2617c2aad20Sopenharmony_ci	attr.prog_flags = OPTS_GET(opts, prog_flags, 0);
2627c2aad20Sopenharmony_ci	attr.prog_ifindex = OPTS_GET(opts, prog_ifindex, 0);
2637c2aad20Sopenharmony_ci	attr.kern_version = OPTS_GET(opts, kern_version, 0);
2647c2aad20Sopenharmony_ci
2657c2aad20Sopenharmony_ci	if (prog_name && kernel_supports(NULL, FEAT_PROG_NAME))
2667c2aad20Sopenharmony_ci		libbpf_strlcpy(attr.prog_name, prog_name, sizeof(attr.prog_name));
2677c2aad20Sopenharmony_ci	attr.license = ptr_to_u64(license);
2687c2aad20Sopenharmony_ci
2697c2aad20Sopenharmony_ci	if (insn_cnt > UINT_MAX)
2707c2aad20Sopenharmony_ci		return libbpf_err(-E2BIG);
2717c2aad20Sopenharmony_ci
2727c2aad20Sopenharmony_ci	attr.insns = ptr_to_u64(insns);
2737c2aad20Sopenharmony_ci	attr.insn_cnt = (__u32)insn_cnt;
2747c2aad20Sopenharmony_ci
2757c2aad20Sopenharmony_ci	attach_prog_fd = OPTS_GET(opts, attach_prog_fd, 0);
2767c2aad20Sopenharmony_ci	attach_btf_obj_fd = OPTS_GET(opts, attach_btf_obj_fd, 0);
2777c2aad20Sopenharmony_ci
2787c2aad20Sopenharmony_ci	if (attach_prog_fd && attach_btf_obj_fd)
2797c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
2807c2aad20Sopenharmony_ci
2817c2aad20Sopenharmony_ci	attr.attach_btf_id = OPTS_GET(opts, attach_btf_id, 0);
2827c2aad20Sopenharmony_ci	if (attach_prog_fd)
2837c2aad20Sopenharmony_ci		attr.attach_prog_fd = attach_prog_fd;
2847c2aad20Sopenharmony_ci	else
2857c2aad20Sopenharmony_ci		attr.attach_btf_obj_fd = attach_btf_obj_fd;
2867c2aad20Sopenharmony_ci
2877c2aad20Sopenharmony_ci	log_buf = OPTS_GET(opts, log_buf, NULL);
2887c2aad20Sopenharmony_ci	log_size = OPTS_GET(opts, log_size, 0);
2897c2aad20Sopenharmony_ci	log_level = OPTS_GET(opts, log_level, 0);
2907c2aad20Sopenharmony_ci
2917c2aad20Sopenharmony_ci	if (!!log_buf != !!log_size)
2927c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
2937c2aad20Sopenharmony_ci
2947c2aad20Sopenharmony_ci	func_info_rec_size = OPTS_GET(opts, func_info_rec_size, 0);
2957c2aad20Sopenharmony_ci	func_info = OPTS_GET(opts, func_info, NULL);
2967c2aad20Sopenharmony_ci	attr.func_info_rec_size = func_info_rec_size;
2977c2aad20Sopenharmony_ci	attr.func_info = ptr_to_u64(func_info);
2987c2aad20Sopenharmony_ci	attr.func_info_cnt = OPTS_GET(opts, func_info_cnt, 0);
2997c2aad20Sopenharmony_ci
3007c2aad20Sopenharmony_ci	line_info_rec_size = OPTS_GET(opts, line_info_rec_size, 0);
3017c2aad20Sopenharmony_ci	line_info = OPTS_GET(opts, line_info, NULL);
3027c2aad20Sopenharmony_ci	attr.line_info_rec_size = line_info_rec_size;
3037c2aad20Sopenharmony_ci	attr.line_info = ptr_to_u64(line_info);
3047c2aad20Sopenharmony_ci	attr.line_info_cnt = OPTS_GET(opts, line_info_cnt, 0);
3057c2aad20Sopenharmony_ci
3067c2aad20Sopenharmony_ci	attr.fd_array = ptr_to_u64(OPTS_GET(opts, fd_array, NULL));
3077c2aad20Sopenharmony_ci
3087c2aad20Sopenharmony_ci	if (log_level) {
3097c2aad20Sopenharmony_ci		attr.log_buf = ptr_to_u64(log_buf);
3107c2aad20Sopenharmony_ci		attr.log_size = log_size;
3117c2aad20Sopenharmony_ci		attr.log_level = log_level;
3127c2aad20Sopenharmony_ci	}
3137c2aad20Sopenharmony_ci
3147c2aad20Sopenharmony_ci	fd = sys_bpf_prog_load(&attr, attr_sz, attempts);
3157c2aad20Sopenharmony_ci	OPTS_SET(opts, log_true_size, attr.log_true_size);
3167c2aad20Sopenharmony_ci	if (fd >= 0)
3177c2aad20Sopenharmony_ci		return fd;
3187c2aad20Sopenharmony_ci
3197c2aad20Sopenharmony_ci	/* After bpf_prog_load, the kernel may modify certain attributes
3207c2aad20Sopenharmony_ci	 * to give user space a hint how to deal with loading failure.
3217c2aad20Sopenharmony_ci	 * Check to see whether we can make some changes and load again.
3227c2aad20Sopenharmony_ci	 */
3237c2aad20Sopenharmony_ci	while (errno == E2BIG && (!finfo || !linfo)) {
3247c2aad20Sopenharmony_ci		if (!finfo && attr.func_info_cnt &&
3257c2aad20Sopenharmony_ci		    attr.func_info_rec_size < func_info_rec_size) {
3267c2aad20Sopenharmony_ci			/* try with corrected func info records */
3277c2aad20Sopenharmony_ci			finfo = alloc_zero_tailing_info(func_info,
3287c2aad20Sopenharmony_ci							attr.func_info_cnt,
3297c2aad20Sopenharmony_ci							func_info_rec_size,
3307c2aad20Sopenharmony_ci							attr.func_info_rec_size);
3317c2aad20Sopenharmony_ci			if (!finfo) {
3327c2aad20Sopenharmony_ci				errno = E2BIG;
3337c2aad20Sopenharmony_ci				goto done;
3347c2aad20Sopenharmony_ci			}
3357c2aad20Sopenharmony_ci
3367c2aad20Sopenharmony_ci			attr.func_info = ptr_to_u64(finfo);
3377c2aad20Sopenharmony_ci			attr.func_info_rec_size = func_info_rec_size;
3387c2aad20Sopenharmony_ci		} else if (!linfo && attr.line_info_cnt &&
3397c2aad20Sopenharmony_ci			   attr.line_info_rec_size < line_info_rec_size) {
3407c2aad20Sopenharmony_ci			linfo = alloc_zero_tailing_info(line_info,
3417c2aad20Sopenharmony_ci							attr.line_info_cnt,
3427c2aad20Sopenharmony_ci							line_info_rec_size,
3437c2aad20Sopenharmony_ci							attr.line_info_rec_size);
3447c2aad20Sopenharmony_ci			if (!linfo) {
3457c2aad20Sopenharmony_ci				errno = E2BIG;
3467c2aad20Sopenharmony_ci				goto done;
3477c2aad20Sopenharmony_ci			}
3487c2aad20Sopenharmony_ci
3497c2aad20Sopenharmony_ci			attr.line_info = ptr_to_u64(linfo);
3507c2aad20Sopenharmony_ci			attr.line_info_rec_size = line_info_rec_size;
3517c2aad20Sopenharmony_ci		} else {
3527c2aad20Sopenharmony_ci			break;
3537c2aad20Sopenharmony_ci		}
3547c2aad20Sopenharmony_ci
3557c2aad20Sopenharmony_ci		fd = sys_bpf_prog_load(&attr, attr_sz, attempts);
3567c2aad20Sopenharmony_ci		OPTS_SET(opts, log_true_size, attr.log_true_size);
3577c2aad20Sopenharmony_ci		if (fd >= 0)
3587c2aad20Sopenharmony_ci			goto done;
3597c2aad20Sopenharmony_ci	}
3607c2aad20Sopenharmony_ci
3617c2aad20Sopenharmony_ci	if (log_level == 0 && log_buf) {
3627c2aad20Sopenharmony_ci		/* log_level == 0 with non-NULL log_buf requires retrying on error
3637c2aad20Sopenharmony_ci		 * with log_level == 1 and log_buf/log_buf_size set, to get details of
3647c2aad20Sopenharmony_ci		 * failure
3657c2aad20Sopenharmony_ci		 */
3667c2aad20Sopenharmony_ci		attr.log_buf = ptr_to_u64(log_buf);
3677c2aad20Sopenharmony_ci		attr.log_size = log_size;
3687c2aad20Sopenharmony_ci		attr.log_level = 1;
3697c2aad20Sopenharmony_ci
3707c2aad20Sopenharmony_ci		fd = sys_bpf_prog_load(&attr, attr_sz, attempts);
3717c2aad20Sopenharmony_ci		OPTS_SET(opts, log_true_size, attr.log_true_size);
3727c2aad20Sopenharmony_ci	}
3737c2aad20Sopenharmony_cidone:
3747c2aad20Sopenharmony_ci	/* free() doesn't affect errno, so we don't need to restore it */
3757c2aad20Sopenharmony_ci	free(finfo);
3767c2aad20Sopenharmony_ci	free(linfo);
3777c2aad20Sopenharmony_ci	return libbpf_err_errno(fd);
3787c2aad20Sopenharmony_ci}
3797c2aad20Sopenharmony_ci
3807c2aad20Sopenharmony_ciint bpf_map_update_elem(int fd, const void *key, const void *value,
3817c2aad20Sopenharmony_ci			__u64 flags)
3827c2aad20Sopenharmony_ci{
3837c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, flags);
3847c2aad20Sopenharmony_ci	union bpf_attr attr;
3857c2aad20Sopenharmony_ci	int ret;
3867c2aad20Sopenharmony_ci
3877c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
3887c2aad20Sopenharmony_ci	attr.map_fd = fd;
3897c2aad20Sopenharmony_ci	attr.key = ptr_to_u64(key);
3907c2aad20Sopenharmony_ci	attr.value = ptr_to_u64(value);
3917c2aad20Sopenharmony_ci	attr.flags = flags;
3927c2aad20Sopenharmony_ci
3937c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, attr_sz);
3947c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
3957c2aad20Sopenharmony_ci}
3967c2aad20Sopenharmony_ci
3977c2aad20Sopenharmony_ciint bpf_map_lookup_elem(int fd, const void *key, void *value)
3987c2aad20Sopenharmony_ci{
3997c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, flags);
4007c2aad20Sopenharmony_ci	union bpf_attr attr;
4017c2aad20Sopenharmony_ci	int ret;
4027c2aad20Sopenharmony_ci
4037c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
4047c2aad20Sopenharmony_ci	attr.map_fd = fd;
4057c2aad20Sopenharmony_ci	attr.key = ptr_to_u64(key);
4067c2aad20Sopenharmony_ci	attr.value = ptr_to_u64(value);
4077c2aad20Sopenharmony_ci
4087c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, attr_sz);
4097c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
4107c2aad20Sopenharmony_ci}
4117c2aad20Sopenharmony_ci
4127c2aad20Sopenharmony_ciint bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags)
4137c2aad20Sopenharmony_ci{
4147c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, flags);
4157c2aad20Sopenharmony_ci	union bpf_attr attr;
4167c2aad20Sopenharmony_ci	int ret;
4177c2aad20Sopenharmony_ci
4187c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
4197c2aad20Sopenharmony_ci	attr.map_fd = fd;
4207c2aad20Sopenharmony_ci	attr.key = ptr_to_u64(key);
4217c2aad20Sopenharmony_ci	attr.value = ptr_to_u64(value);
4227c2aad20Sopenharmony_ci	attr.flags = flags;
4237c2aad20Sopenharmony_ci
4247c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, attr_sz);
4257c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
4267c2aad20Sopenharmony_ci}
4277c2aad20Sopenharmony_ci
4287c2aad20Sopenharmony_ciint bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value)
4297c2aad20Sopenharmony_ci{
4307c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, flags);
4317c2aad20Sopenharmony_ci	union bpf_attr attr;
4327c2aad20Sopenharmony_ci	int ret;
4337c2aad20Sopenharmony_ci
4347c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
4357c2aad20Sopenharmony_ci	attr.map_fd = fd;
4367c2aad20Sopenharmony_ci	attr.key = ptr_to_u64(key);
4377c2aad20Sopenharmony_ci	attr.value = ptr_to_u64(value);
4387c2aad20Sopenharmony_ci
4397c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, attr_sz);
4407c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
4417c2aad20Sopenharmony_ci}
4427c2aad20Sopenharmony_ci
4437c2aad20Sopenharmony_ciint bpf_map_lookup_and_delete_elem_flags(int fd, const void *key, void *value, __u64 flags)
4447c2aad20Sopenharmony_ci{
4457c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, flags);
4467c2aad20Sopenharmony_ci	union bpf_attr attr;
4477c2aad20Sopenharmony_ci	int ret;
4487c2aad20Sopenharmony_ci
4497c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
4507c2aad20Sopenharmony_ci	attr.map_fd = fd;
4517c2aad20Sopenharmony_ci	attr.key = ptr_to_u64(key);
4527c2aad20Sopenharmony_ci	attr.value = ptr_to_u64(value);
4537c2aad20Sopenharmony_ci	attr.flags = flags;
4547c2aad20Sopenharmony_ci
4557c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, attr_sz);
4567c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
4577c2aad20Sopenharmony_ci}
4587c2aad20Sopenharmony_ci
4597c2aad20Sopenharmony_ciint bpf_map_delete_elem(int fd, const void *key)
4607c2aad20Sopenharmony_ci{
4617c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, flags);
4627c2aad20Sopenharmony_ci	union bpf_attr attr;
4637c2aad20Sopenharmony_ci	int ret;
4647c2aad20Sopenharmony_ci
4657c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
4667c2aad20Sopenharmony_ci	attr.map_fd = fd;
4677c2aad20Sopenharmony_ci	attr.key = ptr_to_u64(key);
4687c2aad20Sopenharmony_ci
4697c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_MAP_DELETE_ELEM, &attr, attr_sz);
4707c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
4717c2aad20Sopenharmony_ci}
4727c2aad20Sopenharmony_ci
4737c2aad20Sopenharmony_ciint bpf_map_delete_elem_flags(int fd, const void *key, __u64 flags)
4747c2aad20Sopenharmony_ci{
4757c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, flags);
4767c2aad20Sopenharmony_ci	union bpf_attr attr;
4777c2aad20Sopenharmony_ci	int ret;
4787c2aad20Sopenharmony_ci
4797c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
4807c2aad20Sopenharmony_ci	attr.map_fd = fd;
4817c2aad20Sopenharmony_ci	attr.key = ptr_to_u64(key);
4827c2aad20Sopenharmony_ci	attr.flags = flags;
4837c2aad20Sopenharmony_ci
4847c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_MAP_DELETE_ELEM, &attr, attr_sz);
4857c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
4867c2aad20Sopenharmony_ci}
4877c2aad20Sopenharmony_ci
4887c2aad20Sopenharmony_ciint bpf_map_get_next_key(int fd, const void *key, void *next_key)
4897c2aad20Sopenharmony_ci{
4907c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, next_key);
4917c2aad20Sopenharmony_ci	union bpf_attr attr;
4927c2aad20Sopenharmony_ci	int ret;
4937c2aad20Sopenharmony_ci
4947c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
4957c2aad20Sopenharmony_ci	attr.map_fd = fd;
4967c2aad20Sopenharmony_ci	attr.key = ptr_to_u64(key);
4977c2aad20Sopenharmony_ci	attr.next_key = ptr_to_u64(next_key);
4987c2aad20Sopenharmony_ci
4997c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, attr_sz);
5007c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
5017c2aad20Sopenharmony_ci}
5027c2aad20Sopenharmony_ci
5037c2aad20Sopenharmony_ciint bpf_map_freeze(int fd)
5047c2aad20Sopenharmony_ci{
5057c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, map_fd);
5067c2aad20Sopenharmony_ci	union bpf_attr attr;
5077c2aad20Sopenharmony_ci	int ret;
5087c2aad20Sopenharmony_ci
5097c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
5107c2aad20Sopenharmony_ci	attr.map_fd = fd;
5117c2aad20Sopenharmony_ci
5127c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_MAP_FREEZE, &attr, attr_sz);
5137c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
5147c2aad20Sopenharmony_ci}
5157c2aad20Sopenharmony_ci
5167c2aad20Sopenharmony_cistatic int bpf_map_batch_common(int cmd, int fd, void  *in_batch,
5177c2aad20Sopenharmony_ci				void *out_batch, void *keys, void *values,
5187c2aad20Sopenharmony_ci				__u32 *count,
5197c2aad20Sopenharmony_ci				const struct bpf_map_batch_opts *opts)
5207c2aad20Sopenharmony_ci{
5217c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, batch);
5227c2aad20Sopenharmony_ci	union bpf_attr attr;
5237c2aad20Sopenharmony_ci	int ret;
5247c2aad20Sopenharmony_ci
5257c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_map_batch_opts))
5267c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
5277c2aad20Sopenharmony_ci
5287c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
5297c2aad20Sopenharmony_ci	attr.batch.map_fd = fd;
5307c2aad20Sopenharmony_ci	attr.batch.in_batch = ptr_to_u64(in_batch);
5317c2aad20Sopenharmony_ci	attr.batch.out_batch = ptr_to_u64(out_batch);
5327c2aad20Sopenharmony_ci	attr.batch.keys = ptr_to_u64(keys);
5337c2aad20Sopenharmony_ci	attr.batch.values = ptr_to_u64(values);
5347c2aad20Sopenharmony_ci	attr.batch.count = *count;
5357c2aad20Sopenharmony_ci	attr.batch.elem_flags  = OPTS_GET(opts, elem_flags, 0);
5367c2aad20Sopenharmony_ci	attr.batch.flags = OPTS_GET(opts, flags, 0);
5377c2aad20Sopenharmony_ci
5387c2aad20Sopenharmony_ci	ret = sys_bpf(cmd, &attr, attr_sz);
5397c2aad20Sopenharmony_ci	*count = attr.batch.count;
5407c2aad20Sopenharmony_ci
5417c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
5427c2aad20Sopenharmony_ci}
5437c2aad20Sopenharmony_ci
5447c2aad20Sopenharmony_ciint bpf_map_delete_batch(int fd, const void *keys, __u32 *count,
5457c2aad20Sopenharmony_ci			 const struct bpf_map_batch_opts *opts)
5467c2aad20Sopenharmony_ci{
5477c2aad20Sopenharmony_ci	return bpf_map_batch_common(BPF_MAP_DELETE_BATCH, fd, NULL,
5487c2aad20Sopenharmony_ci				    NULL, (void *)keys, NULL, count, opts);
5497c2aad20Sopenharmony_ci}
5507c2aad20Sopenharmony_ci
5517c2aad20Sopenharmony_ciint bpf_map_lookup_batch(int fd, void *in_batch, void *out_batch, void *keys,
5527c2aad20Sopenharmony_ci			 void *values, __u32 *count,
5537c2aad20Sopenharmony_ci			 const struct bpf_map_batch_opts *opts)
5547c2aad20Sopenharmony_ci{
5557c2aad20Sopenharmony_ci	return bpf_map_batch_common(BPF_MAP_LOOKUP_BATCH, fd, in_batch,
5567c2aad20Sopenharmony_ci				    out_batch, keys, values, count, opts);
5577c2aad20Sopenharmony_ci}
5587c2aad20Sopenharmony_ci
5597c2aad20Sopenharmony_ciint bpf_map_lookup_and_delete_batch(int fd, void *in_batch, void *out_batch,
5607c2aad20Sopenharmony_ci				    void *keys, void *values, __u32 *count,
5617c2aad20Sopenharmony_ci				    const struct bpf_map_batch_opts *opts)
5627c2aad20Sopenharmony_ci{
5637c2aad20Sopenharmony_ci	return bpf_map_batch_common(BPF_MAP_LOOKUP_AND_DELETE_BATCH,
5647c2aad20Sopenharmony_ci				    fd, in_batch, out_batch, keys, values,
5657c2aad20Sopenharmony_ci				    count, opts);
5667c2aad20Sopenharmony_ci}
5677c2aad20Sopenharmony_ci
5687c2aad20Sopenharmony_ciint bpf_map_update_batch(int fd, const void *keys, const void *values, __u32 *count,
5697c2aad20Sopenharmony_ci			 const struct bpf_map_batch_opts *opts)
5707c2aad20Sopenharmony_ci{
5717c2aad20Sopenharmony_ci	return bpf_map_batch_common(BPF_MAP_UPDATE_BATCH, fd, NULL, NULL,
5727c2aad20Sopenharmony_ci				    (void *)keys, (void *)values, count, opts);
5737c2aad20Sopenharmony_ci}
5747c2aad20Sopenharmony_ci
5757c2aad20Sopenharmony_ciint bpf_obj_pin_opts(int fd, const char *pathname, const struct bpf_obj_pin_opts *opts)
5767c2aad20Sopenharmony_ci{
5777c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, path_fd);
5787c2aad20Sopenharmony_ci	union bpf_attr attr;
5797c2aad20Sopenharmony_ci	int ret;
5807c2aad20Sopenharmony_ci
5817c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_obj_pin_opts))
5827c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
5837c2aad20Sopenharmony_ci
5847c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
5857c2aad20Sopenharmony_ci	attr.path_fd = OPTS_GET(opts, path_fd, 0);
5867c2aad20Sopenharmony_ci	attr.pathname = ptr_to_u64((void *)pathname);
5877c2aad20Sopenharmony_ci	attr.file_flags = OPTS_GET(opts, file_flags, 0);
5887c2aad20Sopenharmony_ci	attr.bpf_fd = fd;
5897c2aad20Sopenharmony_ci
5907c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_OBJ_PIN, &attr, attr_sz);
5917c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
5927c2aad20Sopenharmony_ci}
5937c2aad20Sopenharmony_ci
5947c2aad20Sopenharmony_ciint bpf_obj_pin(int fd, const char *pathname)
5957c2aad20Sopenharmony_ci{
5967c2aad20Sopenharmony_ci	return bpf_obj_pin_opts(fd, pathname, NULL);
5977c2aad20Sopenharmony_ci}
5987c2aad20Sopenharmony_ci
5997c2aad20Sopenharmony_ciint bpf_obj_get(const char *pathname)
6007c2aad20Sopenharmony_ci{
6017c2aad20Sopenharmony_ci	return bpf_obj_get_opts(pathname, NULL);
6027c2aad20Sopenharmony_ci}
6037c2aad20Sopenharmony_ci
6047c2aad20Sopenharmony_ciint bpf_obj_get_opts(const char *pathname, const struct bpf_obj_get_opts *opts)
6057c2aad20Sopenharmony_ci{
6067c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, path_fd);
6077c2aad20Sopenharmony_ci	union bpf_attr attr;
6087c2aad20Sopenharmony_ci	int fd;
6097c2aad20Sopenharmony_ci
6107c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_obj_get_opts))
6117c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
6127c2aad20Sopenharmony_ci
6137c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
6147c2aad20Sopenharmony_ci	attr.path_fd = OPTS_GET(opts, path_fd, 0);
6157c2aad20Sopenharmony_ci	attr.pathname = ptr_to_u64((void *)pathname);
6167c2aad20Sopenharmony_ci	attr.file_flags = OPTS_GET(opts, file_flags, 0);
6177c2aad20Sopenharmony_ci
6187c2aad20Sopenharmony_ci	fd = sys_bpf_fd(BPF_OBJ_GET, &attr, attr_sz);
6197c2aad20Sopenharmony_ci	return libbpf_err_errno(fd);
6207c2aad20Sopenharmony_ci}
6217c2aad20Sopenharmony_ci
6227c2aad20Sopenharmony_ciint bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type,
6237c2aad20Sopenharmony_ci		    unsigned int flags)
6247c2aad20Sopenharmony_ci{
6257c2aad20Sopenharmony_ci	DECLARE_LIBBPF_OPTS(bpf_prog_attach_opts, opts,
6267c2aad20Sopenharmony_ci		.flags = flags,
6277c2aad20Sopenharmony_ci	);
6287c2aad20Sopenharmony_ci
6297c2aad20Sopenharmony_ci	return bpf_prog_attach_opts(prog_fd, target_fd, type, &opts);
6307c2aad20Sopenharmony_ci}
6317c2aad20Sopenharmony_ci
6327c2aad20Sopenharmony_ciint bpf_prog_attach_opts(int prog_fd, int target, enum bpf_attach_type type,
6337c2aad20Sopenharmony_ci			 const struct bpf_prog_attach_opts *opts)
6347c2aad20Sopenharmony_ci{
6357c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, expected_revision);
6367c2aad20Sopenharmony_ci	__u32 relative_id, flags;
6377c2aad20Sopenharmony_ci	int ret, relative_fd;
6387c2aad20Sopenharmony_ci	union bpf_attr attr;
6397c2aad20Sopenharmony_ci
6407c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_prog_attach_opts))
6417c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
6427c2aad20Sopenharmony_ci
6437c2aad20Sopenharmony_ci	relative_id = OPTS_GET(opts, relative_id, 0);
6447c2aad20Sopenharmony_ci	relative_fd = OPTS_GET(opts, relative_fd, 0);
6457c2aad20Sopenharmony_ci	flags = OPTS_GET(opts, flags, 0);
6467c2aad20Sopenharmony_ci
6477c2aad20Sopenharmony_ci	/* validate we don't have unexpected combinations of non-zero fields */
6487c2aad20Sopenharmony_ci	if (relative_fd && relative_id)
6497c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
6507c2aad20Sopenharmony_ci
6517c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
6527c2aad20Sopenharmony_ci	attr.target_fd		= target;
6537c2aad20Sopenharmony_ci	attr.attach_bpf_fd	= prog_fd;
6547c2aad20Sopenharmony_ci	attr.attach_type	= type;
6557c2aad20Sopenharmony_ci	attr.replace_bpf_fd	= OPTS_GET(opts, replace_fd, 0);
6567c2aad20Sopenharmony_ci	attr.expected_revision	= OPTS_GET(opts, expected_revision, 0);
6577c2aad20Sopenharmony_ci
6587c2aad20Sopenharmony_ci	if (relative_id) {
6597c2aad20Sopenharmony_ci		attr.attach_flags = flags | BPF_F_ID;
6607c2aad20Sopenharmony_ci		attr.relative_id  = relative_id;
6617c2aad20Sopenharmony_ci	} else {
6627c2aad20Sopenharmony_ci		attr.attach_flags = flags;
6637c2aad20Sopenharmony_ci		attr.relative_fd  = relative_fd;
6647c2aad20Sopenharmony_ci	}
6657c2aad20Sopenharmony_ci
6667c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_PROG_ATTACH, &attr, attr_sz);
6677c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
6687c2aad20Sopenharmony_ci}
6697c2aad20Sopenharmony_ci
6707c2aad20Sopenharmony_ciint bpf_prog_detach_opts(int prog_fd, int target, enum bpf_attach_type type,
6717c2aad20Sopenharmony_ci			 const struct bpf_prog_detach_opts *opts)
6727c2aad20Sopenharmony_ci{
6737c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, expected_revision);
6747c2aad20Sopenharmony_ci	__u32 relative_id, flags;
6757c2aad20Sopenharmony_ci	int ret, relative_fd;
6767c2aad20Sopenharmony_ci	union bpf_attr attr;
6777c2aad20Sopenharmony_ci
6787c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_prog_detach_opts))
6797c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
6807c2aad20Sopenharmony_ci
6817c2aad20Sopenharmony_ci	relative_id = OPTS_GET(opts, relative_id, 0);
6827c2aad20Sopenharmony_ci	relative_fd = OPTS_GET(opts, relative_fd, 0);
6837c2aad20Sopenharmony_ci	flags = OPTS_GET(opts, flags, 0);
6847c2aad20Sopenharmony_ci
6857c2aad20Sopenharmony_ci	/* validate we don't have unexpected combinations of non-zero fields */
6867c2aad20Sopenharmony_ci	if (relative_fd && relative_id)
6877c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
6887c2aad20Sopenharmony_ci
6897c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
6907c2aad20Sopenharmony_ci	attr.target_fd		= target;
6917c2aad20Sopenharmony_ci	attr.attach_bpf_fd	= prog_fd;
6927c2aad20Sopenharmony_ci	attr.attach_type	= type;
6937c2aad20Sopenharmony_ci	attr.expected_revision	= OPTS_GET(opts, expected_revision, 0);
6947c2aad20Sopenharmony_ci
6957c2aad20Sopenharmony_ci	if (relative_id) {
6967c2aad20Sopenharmony_ci		attr.attach_flags = flags | BPF_F_ID;
6977c2aad20Sopenharmony_ci		attr.relative_id  = relative_id;
6987c2aad20Sopenharmony_ci	} else {
6997c2aad20Sopenharmony_ci		attr.attach_flags = flags;
7007c2aad20Sopenharmony_ci		attr.relative_fd  = relative_fd;
7017c2aad20Sopenharmony_ci	}
7027c2aad20Sopenharmony_ci
7037c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_PROG_DETACH, &attr, attr_sz);
7047c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
7057c2aad20Sopenharmony_ci}
7067c2aad20Sopenharmony_ci
7077c2aad20Sopenharmony_ciint bpf_prog_detach(int target_fd, enum bpf_attach_type type)
7087c2aad20Sopenharmony_ci{
7097c2aad20Sopenharmony_ci	return bpf_prog_detach_opts(0, target_fd, type, NULL);
7107c2aad20Sopenharmony_ci}
7117c2aad20Sopenharmony_ci
7127c2aad20Sopenharmony_ciint bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type)
7137c2aad20Sopenharmony_ci{
7147c2aad20Sopenharmony_ci	return bpf_prog_detach_opts(prog_fd, target_fd, type, NULL);
7157c2aad20Sopenharmony_ci}
7167c2aad20Sopenharmony_ci
7177c2aad20Sopenharmony_ciint bpf_link_create(int prog_fd, int target_fd,
7187c2aad20Sopenharmony_ci		    enum bpf_attach_type attach_type,
7197c2aad20Sopenharmony_ci		    const struct bpf_link_create_opts *opts)
7207c2aad20Sopenharmony_ci{
7217c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, link_create);
7227c2aad20Sopenharmony_ci	__u32 target_btf_id, iter_info_len, relative_id;
7237c2aad20Sopenharmony_ci	int fd, err, relative_fd;
7247c2aad20Sopenharmony_ci	union bpf_attr attr;
7257c2aad20Sopenharmony_ci
7267c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_link_create_opts))
7277c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
7287c2aad20Sopenharmony_ci
7297c2aad20Sopenharmony_ci	iter_info_len = OPTS_GET(opts, iter_info_len, 0);
7307c2aad20Sopenharmony_ci	target_btf_id = OPTS_GET(opts, target_btf_id, 0);
7317c2aad20Sopenharmony_ci
7327c2aad20Sopenharmony_ci	/* validate we don't have unexpected combinations of non-zero fields */
7337c2aad20Sopenharmony_ci	if (iter_info_len || target_btf_id) {
7347c2aad20Sopenharmony_ci		if (iter_info_len && target_btf_id)
7357c2aad20Sopenharmony_ci			return libbpf_err(-EINVAL);
7367c2aad20Sopenharmony_ci		if (!OPTS_ZEROED(opts, target_btf_id))
7377c2aad20Sopenharmony_ci			return libbpf_err(-EINVAL);
7387c2aad20Sopenharmony_ci	}
7397c2aad20Sopenharmony_ci
7407c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
7417c2aad20Sopenharmony_ci	attr.link_create.prog_fd = prog_fd;
7427c2aad20Sopenharmony_ci	attr.link_create.target_fd = target_fd;
7437c2aad20Sopenharmony_ci	attr.link_create.attach_type = attach_type;
7447c2aad20Sopenharmony_ci	attr.link_create.flags = OPTS_GET(opts, flags, 0);
7457c2aad20Sopenharmony_ci
7467c2aad20Sopenharmony_ci	if (target_btf_id) {
7477c2aad20Sopenharmony_ci		attr.link_create.target_btf_id = target_btf_id;
7487c2aad20Sopenharmony_ci		goto proceed;
7497c2aad20Sopenharmony_ci	}
7507c2aad20Sopenharmony_ci
7517c2aad20Sopenharmony_ci	switch (attach_type) {
7527c2aad20Sopenharmony_ci	case BPF_TRACE_ITER:
7537c2aad20Sopenharmony_ci		attr.link_create.iter_info = ptr_to_u64(OPTS_GET(opts, iter_info, (void *)0));
7547c2aad20Sopenharmony_ci		attr.link_create.iter_info_len = iter_info_len;
7557c2aad20Sopenharmony_ci		break;
7567c2aad20Sopenharmony_ci	case BPF_PERF_EVENT:
7577c2aad20Sopenharmony_ci		attr.link_create.perf_event.bpf_cookie = OPTS_GET(opts, perf_event.bpf_cookie, 0);
7587c2aad20Sopenharmony_ci		if (!OPTS_ZEROED(opts, perf_event))
7597c2aad20Sopenharmony_ci			return libbpf_err(-EINVAL);
7607c2aad20Sopenharmony_ci		break;
7617c2aad20Sopenharmony_ci	case BPF_TRACE_KPROBE_MULTI:
7627c2aad20Sopenharmony_ci		attr.link_create.kprobe_multi.flags = OPTS_GET(opts, kprobe_multi.flags, 0);
7637c2aad20Sopenharmony_ci		attr.link_create.kprobe_multi.cnt = OPTS_GET(opts, kprobe_multi.cnt, 0);
7647c2aad20Sopenharmony_ci		attr.link_create.kprobe_multi.syms = ptr_to_u64(OPTS_GET(opts, kprobe_multi.syms, 0));
7657c2aad20Sopenharmony_ci		attr.link_create.kprobe_multi.addrs = ptr_to_u64(OPTS_GET(opts, kprobe_multi.addrs, 0));
7667c2aad20Sopenharmony_ci		attr.link_create.kprobe_multi.cookies = ptr_to_u64(OPTS_GET(opts, kprobe_multi.cookies, 0));
7677c2aad20Sopenharmony_ci		if (!OPTS_ZEROED(opts, kprobe_multi))
7687c2aad20Sopenharmony_ci			return libbpf_err(-EINVAL);
7697c2aad20Sopenharmony_ci		break;
7707c2aad20Sopenharmony_ci	case BPF_TRACE_UPROBE_MULTI:
7717c2aad20Sopenharmony_ci		attr.link_create.uprobe_multi.flags = OPTS_GET(opts, uprobe_multi.flags, 0);
7727c2aad20Sopenharmony_ci		attr.link_create.uprobe_multi.cnt = OPTS_GET(opts, uprobe_multi.cnt, 0);
7737c2aad20Sopenharmony_ci		attr.link_create.uprobe_multi.path = ptr_to_u64(OPTS_GET(opts, uprobe_multi.path, 0));
7747c2aad20Sopenharmony_ci		attr.link_create.uprobe_multi.offsets = ptr_to_u64(OPTS_GET(opts, uprobe_multi.offsets, 0));
7757c2aad20Sopenharmony_ci		attr.link_create.uprobe_multi.ref_ctr_offsets = ptr_to_u64(OPTS_GET(opts, uprobe_multi.ref_ctr_offsets, 0));
7767c2aad20Sopenharmony_ci		attr.link_create.uprobe_multi.cookies = ptr_to_u64(OPTS_GET(opts, uprobe_multi.cookies, 0));
7777c2aad20Sopenharmony_ci		attr.link_create.uprobe_multi.pid = OPTS_GET(opts, uprobe_multi.pid, 0);
7787c2aad20Sopenharmony_ci		if (!OPTS_ZEROED(opts, uprobe_multi))
7797c2aad20Sopenharmony_ci			return libbpf_err(-EINVAL);
7807c2aad20Sopenharmony_ci		break;
7817c2aad20Sopenharmony_ci	case BPF_TRACE_FENTRY:
7827c2aad20Sopenharmony_ci	case BPF_TRACE_FEXIT:
7837c2aad20Sopenharmony_ci	case BPF_MODIFY_RETURN:
7847c2aad20Sopenharmony_ci	case BPF_LSM_MAC:
7857c2aad20Sopenharmony_ci		attr.link_create.tracing.cookie = OPTS_GET(opts, tracing.cookie, 0);
7867c2aad20Sopenharmony_ci		if (!OPTS_ZEROED(opts, tracing))
7877c2aad20Sopenharmony_ci			return libbpf_err(-EINVAL);
7887c2aad20Sopenharmony_ci		break;
7897c2aad20Sopenharmony_ci	case BPF_NETFILTER:
7907c2aad20Sopenharmony_ci		attr.link_create.netfilter.pf = OPTS_GET(opts, netfilter.pf, 0);
7917c2aad20Sopenharmony_ci		attr.link_create.netfilter.hooknum = OPTS_GET(opts, netfilter.hooknum, 0);
7927c2aad20Sopenharmony_ci		attr.link_create.netfilter.priority = OPTS_GET(opts, netfilter.priority, 0);
7937c2aad20Sopenharmony_ci		attr.link_create.netfilter.flags = OPTS_GET(opts, netfilter.flags, 0);
7947c2aad20Sopenharmony_ci		if (!OPTS_ZEROED(opts, netfilter))
7957c2aad20Sopenharmony_ci			return libbpf_err(-EINVAL);
7967c2aad20Sopenharmony_ci		break;
7977c2aad20Sopenharmony_ci	case BPF_TCX_INGRESS:
7987c2aad20Sopenharmony_ci	case BPF_TCX_EGRESS:
7997c2aad20Sopenharmony_ci		relative_fd = OPTS_GET(opts, tcx.relative_fd, 0);
8007c2aad20Sopenharmony_ci		relative_id = OPTS_GET(opts, tcx.relative_id, 0);
8017c2aad20Sopenharmony_ci		if (relative_fd && relative_id)
8027c2aad20Sopenharmony_ci			return libbpf_err(-EINVAL);
8037c2aad20Sopenharmony_ci		if (relative_id) {
8047c2aad20Sopenharmony_ci			attr.link_create.tcx.relative_id = relative_id;
8057c2aad20Sopenharmony_ci			attr.link_create.flags |= BPF_F_ID;
8067c2aad20Sopenharmony_ci		} else {
8077c2aad20Sopenharmony_ci			attr.link_create.tcx.relative_fd = relative_fd;
8087c2aad20Sopenharmony_ci		}
8097c2aad20Sopenharmony_ci		attr.link_create.tcx.expected_revision = OPTS_GET(opts, tcx.expected_revision, 0);
8107c2aad20Sopenharmony_ci		if (!OPTS_ZEROED(opts, tcx))
8117c2aad20Sopenharmony_ci			return libbpf_err(-EINVAL);
8127c2aad20Sopenharmony_ci		break;
8137c2aad20Sopenharmony_ci	case BPF_NETKIT_PRIMARY:
8147c2aad20Sopenharmony_ci	case BPF_NETKIT_PEER:
8157c2aad20Sopenharmony_ci		relative_fd = OPTS_GET(opts, netkit.relative_fd, 0);
8167c2aad20Sopenharmony_ci		relative_id = OPTS_GET(opts, netkit.relative_id, 0);
8177c2aad20Sopenharmony_ci		if (relative_fd && relative_id)
8187c2aad20Sopenharmony_ci			return libbpf_err(-EINVAL);
8197c2aad20Sopenharmony_ci		if (relative_id) {
8207c2aad20Sopenharmony_ci			attr.link_create.netkit.relative_id = relative_id;
8217c2aad20Sopenharmony_ci			attr.link_create.flags |= BPF_F_ID;
8227c2aad20Sopenharmony_ci		} else {
8237c2aad20Sopenharmony_ci			attr.link_create.netkit.relative_fd = relative_fd;
8247c2aad20Sopenharmony_ci		}
8257c2aad20Sopenharmony_ci		attr.link_create.netkit.expected_revision = OPTS_GET(opts, netkit.expected_revision, 0);
8267c2aad20Sopenharmony_ci		if (!OPTS_ZEROED(opts, netkit))
8277c2aad20Sopenharmony_ci			return libbpf_err(-EINVAL);
8287c2aad20Sopenharmony_ci		break;
8297c2aad20Sopenharmony_ci	default:
8307c2aad20Sopenharmony_ci		if (!OPTS_ZEROED(opts, flags))
8317c2aad20Sopenharmony_ci			return libbpf_err(-EINVAL);
8327c2aad20Sopenharmony_ci		break;
8337c2aad20Sopenharmony_ci	}
8347c2aad20Sopenharmony_ciproceed:
8357c2aad20Sopenharmony_ci	fd = sys_bpf_fd(BPF_LINK_CREATE, &attr, attr_sz);
8367c2aad20Sopenharmony_ci	if (fd >= 0)
8377c2aad20Sopenharmony_ci		return fd;
8387c2aad20Sopenharmony_ci	/* we'll get EINVAL if LINK_CREATE doesn't support attaching fentry
8397c2aad20Sopenharmony_ci	 * and other similar programs
8407c2aad20Sopenharmony_ci	 */
8417c2aad20Sopenharmony_ci	err = -errno;
8427c2aad20Sopenharmony_ci	if (err != -EINVAL)
8437c2aad20Sopenharmony_ci		return libbpf_err(err);
8447c2aad20Sopenharmony_ci
8457c2aad20Sopenharmony_ci	/* if user used features not supported by
8467c2aad20Sopenharmony_ci	 * BPF_RAW_TRACEPOINT_OPEN command, then just give up immediately
8477c2aad20Sopenharmony_ci	 */
8487c2aad20Sopenharmony_ci	if (attr.link_create.target_fd || attr.link_create.target_btf_id)
8497c2aad20Sopenharmony_ci		return libbpf_err(err);
8507c2aad20Sopenharmony_ci	if (!OPTS_ZEROED(opts, sz))
8517c2aad20Sopenharmony_ci		return libbpf_err(err);
8527c2aad20Sopenharmony_ci
8537c2aad20Sopenharmony_ci	/* otherwise, for few select kinds of programs that can be
8547c2aad20Sopenharmony_ci	 * attached using BPF_RAW_TRACEPOINT_OPEN command, try that as
8557c2aad20Sopenharmony_ci	 * a fallback for older kernels
8567c2aad20Sopenharmony_ci	 */
8577c2aad20Sopenharmony_ci	switch (attach_type) {
8587c2aad20Sopenharmony_ci	case BPF_TRACE_RAW_TP:
8597c2aad20Sopenharmony_ci	case BPF_LSM_MAC:
8607c2aad20Sopenharmony_ci	case BPF_TRACE_FENTRY:
8617c2aad20Sopenharmony_ci	case BPF_TRACE_FEXIT:
8627c2aad20Sopenharmony_ci	case BPF_MODIFY_RETURN:
8637c2aad20Sopenharmony_ci		return bpf_raw_tracepoint_open(NULL, prog_fd);
8647c2aad20Sopenharmony_ci	default:
8657c2aad20Sopenharmony_ci		return libbpf_err(err);
8667c2aad20Sopenharmony_ci	}
8677c2aad20Sopenharmony_ci}
8687c2aad20Sopenharmony_ci
8697c2aad20Sopenharmony_ciint bpf_link_detach(int link_fd)
8707c2aad20Sopenharmony_ci{
8717c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, link_detach);
8727c2aad20Sopenharmony_ci	union bpf_attr attr;
8737c2aad20Sopenharmony_ci	int ret;
8747c2aad20Sopenharmony_ci
8757c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
8767c2aad20Sopenharmony_ci	attr.link_detach.link_fd = link_fd;
8777c2aad20Sopenharmony_ci
8787c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_LINK_DETACH, &attr, attr_sz);
8797c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
8807c2aad20Sopenharmony_ci}
8817c2aad20Sopenharmony_ci
8827c2aad20Sopenharmony_ciint bpf_link_update(int link_fd, int new_prog_fd,
8837c2aad20Sopenharmony_ci		    const struct bpf_link_update_opts *opts)
8847c2aad20Sopenharmony_ci{
8857c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, link_update);
8867c2aad20Sopenharmony_ci	union bpf_attr attr;
8877c2aad20Sopenharmony_ci	int ret;
8887c2aad20Sopenharmony_ci
8897c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_link_update_opts))
8907c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
8917c2aad20Sopenharmony_ci
8927c2aad20Sopenharmony_ci	if (OPTS_GET(opts, old_prog_fd, 0) && OPTS_GET(opts, old_map_fd, 0))
8937c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
8947c2aad20Sopenharmony_ci
8957c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
8967c2aad20Sopenharmony_ci	attr.link_update.link_fd = link_fd;
8977c2aad20Sopenharmony_ci	attr.link_update.new_prog_fd = new_prog_fd;
8987c2aad20Sopenharmony_ci	attr.link_update.flags = OPTS_GET(opts, flags, 0);
8997c2aad20Sopenharmony_ci	if (OPTS_GET(opts, old_prog_fd, 0))
9007c2aad20Sopenharmony_ci		attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0);
9017c2aad20Sopenharmony_ci	else if (OPTS_GET(opts, old_map_fd, 0))
9027c2aad20Sopenharmony_ci		attr.link_update.old_map_fd = OPTS_GET(opts, old_map_fd, 0);
9037c2aad20Sopenharmony_ci
9047c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_LINK_UPDATE, &attr, attr_sz);
9057c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
9067c2aad20Sopenharmony_ci}
9077c2aad20Sopenharmony_ci
9087c2aad20Sopenharmony_ciint bpf_iter_create(int link_fd)
9097c2aad20Sopenharmony_ci{
9107c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, iter_create);
9117c2aad20Sopenharmony_ci	union bpf_attr attr;
9127c2aad20Sopenharmony_ci	int fd;
9137c2aad20Sopenharmony_ci
9147c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
9157c2aad20Sopenharmony_ci	attr.iter_create.link_fd = link_fd;
9167c2aad20Sopenharmony_ci
9177c2aad20Sopenharmony_ci	fd = sys_bpf_fd(BPF_ITER_CREATE, &attr, attr_sz);
9187c2aad20Sopenharmony_ci	return libbpf_err_errno(fd);
9197c2aad20Sopenharmony_ci}
9207c2aad20Sopenharmony_ci
9217c2aad20Sopenharmony_ciint bpf_prog_query_opts(int target, enum bpf_attach_type type,
9227c2aad20Sopenharmony_ci			struct bpf_prog_query_opts *opts)
9237c2aad20Sopenharmony_ci{
9247c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, query);
9257c2aad20Sopenharmony_ci	union bpf_attr attr;
9267c2aad20Sopenharmony_ci	int ret;
9277c2aad20Sopenharmony_ci
9287c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_prog_query_opts))
9297c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
9307c2aad20Sopenharmony_ci
9317c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
9327c2aad20Sopenharmony_ci	attr.query.target_fd		= target;
9337c2aad20Sopenharmony_ci	attr.query.attach_type		= type;
9347c2aad20Sopenharmony_ci	attr.query.query_flags		= OPTS_GET(opts, query_flags, 0);
9357c2aad20Sopenharmony_ci	attr.query.count		= OPTS_GET(opts, count, 0);
9367c2aad20Sopenharmony_ci	attr.query.prog_ids		= ptr_to_u64(OPTS_GET(opts, prog_ids, NULL));
9377c2aad20Sopenharmony_ci	attr.query.link_ids		= ptr_to_u64(OPTS_GET(opts, link_ids, NULL));
9387c2aad20Sopenharmony_ci	attr.query.prog_attach_flags	= ptr_to_u64(OPTS_GET(opts, prog_attach_flags, NULL));
9397c2aad20Sopenharmony_ci	attr.query.link_attach_flags	= ptr_to_u64(OPTS_GET(opts, link_attach_flags, NULL));
9407c2aad20Sopenharmony_ci
9417c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_PROG_QUERY, &attr, attr_sz);
9427c2aad20Sopenharmony_ci
9437c2aad20Sopenharmony_ci	OPTS_SET(opts, attach_flags, attr.query.attach_flags);
9447c2aad20Sopenharmony_ci	OPTS_SET(opts, revision, attr.query.revision);
9457c2aad20Sopenharmony_ci	OPTS_SET(opts, count, attr.query.count);
9467c2aad20Sopenharmony_ci
9477c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
9487c2aad20Sopenharmony_ci}
9497c2aad20Sopenharmony_ci
9507c2aad20Sopenharmony_ciint bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
9517c2aad20Sopenharmony_ci		   __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt)
9527c2aad20Sopenharmony_ci{
9537c2aad20Sopenharmony_ci	LIBBPF_OPTS(bpf_prog_query_opts, opts);
9547c2aad20Sopenharmony_ci	int ret;
9557c2aad20Sopenharmony_ci
9567c2aad20Sopenharmony_ci	opts.query_flags = query_flags;
9577c2aad20Sopenharmony_ci	opts.prog_ids = prog_ids;
9587c2aad20Sopenharmony_ci	opts.prog_cnt = *prog_cnt;
9597c2aad20Sopenharmony_ci
9607c2aad20Sopenharmony_ci	ret = bpf_prog_query_opts(target_fd, type, &opts);
9617c2aad20Sopenharmony_ci
9627c2aad20Sopenharmony_ci	if (attach_flags)
9637c2aad20Sopenharmony_ci		*attach_flags = opts.attach_flags;
9647c2aad20Sopenharmony_ci	*prog_cnt = opts.prog_cnt;
9657c2aad20Sopenharmony_ci
9667c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
9677c2aad20Sopenharmony_ci}
9687c2aad20Sopenharmony_ci
9697c2aad20Sopenharmony_ciint bpf_prog_test_run_opts(int prog_fd, struct bpf_test_run_opts *opts)
9707c2aad20Sopenharmony_ci{
9717c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, test);
9727c2aad20Sopenharmony_ci	union bpf_attr attr;
9737c2aad20Sopenharmony_ci	int ret;
9747c2aad20Sopenharmony_ci
9757c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_test_run_opts))
9767c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
9777c2aad20Sopenharmony_ci
9787c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
9797c2aad20Sopenharmony_ci	attr.test.prog_fd = prog_fd;
9807c2aad20Sopenharmony_ci	attr.test.batch_size = OPTS_GET(opts, batch_size, 0);
9817c2aad20Sopenharmony_ci	attr.test.cpu = OPTS_GET(opts, cpu, 0);
9827c2aad20Sopenharmony_ci	attr.test.flags = OPTS_GET(opts, flags, 0);
9837c2aad20Sopenharmony_ci	attr.test.repeat = OPTS_GET(opts, repeat, 0);
9847c2aad20Sopenharmony_ci	attr.test.duration = OPTS_GET(opts, duration, 0);
9857c2aad20Sopenharmony_ci	attr.test.ctx_size_in = OPTS_GET(opts, ctx_size_in, 0);
9867c2aad20Sopenharmony_ci	attr.test.ctx_size_out = OPTS_GET(opts, ctx_size_out, 0);
9877c2aad20Sopenharmony_ci	attr.test.data_size_in = OPTS_GET(opts, data_size_in, 0);
9887c2aad20Sopenharmony_ci	attr.test.data_size_out = OPTS_GET(opts, data_size_out, 0);
9897c2aad20Sopenharmony_ci	attr.test.ctx_in = ptr_to_u64(OPTS_GET(opts, ctx_in, NULL));
9907c2aad20Sopenharmony_ci	attr.test.ctx_out = ptr_to_u64(OPTS_GET(opts, ctx_out, NULL));
9917c2aad20Sopenharmony_ci	attr.test.data_in = ptr_to_u64(OPTS_GET(opts, data_in, NULL));
9927c2aad20Sopenharmony_ci	attr.test.data_out = ptr_to_u64(OPTS_GET(opts, data_out, NULL));
9937c2aad20Sopenharmony_ci
9947c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, attr_sz);
9957c2aad20Sopenharmony_ci
9967c2aad20Sopenharmony_ci	OPTS_SET(opts, data_size_out, attr.test.data_size_out);
9977c2aad20Sopenharmony_ci	OPTS_SET(opts, ctx_size_out, attr.test.ctx_size_out);
9987c2aad20Sopenharmony_ci	OPTS_SET(opts, duration, attr.test.duration);
9997c2aad20Sopenharmony_ci	OPTS_SET(opts, retval, attr.test.retval);
10007c2aad20Sopenharmony_ci
10017c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
10027c2aad20Sopenharmony_ci}
10037c2aad20Sopenharmony_ci
10047c2aad20Sopenharmony_cistatic int bpf_obj_get_next_id(__u32 start_id, __u32 *next_id, int cmd)
10057c2aad20Sopenharmony_ci{
10067c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
10077c2aad20Sopenharmony_ci	union bpf_attr attr;
10087c2aad20Sopenharmony_ci	int err;
10097c2aad20Sopenharmony_ci
10107c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
10117c2aad20Sopenharmony_ci	attr.start_id = start_id;
10127c2aad20Sopenharmony_ci
10137c2aad20Sopenharmony_ci	err = sys_bpf(cmd, &attr, attr_sz);
10147c2aad20Sopenharmony_ci	if (!err)
10157c2aad20Sopenharmony_ci		*next_id = attr.next_id;
10167c2aad20Sopenharmony_ci
10177c2aad20Sopenharmony_ci	return libbpf_err_errno(err);
10187c2aad20Sopenharmony_ci}
10197c2aad20Sopenharmony_ci
10207c2aad20Sopenharmony_ciint bpf_prog_get_next_id(__u32 start_id, __u32 *next_id)
10217c2aad20Sopenharmony_ci{
10227c2aad20Sopenharmony_ci	return bpf_obj_get_next_id(start_id, next_id, BPF_PROG_GET_NEXT_ID);
10237c2aad20Sopenharmony_ci}
10247c2aad20Sopenharmony_ci
10257c2aad20Sopenharmony_ciint bpf_map_get_next_id(__u32 start_id, __u32 *next_id)
10267c2aad20Sopenharmony_ci{
10277c2aad20Sopenharmony_ci	return bpf_obj_get_next_id(start_id, next_id, BPF_MAP_GET_NEXT_ID);
10287c2aad20Sopenharmony_ci}
10297c2aad20Sopenharmony_ci
10307c2aad20Sopenharmony_ciint bpf_btf_get_next_id(__u32 start_id, __u32 *next_id)
10317c2aad20Sopenharmony_ci{
10327c2aad20Sopenharmony_ci	return bpf_obj_get_next_id(start_id, next_id, BPF_BTF_GET_NEXT_ID);
10337c2aad20Sopenharmony_ci}
10347c2aad20Sopenharmony_ci
10357c2aad20Sopenharmony_ciint bpf_link_get_next_id(__u32 start_id, __u32 *next_id)
10367c2aad20Sopenharmony_ci{
10377c2aad20Sopenharmony_ci	return bpf_obj_get_next_id(start_id, next_id, BPF_LINK_GET_NEXT_ID);
10387c2aad20Sopenharmony_ci}
10397c2aad20Sopenharmony_ci
10407c2aad20Sopenharmony_ciint bpf_prog_get_fd_by_id_opts(__u32 id,
10417c2aad20Sopenharmony_ci			       const struct bpf_get_fd_by_id_opts *opts)
10427c2aad20Sopenharmony_ci{
10437c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
10447c2aad20Sopenharmony_ci	union bpf_attr attr;
10457c2aad20Sopenharmony_ci	int fd;
10467c2aad20Sopenharmony_ci
10477c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
10487c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
10497c2aad20Sopenharmony_ci
10507c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
10517c2aad20Sopenharmony_ci	attr.prog_id = id;
10527c2aad20Sopenharmony_ci	attr.open_flags = OPTS_GET(opts, open_flags, 0);
10537c2aad20Sopenharmony_ci
10547c2aad20Sopenharmony_ci	fd = sys_bpf_fd(BPF_PROG_GET_FD_BY_ID, &attr, attr_sz);
10557c2aad20Sopenharmony_ci	return libbpf_err_errno(fd);
10567c2aad20Sopenharmony_ci}
10577c2aad20Sopenharmony_ci
10587c2aad20Sopenharmony_ciint bpf_prog_get_fd_by_id(__u32 id)
10597c2aad20Sopenharmony_ci{
10607c2aad20Sopenharmony_ci	return bpf_prog_get_fd_by_id_opts(id, NULL);
10617c2aad20Sopenharmony_ci}
10627c2aad20Sopenharmony_ci
10637c2aad20Sopenharmony_ciint bpf_map_get_fd_by_id_opts(__u32 id,
10647c2aad20Sopenharmony_ci			      const struct bpf_get_fd_by_id_opts *opts)
10657c2aad20Sopenharmony_ci{
10667c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
10677c2aad20Sopenharmony_ci	union bpf_attr attr;
10687c2aad20Sopenharmony_ci	int fd;
10697c2aad20Sopenharmony_ci
10707c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
10717c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
10727c2aad20Sopenharmony_ci
10737c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
10747c2aad20Sopenharmony_ci	attr.map_id = id;
10757c2aad20Sopenharmony_ci	attr.open_flags = OPTS_GET(opts, open_flags, 0);
10767c2aad20Sopenharmony_ci
10777c2aad20Sopenharmony_ci	fd = sys_bpf_fd(BPF_MAP_GET_FD_BY_ID, &attr, attr_sz);
10787c2aad20Sopenharmony_ci	return libbpf_err_errno(fd);
10797c2aad20Sopenharmony_ci}
10807c2aad20Sopenharmony_ci
10817c2aad20Sopenharmony_ciint bpf_map_get_fd_by_id(__u32 id)
10827c2aad20Sopenharmony_ci{
10837c2aad20Sopenharmony_ci	return bpf_map_get_fd_by_id_opts(id, NULL);
10847c2aad20Sopenharmony_ci}
10857c2aad20Sopenharmony_ci
10867c2aad20Sopenharmony_ciint bpf_btf_get_fd_by_id_opts(__u32 id,
10877c2aad20Sopenharmony_ci			      const struct bpf_get_fd_by_id_opts *opts)
10887c2aad20Sopenharmony_ci{
10897c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
10907c2aad20Sopenharmony_ci	union bpf_attr attr;
10917c2aad20Sopenharmony_ci	int fd;
10927c2aad20Sopenharmony_ci
10937c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
10947c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
10957c2aad20Sopenharmony_ci
10967c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
10977c2aad20Sopenharmony_ci	attr.btf_id = id;
10987c2aad20Sopenharmony_ci	attr.open_flags = OPTS_GET(opts, open_flags, 0);
10997c2aad20Sopenharmony_ci
11007c2aad20Sopenharmony_ci	fd = sys_bpf_fd(BPF_BTF_GET_FD_BY_ID, &attr, attr_sz);
11017c2aad20Sopenharmony_ci	return libbpf_err_errno(fd);
11027c2aad20Sopenharmony_ci}
11037c2aad20Sopenharmony_ci
11047c2aad20Sopenharmony_ciint bpf_btf_get_fd_by_id(__u32 id)
11057c2aad20Sopenharmony_ci{
11067c2aad20Sopenharmony_ci	return bpf_btf_get_fd_by_id_opts(id, NULL);
11077c2aad20Sopenharmony_ci}
11087c2aad20Sopenharmony_ci
11097c2aad20Sopenharmony_ciint bpf_link_get_fd_by_id_opts(__u32 id,
11107c2aad20Sopenharmony_ci			       const struct bpf_get_fd_by_id_opts *opts)
11117c2aad20Sopenharmony_ci{
11127c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
11137c2aad20Sopenharmony_ci	union bpf_attr attr;
11147c2aad20Sopenharmony_ci	int fd;
11157c2aad20Sopenharmony_ci
11167c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
11177c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
11187c2aad20Sopenharmony_ci
11197c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
11207c2aad20Sopenharmony_ci	attr.link_id = id;
11217c2aad20Sopenharmony_ci	attr.open_flags = OPTS_GET(opts, open_flags, 0);
11227c2aad20Sopenharmony_ci
11237c2aad20Sopenharmony_ci	fd = sys_bpf_fd(BPF_LINK_GET_FD_BY_ID, &attr, attr_sz);
11247c2aad20Sopenharmony_ci	return libbpf_err_errno(fd);
11257c2aad20Sopenharmony_ci}
11267c2aad20Sopenharmony_ci
11277c2aad20Sopenharmony_ciint bpf_link_get_fd_by_id(__u32 id)
11287c2aad20Sopenharmony_ci{
11297c2aad20Sopenharmony_ci	return bpf_link_get_fd_by_id_opts(id, NULL);
11307c2aad20Sopenharmony_ci}
11317c2aad20Sopenharmony_ci
11327c2aad20Sopenharmony_ciint bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len)
11337c2aad20Sopenharmony_ci{
11347c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, info);
11357c2aad20Sopenharmony_ci	union bpf_attr attr;
11367c2aad20Sopenharmony_ci	int err;
11377c2aad20Sopenharmony_ci
11387c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
11397c2aad20Sopenharmony_ci	attr.info.bpf_fd = bpf_fd;
11407c2aad20Sopenharmony_ci	attr.info.info_len = *info_len;
11417c2aad20Sopenharmony_ci	attr.info.info = ptr_to_u64(info);
11427c2aad20Sopenharmony_ci
11437c2aad20Sopenharmony_ci	err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, attr_sz);
11447c2aad20Sopenharmony_ci	if (!err)
11457c2aad20Sopenharmony_ci		*info_len = attr.info.info_len;
11467c2aad20Sopenharmony_ci	return libbpf_err_errno(err);
11477c2aad20Sopenharmony_ci}
11487c2aad20Sopenharmony_ci
11497c2aad20Sopenharmony_ciint bpf_prog_get_info_by_fd(int prog_fd, struct bpf_prog_info *info, __u32 *info_len)
11507c2aad20Sopenharmony_ci{
11517c2aad20Sopenharmony_ci	return bpf_obj_get_info_by_fd(prog_fd, info, info_len);
11527c2aad20Sopenharmony_ci}
11537c2aad20Sopenharmony_ci
11547c2aad20Sopenharmony_ciint bpf_map_get_info_by_fd(int map_fd, struct bpf_map_info *info, __u32 *info_len)
11557c2aad20Sopenharmony_ci{
11567c2aad20Sopenharmony_ci	return bpf_obj_get_info_by_fd(map_fd, info, info_len);
11577c2aad20Sopenharmony_ci}
11587c2aad20Sopenharmony_ci
11597c2aad20Sopenharmony_ciint bpf_btf_get_info_by_fd(int btf_fd, struct bpf_btf_info *info, __u32 *info_len)
11607c2aad20Sopenharmony_ci{
11617c2aad20Sopenharmony_ci	return bpf_obj_get_info_by_fd(btf_fd, info, info_len);
11627c2aad20Sopenharmony_ci}
11637c2aad20Sopenharmony_ci
11647c2aad20Sopenharmony_ciint bpf_link_get_info_by_fd(int link_fd, struct bpf_link_info *info, __u32 *info_len)
11657c2aad20Sopenharmony_ci{
11667c2aad20Sopenharmony_ci	return bpf_obj_get_info_by_fd(link_fd, info, info_len);
11677c2aad20Sopenharmony_ci}
11687c2aad20Sopenharmony_ci
11697c2aad20Sopenharmony_ciint bpf_raw_tracepoint_open(const char *name, int prog_fd)
11707c2aad20Sopenharmony_ci{
11717c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, raw_tracepoint);
11727c2aad20Sopenharmony_ci	union bpf_attr attr;
11737c2aad20Sopenharmony_ci	int fd;
11747c2aad20Sopenharmony_ci
11757c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
11767c2aad20Sopenharmony_ci	attr.raw_tracepoint.name = ptr_to_u64(name);
11777c2aad20Sopenharmony_ci	attr.raw_tracepoint.prog_fd = prog_fd;
11787c2aad20Sopenharmony_ci
11797c2aad20Sopenharmony_ci	fd = sys_bpf_fd(BPF_RAW_TRACEPOINT_OPEN, &attr, attr_sz);
11807c2aad20Sopenharmony_ci	return libbpf_err_errno(fd);
11817c2aad20Sopenharmony_ci}
11827c2aad20Sopenharmony_ci
11837c2aad20Sopenharmony_ciint bpf_btf_load(const void *btf_data, size_t btf_size, struct bpf_btf_load_opts *opts)
11847c2aad20Sopenharmony_ci{
11857c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, btf_log_true_size);
11867c2aad20Sopenharmony_ci	union bpf_attr attr;
11877c2aad20Sopenharmony_ci	char *log_buf;
11887c2aad20Sopenharmony_ci	size_t log_size;
11897c2aad20Sopenharmony_ci	__u32 log_level;
11907c2aad20Sopenharmony_ci	int fd;
11917c2aad20Sopenharmony_ci
11927c2aad20Sopenharmony_ci	bump_rlimit_memlock();
11937c2aad20Sopenharmony_ci
11947c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
11957c2aad20Sopenharmony_ci
11967c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_btf_load_opts))
11977c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
11987c2aad20Sopenharmony_ci
11997c2aad20Sopenharmony_ci	log_buf = OPTS_GET(opts, log_buf, NULL);
12007c2aad20Sopenharmony_ci	log_size = OPTS_GET(opts, log_size, 0);
12017c2aad20Sopenharmony_ci	log_level = OPTS_GET(opts, log_level, 0);
12027c2aad20Sopenharmony_ci
12037c2aad20Sopenharmony_ci	if (log_size > UINT_MAX)
12047c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
12057c2aad20Sopenharmony_ci	if (log_size && !log_buf)
12067c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
12077c2aad20Sopenharmony_ci
12087c2aad20Sopenharmony_ci	attr.btf = ptr_to_u64(btf_data);
12097c2aad20Sopenharmony_ci	attr.btf_size = btf_size;
12107c2aad20Sopenharmony_ci	/* log_level == 0 and log_buf != NULL means "try loading without
12117c2aad20Sopenharmony_ci	 * log_buf, but retry with log_buf and log_level=1 on error", which is
12127c2aad20Sopenharmony_ci	 * consistent across low-level and high-level BTF and program loading
12137c2aad20Sopenharmony_ci	 * APIs within libbpf and provides a sensible behavior in practice
12147c2aad20Sopenharmony_ci	 */
12157c2aad20Sopenharmony_ci	if (log_level) {
12167c2aad20Sopenharmony_ci		attr.btf_log_buf = ptr_to_u64(log_buf);
12177c2aad20Sopenharmony_ci		attr.btf_log_size = (__u32)log_size;
12187c2aad20Sopenharmony_ci		attr.btf_log_level = log_level;
12197c2aad20Sopenharmony_ci	}
12207c2aad20Sopenharmony_ci
12217c2aad20Sopenharmony_ci	fd = sys_bpf_fd(BPF_BTF_LOAD, &attr, attr_sz);
12227c2aad20Sopenharmony_ci	if (fd < 0 && log_buf && log_level == 0) {
12237c2aad20Sopenharmony_ci		attr.btf_log_buf = ptr_to_u64(log_buf);
12247c2aad20Sopenharmony_ci		attr.btf_log_size = (__u32)log_size;
12257c2aad20Sopenharmony_ci		attr.btf_log_level = 1;
12267c2aad20Sopenharmony_ci		fd = sys_bpf_fd(BPF_BTF_LOAD, &attr, attr_sz);
12277c2aad20Sopenharmony_ci	}
12287c2aad20Sopenharmony_ci
12297c2aad20Sopenharmony_ci	OPTS_SET(opts, log_true_size, attr.btf_log_true_size);
12307c2aad20Sopenharmony_ci	return libbpf_err_errno(fd);
12317c2aad20Sopenharmony_ci}
12327c2aad20Sopenharmony_ci
12337c2aad20Sopenharmony_ciint bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len,
12347c2aad20Sopenharmony_ci		      __u32 *prog_id, __u32 *fd_type, __u64 *probe_offset,
12357c2aad20Sopenharmony_ci		      __u64 *probe_addr)
12367c2aad20Sopenharmony_ci{
12377c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, task_fd_query);
12387c2aad20Sopenharmony_ci	union bpf_attr attr;
12397c2aad20Sopenharmony_ci	int err;
12407c2aad20Sopenharmony_ci
12417c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
12427c2aad20Sopenharmony_ci	attr.task_fd_query.pid = pid;
12437c2aad20Sopenharmony_ci	attr.task_fd_query.fd = fd;
12447c2aad20Sopenharmony_ci	attr.task_fd_query.flags = flags;
12457c2aad20Sopenharmony_ci	attr.task_fd_query.buf = ptr_to_u64(buf);
12467c2aad20Sopenharmony_ci	attr.task_fd_query.buf_len = *buf_len;
12477c2aad20Sopenharmony_ci
12487c2aad20Sopenharmony_ci	err = sys_bpf(BPF_TASK_FD_QUERY, &attr, attr_sz);
12497c2aad20Sopenharmony_ci
12507c2aad20Sopenharmony_ci	*buf_len = attr.task_fd_query.buf_len;
12517c2aad20Sopenharmony_ci	*prog_id = attr.task_fd_query.prog_id;
12527c2aad20Sopenharmony_ci	*fd_type = attr.task_fd_query.fd_type;
12537c2aad20Sopenharmony_ci	*probe_offset = attr.task_fd_query.probe_offset;
12547c2aad20Sopenharmony_ci	*probe_addr = attr.task_fd_query.probe_addr;
12557c2aad20Sopenharmony_ci
12567c2aad20Sopenharmony_ci	return libbpf_err_errno(err);
12577c2aad20Sopenharmony_ci}
12587c2aad20Sopenharmony_ci
12597c2aad20Sopenharmony_ciint bpf_enable_stats(enum bpf_stats_type type)
12607c2aad20Sopenharmony_ci{
12617c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, enable_stats);
12627c2aad20Sopenharmony_ci	union bpf_attr attr;
12637c2aad20Sopenharmony_ci	int fd;
12647c2aad20Sopenharmony_ci
12657c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
12667c2aad20Sopenharmony_ci	attr.enable_stats.type = type;
12677c2aad20Sopenharmony_ci
12687c2aad20Sopenharmony_ci	fd = sys_bpf_fd(BPF_ENABLE_STATS, &attr, attr_sz);
12697c2aad20Sopenharmony_ci	return libbpf_err_errno(fd);
12707c2aad20Sopenharmony_ci}
12717c2aad20Sopenharmony_ci
12727c2aad20Sopenharmony_ciint bpf_prog_bind_map(int prog_fd, int map_fd,
12737c2aad20Sopenharmony_ci		      const struct bpf_prog_bind_opts *opts)
12747c2aad20Sopenharmony_ci{
12757c2aad20Sopenharmony_ci	const size_t attr_sz = offsetofend(union bpf_attr, prog_bind_map);
12767c2aad20Sopenharmony_ci	union bpf_attr attr;
12777c2aad20Sopenharmony_ci	int ret;
12787c2aad20Sopenharmony_ci
12797c2aad20Sopenharmony_ci	if (!OPTS_VALID(opts, bpf_prog_bind_opts))
12807c2aad20Sopenharmony_ci		return libbpf_err(-EINVAL);
12817c2aad20Sopenharmony_ci
12827c2aad20Sopenharmony_ci	memset(&attr, 0, attr_sz);
12837c2aad20Sopenharmony_ci	attr.prog_bind_map.prog_fd = prog_fd;
12847c2aad20Sopenharmony_ci	attr.prog_bind_map.map_fd = map_fd;
12857c2aad20Sopenharmony_ci	attr.prog_bind_map.flags = OPTS_GET(opts, flags, 0);
12867c2aad20Sopenharmony_ci
12877c2aad20Sopenharmony_ci	ret = sys_bpf(BPF_PROG_BIND_MAP, &attr, attr_sz);
12887c2aad20Sopenharmony_ci	return libbpf_err_errno(ret);
12897c2aad20Sopenharmony_ci}
1290