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 :
19 : #if defined(__i386__)
20 : #define _BF_NR_bpf 357
21 : #elif defined(__x86_64__)
22 : #define _BF_NR_bpf 321
23 : #elif defined(__aarch64__)
24 : #define _BF_NR_bpf 280
25 : #else
26 : #error _BF_NR_bpf not defined. bpfilter does not support your arch.
27 : #endif
28 :
29 0 : int bf_bpf(enum bpf_cmd cmd, union bpf_attr *attr)
30 : {
31 0 : int r = (int)syscall(_BF_NR_bpf, cmd, attr, sizeof(*attr));
32 0 : if (r < 0)
33 0 : return -errno;
34 :
35 : return r;
36 : }
37 :
38 0 : int bf_bpf_prog_load(const char *name, unsigned int prog_type, void *img,
39 : size_t img_len, enum bpf_attach_type attach_type,
40 : const char *log_buf, size_t log_size, int token_fd,
41 : int *fd)
42 : {
43 : union bpf_attr attr;
44 : int r;
45 :
46 0 : bf_assert(name && img && fd);
47 :
48 0 : memset(&attr, 0, sizeof(attr));
49 :
50 0 : attr.prog_type = prog_type;
51 0 : attr.insns = bf_ptr_to_u64(img);
52 0 : attr.insn_cnt = (unsigned int)img_len;
53 0 : attr.license = bf_ptr_to_u64("GPL");
54 0 : attr.expected_attach_type = attach_type;
55 0 : attr.log_buf = bf_ptr_to_u64(log_buf);
56 0 : attr.log_size = log_size;
57 0 : attr.log_level = 1;
58 :
59 0 : (void)snprintf(attr.prog_name, BPF_OBJ_NAME_LEN, "%s", name);
60 :
61 0 : if (token_fd != -1) {
62 0 : attr.prog_token_fd = token_fd;
63 0 : attr.prog_flags |= BPF_F_TOKEN_FD;
64 : }
65 :
66 0 : r = bf_bpf(BPF_PROG_LOAD, &attr);
67 0 : if (r < 0)
68 : return r;
69 :
70 0 : *fd = r;
71 :
72 0 : return 0;
73 : }
74 :
75 0 : int bf_bpf_map_lookup_elem(int fd, const void *key, void *value)
76 : {
77 : union bpf_attr attr;
78 :
79 0 : bf_assert(key);
80 0 : bf_assert(value);
81 :
82 0 : memset(&attr, 0, sizeof(attr));
83 :
84 0 : attr.map_fd = fd;
85 0 : attr.key = (uint64_t)key;
86 0 : attr.value = (uint64_t)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 : union bpf_attr attr;
94 :
95 0 : memset(&attr, 0, sizeof(attr));
96 :
97 0 : attr.map_fd = fd;
98 0 : attr.key = bf_ptr_to_u64(key);
99 0 : attr.value = bf_ptr_to_u64(value);
100 : attr.flags = BPF_ANY;
101 :
102 0 : return bf_bpf(BPF_MAP_UPDATE_ELEM, &attr);
103 : }
104 :
105 0 : int bf_bpf_obj_pin(const char *path, int fd, int dir_fd)
106 : {
107 : union bpf_attr attr;
108 :
109 0 : bf_assert(path);
110 0 : bf_assert(dir_fd >= 0);
111 0 : bf_assert(path[0] == '/' ? !dir_fd : 1);
112 :
113 0 : memset(&attr, 0, sizeof(attr));
114 :
115 0 : attr.pathname = bf_ptr_to_u64(path);
116 0 : attr.bpf_fd = fd;
117 0 : attr.file_flags = dir_fd ? BPF_F_PATH_FD : 0;
118 0 : attr.path_fd = dir_fd;
119 :
120 0 : int r = bf_bpf(BPF_OBJ_PIN, &attr);
121 0 : return r;
122 : }
123 :
124 0 : int bf_bpf_obj_get(const char *path, int dir_fd, int *fd)
125 : {
126 : union bpf_attr attr;
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 : memset(&attr, 0, sizeof(attr));
134 :
135 0 : attr.pathname = bf_ptr_to_u64(path);
136 0 : attr.file_flags = dir_fd ? BPF_F_PATH_FD : 0;
137 0 : attr.path_fd = dir_fd;
138 :
139 0 : r = bf_bpf(BPF_OBJ_GET, &attr);
140 0 : if (r < 0)
141 : return r;
142 :
143 0 : *fd = r;
144 :
145 0 : return 0;
146 : }
147 :
148 0 : int bf_prog_run(int prog_fd, const void *pkt, size_t pkt_len, const void *ctx,
149 : size_t ctx_len)
150 : {
151 : union bpf_attr attr;
152 : int r;
153 :
154 0 : bf_assert(pkt);
155 0 : bf_assert(pkt_len > 0);
156 0 : bf_assert(!(!!ctx ^ !!ctx_len));
157 :
158 0 : memset(&attr, 0, sizeof(attr));
159 :
160 0 : attr.test.prog_fd = prog_fd;
161 0 : attr.test.data_size_in = pkt_len;
162 0 : attr.test.data_in = ((unsigned long long)(pkt));
163 0 : attr.test.repeat = 1;
164 :
165 0 : if (ctx_len) {
166 0 : attr.test.ctx_size_in = ctx_len;
167 0 : attr.test.ctx_in = ((unsigned long long)(ctx));
168 : }
169 :
170 0 : r = bf_bpf(BPF_PROG_TEST_RUN, &attr);
171 0 : if (r)
172 0 : return bf_err_r(r, "failed to run the test program");
173 :
174 0 : return (int)attr.test.retval;
175 : }
|