Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-only
2 : /*
3 : * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
4 : */
5 :
6 : #include "core/bpf.h"
7 :
8 : #include <linux/bpf.h>
9 :
10 : #include <errno.h>
11 : #include <stdint.h>
12 : #include <stdio.h>
13 : #include <stdlib.h>
14 : #include <unistd.h>
15 :
16 : #include "core/helper.h"
17 : #include "core/logger.h"
18 : #include "core/opts.h"
19 :
20 : #if defined(__i386__)
21 : #define _BF_NR_bpf 357
22 : #elif defined(__x86_64__)
23 : #define _BF_NR_bpf 321
24 : #elif defined(__aarch64__)
25 : #define _BF_NR_bpf 280
26 : #else
27 : #error _BF_NR_bpf not defined. bpfilter does not support your arch.
28 : #endif
29 :
30 0 : int bf_bpf(enum bpf_cmd cmd, union bpf_attr *attr)
31 : {
32 0 : int r = (int)syscall(_BF_NR_bpf, cmd, attr, sizeof(*attr));
33 0 : if (r < 0)
34 0 : return -errno;
35 :
36 : return r;
37 : }
38 :
39 0 : int bf_bpf_prog_load(const char *name, unsigned int prog_type, void *img,
40 : size_t img_len, enum bpf_attach_type attach_type, int *fd)
41 : {
42 : _cleanup_free_ char *log_buf = NULL;
43 0 : union bpf_attr attr = {
44 : .prog_type = prog_type,
45 0 : .insns = bf_ptr_to_u64(img),
46 0 : .insn_cnt = (unsigned int)img_len,
47 0 : .license = bf_ptr_to_u64("GPL"),
48 : .expected_attach_type = attach_type,
49 : };
50 : int r;
51 :
52 0 : bf_assert(name && img && fd);
53 :
54 0 : if (bf_opts_is_verbose(BF_VERBOSE_BPF)) {
55 0 : log_buf = malloc(1 << bf_opts_bpf_log_buf_len_pow());
56 0 : if (!log_buf)
57 : return -ENOMEM;
58 :
59 0 : attr.log_buf = bf_ptr_to_u64(log_buf);
60 0 : attr.log_size = (uint32_t)(1 << bf_opts_bpf_log_buf_len_pow());
61 0 : attr.log_level = 1;
62 : }
63 :
64 0 : (void)snprintf(attr.prog_name, BPF_OBJ_NAME_LEN, "%s", name);
65 :
66 0 : r = bf_bpf(BPF_PROG_LOAD, &attr);
67 0 : if (r < 0) {
68 0 : return bf_err_r(r, "failed to load BPF program (%lu bytes):\n%s\n",
69 : img_len, log_buf ?: "(no log buffer available)");
70 : }
71 :
72 0 : *fd = r;
73 :
74 0 : return 0;
75 : }
76 :
77 0 : int bf_bpf_map_lookup_elem(int fd, const void *key, void *value)
78 : {
79 0 : union bpf_attr attr = {
80 : .map_fd = fd,
81 0 : .key = (uint64_t)key,
82 0 : .value = (uint64_t)value,
83 : };
84 :
85 0 : bf_assert(key);
86 0 : bf_assert(value);
87 :
88 0 : return bf_bpf(BPF_MAP_LOOKUP_ELEM, &attr);
89 : }
90 :
91 0 : int bf_bpf_map_update_elem(int fd, const void *key, void *value)
92 : {
93 0 : union bpf_attr attr = {
94 : .map_fd = fd,
95 0 : .key = bf_ptr_to_u64(key),
96 0 : .value = bf_ptr_to_u64(value),
97 : .flags = BPF_ANY,
98 : };
99 :
100 0 : return bf_bpf(BPF_MAP_UPDATE_ELEM, &attr);
101 : }
102 :
103 0 : int bf_bpf_obj_pin(const char *path, int fd, int dir_fd)
104 : {
105 0 : union bpf_attr attr = {
106 0 : .pathname = bf_ptr_to_u64(path),
107 : .bpf_fd = fd,
108 0 : .file_flags = dir_fd ? BPF_F_PATH_FD : 0,
109 : .path_fd = dir_fd,
110 : };
111 :
112 0 : bf_assert(path);
113 0 : bf_assert(dir_fd >= 0);
114 0 : bf_assert(path[0] == '/' ? !dir_fd : 1);
115 :
116 0 : int r = bf_bpf(BPF_OBJ_PIN, &attr);
117 0 : return r;
118 : }
119 :
120 0 : int bf_bpf_obj_get(const char *path, int dir_fd, int *fd)
121 : {
122 0 : union bpf_attr attr = {
123 0 : .pathname = bf_ptr_to_u64(path),
124 0 : .file_flags = dir_fd ? BPF_F_PATH_FD : 0,
125 : .path_fd = dir_fd,
126 : };
127 : int r;
128 :
129 0 : bf_assert(path && fd);
130 0 : bf_assert(dir_fd >= 0);
131 0 : bf_assert(path[0] == '/' ? !dir_fd : 1);
132 :
133 0 : r = bf_bpf(BPF_OBJ_GET, &attr);
134 0 : if (r < 0)
135 : return r;
136 :
137 0 : *fd = r;
138 :
139 0 : return 0;
140 : }
|