Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
3 : : * Copyright (c) 2017 Quentin Monnet <quentin.monnet@6wind.com>
4 : : * All rights reserved.
5 : : *
6 : : * Redistribution and use in source and binary forms, with or without
7 : : * modification, are permitted provided that the following conditions
8 : : * are met:
9 : : * 1. Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer.
11 : : * 2. Redistributions in binary form must reproduce the above copyright
12 : : * notice, this list of conditions and the following disclaimer in the
13 : : * documentation and/or other materials provided with the distribution.
14 : : * 3. The name of the author may not be used to endorse or promote products
15 : : * derived from this software without specific prior written permission.
16 : : *
17 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 : : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 : : */
28 : :
29 : : #include "defs.h"
30 : :
31 : : #ifdef HAVE_LINUX_BPF_H
32 : : # include <linux/bpf.h>
33 : : #endif
34 : :
35 : : #include "xlat/bpf_commands.h"
36 : : #include "xlat/bpf_map_types.h"
37 : : #include "xlat/bpf_prog_types.h"
38 : : #include "xlat/bpf_map_update_elem_flags.h"
39 : : #include "xlat/bpf_attach_type.h"
40 : : #include "xlat/bpf_attach_flags.h"
41 : :
42 : : static int
43 : 20 : bpf_map_create(struct tcb *const tcp, const kernel_ulong_t addr,
44 : : unsigned int size)
45 : : {
46 : : struct {
47 : : uint32_t map_type, key_size, value_size, max_entries;
48 : 20 : } attr = {};
49 : :
50 [ + + ]: 20 : if (!size) {
51 : 5 : printaddr(addr);
52 : 5 : return RVAL_DECODED | RVAL_FD;
53 : : }
54 [ + + ]: 15 : if (size > sizeof(attr))
55 : 10 : size = sizeof(attr);
56 [ + + ]: 15 : if (umoven_or_printaddr(tcp, addr, size, &attr))
57 : 10 : return RVAL_DECODED | RVAL_FD;
58 : :
59 : 5 : tprints("{map_type=");
60 : 5 : printxval(bpf_map_types, attr.map_type, "BPF_MAP_TYPE_???");
61 : 5 : tprintf(", key_size=%u, value_size=%u, max_entries=%u}",
62 : : attr.key_size, attr.value_size, attr.max_entries);
63 : :
64 : 20 : return RVAL_DECODED | RVAL_FD;
65 : : }
66 : :
67 : : static void
68 : 20 : bpf_map_update_elem(struct tcb *const tcp, const kernel_ulong_t addr,
69 : : unsigned int size)
70 : : {
71 : : struct {
72 : : uint32_t map_fd;
73 : : uint64_t ATTRIBUTE_ALIGNED(8) key;
74 : : uint64_t ATTRIBUTE_ALIGNED(8) value;
75 : : uint64_t flags;
76 : 20 : } attr = {};
77 : :
78 [ + + ]: 20 : if (!size) {
79 : 5 : printaddr(addr);
80 : 15 : return;
81 : : }
82 [ + + ]: 15 : if (size > sizeof(attr))
83 : 10 : size = sizeof(attr);
84 [ + + ]: 15 : if (umoven_or_printaddr(tcp, addr, size, &attr))
85 : 10 : return;
86 : :
87 : 5 : tprints("{map_fd=");
88 : 5 : printfd(tcp, attr.map_fd);
89 : 5 : tprintf(", key=%#" PRIx64 ", value=%#" PRIx64 ", flags=",
90 : : attr.key, attr.value);
91 : 5 : printxval64(bpf_map_update_elem_flags, attr.flags, "BPF_???");
92 : 5 : tprints("}");
93 : : }
94 : :
95 : : static void
96 : 20 : bpf_map_delete_elem(struct tcb *const tcp, const kernel_ulong_t addr,
97 : : unsigned int size)
98 : : {
99 : : struct {
100 : : uint32_t map_fd;
101 : : uint64_t ATTRIBUTE_ALIGNED(8) key;
102 : 20 : } attr = {};
103 : :
104 [ + + ]: 20 : if (!size) {
105 : 5 : printaddr(addr);
106 : 15 : return;
107 : : }
108 [ + + ]: 15 : if (size > sizeof(attr))
109 : 10 : size = sizeof(attr);
110 [ + + ]: 15 : if (umoven_or_printaddr(tcp, addr, size, &attr))
111 : 10 : return;
112 : :
113 : 5 : tprints("{map_fd=");
114 : 5 : printfd(tcp, attr.map_fd);
115 : 5 : tprintf(", key=%#" PRIx64 "}", attr.key);
116 : : }
117 : :
118 : : static int
119 : 50 : bpf_map_io(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int size,
120 : : const char *const text)
121 : : {
122 : : struct bpf_io_elem_struct {
123 : : uint32_t map_fd;
124 : : uint64_t ATTRIBUTE_ALIGNED(8) key;
125 : : uint64_t ATTRIBUTE_ALIGNED(8) value;
126 : 50 : } attr = {};
127 : :
128 [ + + ]: 50 : if (exiting(tcp)) {
129 [ - + ][ # # ]: 10 : if (!syserror(tcp) && !umove_or_printaddr(tcp, addr, &attr))
130 : 0 : tprintf(", %s=%#" PRIx64, text, attr.value);
131 : 10 : tprints("}");
132 : 10 : return RVAL_DECODED;
133 : : }
134 : :
135 [ + + ]: 40 : if (!size) {
136 : 10 : printaddr(addr);
137 : 10 : return RVAL_DECODED;
138 : : }
139 [ + + ]: 30 : if (size > sizeof(attr))
140 : 20 : size = sizeof(attr);
141 [ + + ]: 30 : if (umoven_or_printaddr(tcp, addr, size, &attr))
142 : 20 : return RVAL_DECODED;
143 : :
144 : 10 : tprints("{map_fd=");
145 : 10 : printfd(tcp, attr.map_fd);
146 : 10 : tprintf(", key=%#" PRIx64, attr.key);
147 : :
148 : 50 : return 0;
149 : : }
150 : :
151 : : static int
152 : 20 : bpf_prog_load(struct tcb *const tcp, const kernel_ulong_t addr,
153 : : unsigned int size)
154 : : {
155 : : struct {
156 : : uint32_t prog_type, insn_cnt;
157 : : uint64_t ATTRIBUTE_ALIGNED(8) insns, license;
158 : : uint32_t log_level, log_size;
159 : : uint64_t ATTRIBUTE_ALIGNED(8) log_buf;
160 : : uint32_t kern_version;
161 : 20 : } attr = {};
162 : :
163 [ + + ]: 20 : if (!size) {
164 : 5 : printaddr(addr);
165 : 5 : return RVAL_DECODED | RVAL_FD;
166 : : }
167 [ + + ]: 15 : if (size > sizeof(attr))
168 : 5 : size = sizeof(attr);
169 [ + + ]: 15 : if (umoven_or_printaddr(tcp, addr, size, &attr))
170 : 10 : return RVAL_DECODED | RVAL_FD;
171 : :
172 : 5 : tprints("{prog_type=");
173 : 5 : printxval(bpf_prog_types, attr.prog_type, "BPF_PROG_TYPE_???");
174 : 5 : tprintf(", insn_cnt=%u, insns=%#" PRIx64 ", license=",
175 : : attr.insn_cnt, attr.insns);
176 : 5 : printstr(tcp, attr.license);
177 : 5 : tprintf(", log_level=%u, log_size=%u, log_buf=%#" PRIx64 ", kern_version=%u}",
178 : : attr.log_level, attr.log_size, attr.log_buf, attr.kern_version);
179 : :
180 : 20 : return RVAL_DECODED | RVAL_FD;
181 : : }
182 : :
183 : : static int
184 : 40 : bpf_obj_manage(struct tcb *const tcp, const kernel_ulong_t addr,
185 : : unsigned int size)
186 : : {
187 : : struct {
188 : : uint64_t ATTRIBUTE_ALIGNED(8) pathname;
189 : : uint32_t bpf_fd;
190 : 40 : } attr = {};
191 : :
192 [ + + ]: 40 : if (!size) {
193 : 10 : printaddr(addr);
194 : 10 : return RVAL_DECODED | RVAL_FD;
195 : : }
196 [ + + ]: 30 : if (size > sizeof(attr))
197 : 20 : size = sizeof(attr);
198 [ + + ]: 30 : if (umoven_or_printaddr(tcp, addr, size, &attr))
199 : 20 : return RVAL_DECODED | RVAL_FD;
200 : :
201 : 10 : tprints("{pathname=");
202 : 10 : printpath(tcp, attr.pathname);
203 : 10 : tprints(", bpf_fd=");
204 : 10 : printfd(tcp, attr.bpf_fd);
205 : 10 : tprints("}");
206 : :
207 : 40 : return RVAL_DECODED | RVAL_FD;
208 : : }
209 : :
210 : : static int
211 : 40 : bpf_prog_attach_detach(struct tcb *const tcp, const kernel_ulong_t addr,
212 : : unsigned int size, bool print_attach)
213 : : {
214 : : struct {
215 : : uint32_t target_fd, attach_bpf_fd, attach_type, attach_flags;
216 : 40 : } attr = {};
217 : :
218 [ + + ]: 40 : if (!size) {
219 : 10 : printaddr(addr);
220 : 10 : return RVAL_DECODED;
221 : : }
222 [ + + ]: 30 : if (size > sizeof(attr))
223 : 20 : size = sizeof(attr);
224 [ + + ]: 30 : if (umoven_or_printaddr(tcp, addr, size, &attr))
225 : 20 : return RVAL_DECODED;
226 : :
227 : 10 : tprints("{target_fd=");
228 : 10 : printfd(tcp, attr.target_fd);
229 [ + + ]: 10 : if (print_attach) {
230 : 5 : tprints(", attach_bpf_fd=");
231 : 5 : printfd(tcp, attr.attach_bpf_fd);
232 : : }
233 : 10 : tprints(", attach_type=");
234 : 10 : printxval(bpf_attach_type, attr.attach_type, "BPF_???");
235 [ + + ]: 10 : if (print_attach) {
236 : 5 : tprints(", attach_flags=");
237 : 5 : printflags(bpf_attach_flags, attr.attach_flags, "BPF_F_???");
238 : : }
239 : 10 : tprints("}");
240 : :
241 : 40 : return RVAL_DECODED;
242 : : }
243 : :
244 : : static int
245 : 20 : bpf_prog_attach(struct tcb *const tcp, const kernel_ulong_t addr,
246 : : unsigned int size)
247 : : {
248 : 20 : return bpf_prog_attach_detach(tcp, addr, size, true);
249 : : }
250 : :
251 : : static int
252 : 20 : bpf_prog_detach(struct tcb *const tcp, const kernel_ulong_t addr,
253 : : unsigned int size)
254 : : {
255 : 20 : return bpf_prog_attach_detach(tcp, addr, size, false);
256 : : }
257 : :
258 : 225 : SYS_FUNC(bpf)
259 : : {
260 : 225 : const unsigned int cmd = tcp->u_arg[0];
261 : 225 : const kernel_ulong_t addr = tcp->u_arg[1];
262 : 225 : const unsigned int size = tcp->u_arg[2];
263 : 225 : int rc = RVAL_DECODED;
264 : :
265 [ + + ]: 225 : if (entering(tcp)) {
266 : 215 : printxval(bpf_commands, cmd, "BPF_???");
267 : 215 : tprints(", ");
268 : : }
269 : :
270 [ + + + + : 225 : switch (cmd) {
+ + + + +
+ + ]
271 : : case BPF_MAP_CREATE:
272 : 20 : rc = bpf_map_create(tcp, addr, size);
273 : 20 : break;
274 : : case BPF_MAP_LOOKUP_ELEM:
275 : 25 : rc = bpf_map_io(tcp, addr, size, "value");
276 : 25 : break;
277 : : case BPF_MAP_UPDATE_ELEM:
278 : 20 : bpf_map_update_elem(tcp, addr, size);
279 : 20 : break;
280 : : case BPF_MAP_DELETE_ELEM:
281 : 20 : bpf_map_delete_elem(tcp, addr, size);
282 : 20 : break;
283 : : case BPF_MAP_GET_NEXT_KEY:
284 : 25 : rc = bpf_map_io(tcp, addr, size, "next_key");
285 : 25 : break;
286 : : case BPF_PROG_LOAD:
287 : 20 : rc = bpf_prog_load(tcp, addr, size);
288 : 20 : break;
289 : : case BPF_OBJ_PIN:
290 : 20 : rc = bpf_obj_manage(tcp, addr, size);
291 : 20 : break;
292 : : case BPF_OBJ_GET:
293 : 20 : rc = bpf_obj_manage(tcp, addr, size);
294 : 20 : break;
295 : : case BPF_PROG_ATTACH:
296 : 20 : rc = bpf_prog_attach(tcp, addr, size);
297 : 20 : break;
298 : : case BPF_PROG_DETACH:
299 : 20 : rc = bpf_prog_detach(tcp, addr, size);
300 : 20 : break;
301 : : default:
302 : 15 : printaddr(addr);
303 : 15 : break;
304 : : }
305 : :
306 [ + + ]: 225 : if (rc & RVAL_DECODED)
307 : 215 : tprintf(", %u", size);
308 : :
309 : 225 : return rc;
310 : : }
|