Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
43b987d
Documentation
LICENSES
arch
block
certs
crypto
drivers
firmware
fs
include
init
ipc
kernel
lib
mm
net
samples
scripts
security
sound
tools
accounting
arch
bpf
build
cgroup
firewire
gpio
hv
iio
include
kvm
laptop
leds
lib
api
bpf
.gitignore
Build
Makefile
bpf.c
bpf.h
btf.c
btf.h
libbpf.c
libbpf.h
libbpf_errno.c
netlink.c
nlattr.c
nlattr.h
str_error.c
str_error.h
lockdep
subcmd
symbol
traceevent
bitmap.c
find_bit.c
hweight.c
rbtree.c
str_error_r.c
string.c
vsprintf.c
memory-model
nfsd
objtool
pci
pcmcia
perf
power
scripts
spi
testing
thermal
time
usb
virtio
vm
wmi
Makefile
usr
virt
.clang-format
.cocciconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
Breadcrumbs
linux
/
tools
/
lib
/
bpf
/
bpf.c
Blame
Blame
Latest commit
History
History
552 lines (446 loc) · 13.5 KB
Breadcrumbs
linux
/
tools
/
lib
/
bpf
/
bpf.c
Top
File metadata and controls
Code
Blame
552 lines (446 loc) · 13.5 KB
Raw
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) /* * common eBPF ELF operations. * * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> * Copyright (C) 2015 Huawei Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License (not later!) * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see <http://www.gnu.org/licenses> */ #include <stdlib.h> #include <memory.h> #include <unistd.h> #include <asm/unistd.h> #include <linux/bpf.h> #include "bpf.h" #include "libbpf.h" #include <errno.h> /* * When building perf, unistd.h is overridden. __NR_bpf is * required to be defined explicitly. */ #ifndef __NR_bpf # if defined(__i386__) # define __NR_bpf 357 # elif defined(__x86_64__) # define __NR_bpf 321 # elif defined(__aarch64__) # define __NR_bpf 280 # elif defined(__sparc__) # define __NR_bpf 349 # elif defined(__s390__) # define __NR_bpf 351 # else # error __NR_bpf not defined. libbpf does not support your arch. # endif #endif #ifndef min #define min(x, y) ((x) < (y) ? (x) : (y)) #endif static inline __u64 ptr_to_u64(const void *ptr) { return (__u64) (unsigned long) ptr; } static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, unsigned int size) { return syscall(__NR_bpf, cmd, attr, size); } int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr) { __u32 name_len = create_attr->name ? strlen(create_attr->name) : 0; union bpf_attr attr; memset(&attr, '\0', sizeof(attr)); attr.map_type = create_attr->map_type; attr.key_size = create_attr->key_size; attr.value_size = create_attr->value_size; attr.max_entries = create_attr->max_entries; attr.map_flags = create_attr->map_flags; memcpy(attr.map_name, create_attr->name, min(name_len, BPF_OBJ_NAME_LEN - 1)); attr.numa_node = create_attr->numa_node; attr.btf_fd = create_attr->btf_fd; attr.btf_key_type_id = create_attr->btf_key_type_id; attr.btf_value_type_id = create_attr->btf_value_type_id; attr.map_ifindex = create_attr->map_ifindex; attr.inner_map_fd = create_attr->inner_map_fd; return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); } int bpf_create_map_node(enum bpf_map_type map_type, const char *name, int key_size, int value_size, int max_entries, __u32 map_flags, int node) { struct bpf_create_map_attr map_attr = {}; map_attr.name = name; map_attr.map_type = map_type; map_attr.map_flags = map_flags; map_attr.key_size = key_size; map_attr.value_size = value_size; map_attr.max_entries = max_entries; if (node >= 0) { map_attr.numa_node = node; map_attr.map_flags |= BPF_F_NUMA_NODE; } return bpf_create_map_xattr(&map_attr); } int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int max_entries, __u32 map_flags) { struct bpf_create_map_attr map_attr = {}; map_attr.map_type = map_type; map_attr.map_flags = map_flags; map_attr.key_size = key_size; map_attr.value_size = value_size; map_attr.max_entries = max_entries; return bpf_create_map_xattr(&map_attr); } int bpf_create_map_name(enum bpf_map_type map_type, const char *name, int key_size, int value_size, int max_entries, __u32 map_flags) { struct bpf_create_map_attr map_attr = {}; map_attr.name = name; map_attr.map_type = map_type; map_attr.map_flags = map_flags; map_attr.key_size = key_size; map_attr.value_size = value_size; map_attr.max_entries = max_entries; return bpf_create_map_xattr(&map_attr); } int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name, int key_size, int inner_map_fd, int max_entries, __u32 map_flags, int node) { __u32 name_len = name ? strlen(name) : 0; union bpf_attr attr; memset(&attr, '\0', sizeof(attr)); attr.map_type = map_type; attr.key_size = key_size; attr.value_size = 4; attr.inner_map_fd = inner_map_fd; attr.max_entries = max_entries; attr.map_flags = map_flags; memcpy(attr.map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1)); if (node >= 0) { attr.map_flags |= BPF_F_NUMA_NODE; attr.numa_node = node; } return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); } int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name, int key_size, int inner_map_fd, int max_entries, __u32 map_flags) { return bpf_create_map_in_map_node(map_type, name, key_size, inner_map_fd, max_entries, map_flags, -1); } int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr, char *log_buf, size_t log_buf_sz) { union bpf_attr attr; __u32 name_len; int fd; if (!load_attr) return -EINVAL; name_len = load_attr->name ? strlen(load_attr->name) : 0; bzero(&attr, sizeof(attr)); attr.prog_type = load_attr->prog_type; attr.expected_attach_type = load_attr->expected_attach_type; attr.insn_cnt = (__u32)load_attr->insns_cnt; attr.insns = ptr_to_u64(load_attr->insns); attr.license = ptr_to_u64(load_attr->license); attr.log_buf = ptr_to_u64(NULL); attr.log_size = 0; attr.log_level = 0; attr.kern_version = load_attr->kern_version; attr.prog_ifindex = load_attr->prog_ifindex; memcpy(attr.prog_name, load_attr->name, min(name_len, BPF_OBJ_NAME_LEN - 1)); fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); if (fd >= 0 || !log_buf || !log_buf_sz) return fd; /* Try again with log */ attr.log_buf = ptr_to_u64(log_buf); attr.log_size = log_buf_sz; attr.log_level = 1; log_buf[0] = 0; return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); } int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, size_t insns_cnt, const char *license, __u32 kern_version, char *log_buf, size_t log_buf_sz) { struct bpf_load_program_attr load_attr; memset(&load_attr, 0, sizeof(struct bpf_load_program_attr)); load_attr.prog_type = type; load_attr.expected_attach_type = 0; load_attr.name = NULL; load_attr.insns = insns; load_attr.insns_cnt = insns_cnt; load_attr.license = license; load_attr.kern_version = kern_version; return bpf_load_program_xattr(&load_attr, log_buf, log_buf_sz); } int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, size_t insns_cnt, int strict_alignment, const char *license, __u32 kern_version, char *log_buf, size_t log_buf_sz, int log_level) { union bpf_attr attr; bzero(&attr, sizeof(attr)); attr.prog_type = type; attr.insn_cnt = (__u32)insns_cnt; attr.insns = ptr_to_u64(insns); attr.license = ptr_to_u64(license); attr.log_buf = ptr_to_u64(log_buf); attr.log_size = log_buf_sz; attr.log_level = log_level; log_buf[0] = 0; attr.kern_version = kern_version; attr.prog_flags = strict_alignment ? BPF_F_STRICT_ALIGNMENT : 0; return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); } int bpf_map_update_elem(int fd, const void *key, const void *value, __u64 flags) { union bpf_attr attr; bzero(&attr, sizeof(attr)); attr.map_fd = fd; attr.key = ptr_to_u64(key); attr.value = ptr_to_u64(value); attr.flags = flags; return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); } int bpf_map_lookup_elem(int fd, const void *key, void *value) { union bpf_attr attr; bzero(&attr, sizeof(attr)); attr.map_fd = fd; attr.key = ptr_to_u64(key); attr.value = ptr_to_u64(value); return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); } int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value) { union bpf_attr attr; bzero(&attr, sizeof(attr)); attr.map_fd = fd; attr.key = ptr_to_u64(key); attr.value = ptr_to_u64(value); return sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr)); } int bpf_map_delete_elem(int fd, const void *key) { union bpf_attr attr; bzero(&attr, sizeof(attr)); attr.map_fd = fd; attr.key = ptr_to_u64(key); return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr)); } int bpf_map_get_next_key(int fd, const void *key, void *next_key) { union bpf_attr attr; bzero(&attr, sizeof(attr)); attr.map_fd = fd; attr.key = ptr_to_u64(key); attr.next_key = ptr_to_u64(next_key); return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr)); } int bpf_obj_pin(int fd, const char *pathname) { union bpf_attr attr; bzero(&attr, sizeof(attr)); attr.pathname = ptr_to_u64((void *)pathname); attr.bpf_fd = fd; return sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr)); } int bpf_obj_get(const char *pathname) { union bpf_attr attr; bzero(&attr, sizeof(attr)); attr.pathname = ptr_to_u64((void *)pathname); return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr)); } int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type, unsigned int flags) { union bpf_attr attr; bzero(&attr, sizeof(attr)); attr.target_fd = target_fd; attr.attach_bpf_fd = prog_fd; attr.attach_type = type; attr.attach_flags = flags; return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)); } int bpf_prog_detach(int target_fd, enum bpf_attach_type type) { union bpf_attr attr; bzero(&attr, sizeof(attr)); attr.target_fd = target_fd; attr.attach_type = type; return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr)); } int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type) { union bpf_attr attr; bzero(&attr, sizeof(attr)); attr.target_fd = target_fd; attr.attach_bpf_fd = prog_fd; attr.attach_type = type; return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr)); } int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags, __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt) { union bpf_attr attr; int ret; bzero(&attr, sizeof(attr)); attr.query.target_fd = target_fd; attr.query.attach_type = type; attr.query.query_flags = query_flags; attr.query.prog_cnt = *prog_cnt; attr.query.prog_ids = ptr_to_u64(prog_ids); ret = sys_bpf(BPF_PROG_QUERY, &attr, sizeof(attr)); if (attach_flags) *attach_flags = attr.query.attach_flags; *prog_cnt = attr.query.prog_cnt; return ret; } int bpf_prog_test_run(int prog_fd, int repeat, void *data, __u32 size, void *data_out, __u32 *size_out, __u32 *retval, __u32 *duration) { union bpf_attr attr; int ret; bzero(&attr, sizeof(attr)); attr.test.prog_fd = prog_fd; attr.test.data_in = ptr_to_u64(data); attr.test.data_out = ptr_to_u64(data_out); attr.test.data_size_in = size; attr.test.repeat = repeat; ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr)); if (size_out) *size_out = attr.test.data_size_out; if (retval) *retval = attr.test.retval; if (duration) *duration = attr.test.duration; return ret; } int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id) { union bpf_attr attr; int err; bzero(&attr, sizeof(attr)); attr.start_id = start_id; err = sys_bpf(BPF_PROG_GET_NEXT_ID, &attr, sizeof(attr)); if (!err) *next_id = attr.next_id; return err; } int bpf_map_get_next_id(__u32 start_id, __u32 *next_id) { union bpf_attr attr; int err; bzero(&attr, sizeof(attr)); attr.start_id = start_id; err = sys_bpf(BPF_MAP_GET_NEXT_ID, &attr, sizeof(attr)); if (!err) *next_id = attr.next_id; return err; } int bpf_prog_get_fd_by_id(__u32 id) { union bpf_attr attr; bzero(&attr, sizeof(attr)); attr.prog_id = id; return sys_bpf(BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr)); } int bpf_map_get_fd_by_id(__u32 id) { union bpf_attr attr; bzero(&attr, sizeof(attr)); attr.map_id = id; return sys_bpf(BPF_MAP_GET_FD_BY_ID, &attr, sizeof(attr)); } int bpf_btf_get_fd_by_id(__u32 id) { union bpf_attr attr; bzero(&attr, sizeof(attr)); attr.btf_id = id; return sys_bpf(BPF_BTF_GET_FD_BY_ID, &attr, sizeof(attr)); } int bpf_obj_get_info_by_fd(int prog_fd, void *info, __u32 *info_len) { union bpf_attr attr; int err; bzero(&attr, sizeof(attr)); attr.info.bpf_fd = prog_fd; attr.info.info_len = *info_len; attr.info.info = ptr_to_u64(info); err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr)); if (!err) *info_len = attr.info.info_len; return err; } int bpf_raw_tracepoint_open(const char *name, int prog_fd) { union bpf_attr attr; bzero(&attr, sizeof(attr)); attr.raw_tracepoint.name = ptr_to_u64(name); attr.raw_tracepoint.prog_fd = prog_fd; return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr)); } int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size, bool do_log) { union bpf_attr attr = {}; int fd; attr.btf = ptr_to_u64(btf); attr.btf_size = btf_size; retry: if (do_log && log_buf && log_buf_size) { attr.btf_log_level = 1; attr.btf_log_size = log_buf_size; attr.btf_log_buf = ptr_to_u64(log_buf); } fd = sys_bpf(BPF_BTF_LOAD, &attr, sizeof(attr)); if (fd == -1 && !do_log && log_buf && log_buf_size) { do_log = true; goto retry; } return fd; } int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len, __u32 *prog_id, __u32 *fd_type, __u64 *probe_offset, __u64 *probe_addr) { union bpf_attr attr = {}; int err; attr.task_fd_query.pid = pid; attr.task_fd_query.fd = fd; attr.task_fd_query.flags = flags; attr.task_fd_query.buf = ptr_to_u64(buf); attr.task_fd_query.buf_len = *buf_len; err = sys_bpf(BPF_TASK_FD_QUERY, &attr, sizeof(attr)); *buf_len = attr.task_fd_query.buf_len; *prog_id = attr.task_fd_query.prog_id; *fd_type = attr.task_fd_query.fd_type; *probe_offset = attr.task_fd_query.probe_offset; *probe_addr = attr.task_fd_query.probe_addr; return err; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
You can’t perform that action at this time.