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