1 /*
2 * Copyright (c) 2015-2017 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 #include "print_fields.h"
31
32 #ifdef HAVE_LINUX_BPF_H
33 # include <linux/bpf.h>
34 #endif
35
36 #include "xlat/bpf_commands.h"
37 #include "xlat/bpf_map_types.h"
38 #include "xlat/bpf_map_flags.h"
39 #include "xlat/bpf_prog_types.h"
40 #include "xlat/bpf_prog_flags.h"
41 #include "xlat/bpf_map_update_elem_flags.h"
42 #include "xlat/bpf_attach_type.h"
43 #include "xlat/bpf_attach_flags.h"
44
45 #define DECL_BPF_CMD_DECODER(bpf_cmd_decoder) \
46 int \
47 bpf_cmd_decoder(struct tcb *const tcp, \
48 const kernel_ulong_t addr, \
49 const unsigned int size, \
50 void *const data) \
51 /* End of DECL_BPF_CMD_DECODER definition. */
52
53 #define DEF_BPF_CMD_DECODER(bpf_cmd) \
54 static DECL_BPF_CMD_DECODER(decode_ ## bpf_cmd)
55
56 #define BPF_CMD_ENTRY(bpf_cmd) \
57 [bpf_cmd] = decode_ ## bpf_cmd
58
59 typedef DECL_BPF_CMD_DECODER((*bpf_cmd_decoder_t));
60
61 static int
decode_attr_extra_data(struct tcb * const tcp,const char * data,unsigned int size,const size_t attr_size)62 decode_attr_extra_data(struct tcb *const tcp,
63 const char *data,
64 unsigned int size,
65 const size_t attr_size)
66 {
67 if (size <= attr_size)
68 return 0;
69
70 data += attr_size;
71 size -= attr_size;
72
73 unsigned int i;
74 for (i = 0; i < size; ++i) {
75 if (data[i]) {
76 tprints(", ");
77 if (abbrev(tcp))
78 tprints("...");
79 else
80 print_quoted_string(data, size,
81 QUOTE_FORCE_HEX);
82 return RVAL_DECODED;
83 }
84 }
85
86 return 0;
87 }
88
DEF_BPF_CMD_DECODER(BPF_MAP_CREATE)89 DEF_BPF_CMD_DECODER(BPF_MAP_CREATE)
90 {
91 struct {
92 uint32_t map_type, key_size, value_size, max_entries,
93 map_flags, inner_map_fd, numa_node;
94 } attr = {};
95 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
96
97 memcpy(&attr, data, len);
98
99 PRINT_FIELD_XVAL("{", attr, map_type, bpf_map_types,
100 "BPF_MAP_TYPE_???");
101 PRINT_FIELD_U(", ", attr, key_size);
102 PRINT_FIELD_U(", ", attr, value_size);
103 PRINT_FIELD_U(", ", attr, max_entries);
104 PRINT_FIELD_FLAGS(", ", attr, map_flags, bpf_map_flags, "BPF_F_???");
105 PRINT_FIELD_FD(", ", attr, inner_map_fd, tcp);
106 if (attr.map_flags & BPF_F_NUMA_NODE)
107 PRINT_FIELD_U(", ", attr, numa_node);
108 decode_attr_extra_data(tcp, data, size, sizeof(attr));
109 tprints("}");
110
111 return RVAL_DECODED | RVAL_FD;
112 }
113
DEF_BPF_CMD_DECODER(BPF_MAP_LOOKUP_ELEM)114 DEF_BPF_CMD_DECODER(BPF_MAP_LOOKUP_ELEM)
115 {
116 struct bpf_io_elem_struct {
117 uint32_t map_fd;
118 uint64_t ATTRIBUTE_ALIGNED(8) key, value;
119 } attr = {};
120
121 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
122
123 memcpy(&attr, data, len);
124
125 PRINT_FIELD_FD("{", attr, map_fd, tcp);
126 PRINT_FIELD_X(", ", attr, key);
127 PRINT_FIELD_X(", ", attr, value);
128 decode_attr_extra_data(tcp, data, size, sizeof(attr));
129 tprints("}");
130
131 return RVAL_DECODED;
132 }
133
DEF_BPF_CMD_DECODER(BPF_MAP_UPDATE_ELEM)134 DEF_BPF_CMD_DECODER(BPF_MAP_UPDATE_ELEM)
135 {
136 struct {
137 uint32_t map_fd;
138 uint64_t ATTRIBUTE_ALIGNED(8) key;
139 uint64_t ATTRIBUTE_ALIGNED(8) value;
140 uint64_t flags;
141 } attr = {};
142 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
143
144 memcpy(&attr, data, len);
145
146 PRINT_FIELD_FD("{", attr, map_fd, tcp);
147 PRINT_FIELD_X(", ", attr, key);
148 PRINT_FIELD_X(", ", attr, value);
149 PRINT_FIELD_XVAL(", ", attr, flags, bpf_map_update_elem_flags,
150 "BPF_???");
151 decode_attr_extra_data(tcp, data, size, sizeof(attr));
152 tprints("}");
153
154 return RVAL_DECODED;
155 }
156
DEF_BPF_CMD_DECODER(BPF_MAP_DELETE_ELEM)157 DEF_BPF_CMD_DECODER(BPF_MAP_DELETE_ELEM)
158 {
159 struct {
160 uint32_t map_fd;
161 uint64_t ATTRIBUTE_ALIGNED(8) key;
162 } attr = {};
163 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
164
165 memcpy(&attr, data, len);
166
167 PRINT_FIELD_FD("{", attr, map_fd, tcp);
168 PRINT_FIELD_X(", ", attr, key);
169 decode_attr_extra_data(tcp, data, size, sizeof(attr));
170 tprints("}");
171
172 return RVAL_DECODED;
173 }
174
DEF_BPF_CMD_DECODER(BPF_MAP_GET_NEXT_KEY)175 DEF_BPF_CMD_DECODER(BPF_MAP_GET_NEXT_KEY)
176 {
177 struct bpf_io_elem_struct {
178 uint32_t map_fd;
179 uint64_t ATTRIBUTE_ALIGNED(8) key, next_key;
180 } attr = {};
181
182 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
183
184 memcpy(&attr, data, len);
185
186 PRINT_FIELD_FD("{", attr, map_fd, tcp);
187 PRINT_FIELD_X(", ", attr, key);
188 PRINT_FIELD_X(", ", attr, next_key);
189 decode_attr_extra_data(tcp, data, size, sizeof(attr));
190 tprints("}");
191
192 return RVAL_DECODED;
193 }
194
DEF_BPF_CMD_DECODER(BPF_PROG_LOAD)195 DEF_BPF_CMD_DECODER(BPF_PROG_LOAD)
196 {
197 struct bpf_prog_load {
198 uint32_t prog_type, insn_cnt;
199 uint64_t ATTRIBUTE_ALIGNED(8) insns, license;
200 uint32_t log_level, log_size;
201 uint64_t ATTRIBUTE_ALIGNED(8) log_buf;
202 uint32_t kern_version, prog_flags;
203 } attr = {};
204 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
205
206 memcpy(&attr, data, len);
207
208 PRINT_FIELD_XVAL("{", attr, prog_type, bpf_prog_types,
209 "BPF_PROG_TYPE_???");
210 PRINT_FIELD_U(", ", attr, insn_cnt);
211 PRINT_FIELD_X(", ", attr, insns);
212 PRINT_FIELD_STR(", ", attr, license, tcp);
213 PRINT_FIELD_U(", ", attr, log_level);
214 PRINT_FIELD_U(", ", attr, log_size);
215 PRINT_FIELD_X(", ", attr, log_buf);
216 PRINT_FIELD_U(", ", attr, kern_version);
217 PRINT_FIELD_FLAGS(", ", attr, prog_flags, bpf_prog_flags, "BPF_F_???");
218 decode_attr_extra_data(tcp, data, size, sizeof(attr));
219 tprints("}");
220
221 return RVAL_DECODED | RVAL_FD;
222 }
223
DEF_BPF_CMD_DECODER(BPF_OBJ_PIN)224 DEF_BPF_CMD_DECODER(BPF_OBJ_PIN)
225 {
226 struct bpf_obj {
227 uint64_t ATTRIBUTE_ALIGNED(8) pathname;
228 uint32_t bpf_fd;
229 } attr = {};
230 const size_t attr_size =
231 offsetofend(struct bpf_obj, bpf_fd);
232 const unsigned int len = size < attr_size ? size : attr_size;
233
234 memcpy(&attr, data, len);
235
236 PRINT_FIELD_PATH("{", attr, pathname, tcp);
237 PRINT_FIELD_FD(", ", attr, bpf_fd, tcp);
238 decode_attr_extra_data(tcp, data, size, attr_size);
239 tprints("}");
240
241 return RVAL_DECODED | RVAL_FD;
242 }
243
244 #define decode_BPF_OBJ_GET decode_BPF_OBJ_PIN
245
DEF_BPF_CMD_DECODER(BPF_PROG_ATTACH)246 DEF_BPF_CMD_DECODER(BPF_PROG_ATTACH)
247 {
248 struct {
249 uint32_t target_fd, attach_bpf_fd, attach_type, attach_flags;
250 } attr = {};
251 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
252
253 memcpy(&attr, data, len);
254
255 PRINT_FIELD_FD("{", attr, target_fd, tcp);
256 PRINT_FIELD_FD(", ", attr, attach_bpf_fd, tcp);
257 PRINT_FIELD_XVAL(", ", attr, attach_type, bpf_attach_type, "BPF_???");
258 PRINT_FIELD_FLAGS(", ", attr, attach_flags, bpf_attach_flags,
259 "BPF_F_???");
260 decode_attr_extra_data(tcp, data, size, sizeof(attr));
261 tprints("}");
262
263 return RVAL_DECODED;
264 }
265
DEF_BPF_CMD_DECODER(BPF_PROG_DETACH)266 DEF_BPF_CMD_DECODER(BPF_PROG_DETACH)
267 {
268 struct {
269 uint32_t target_fd, dummy, attach_type;
270 } attr = {};
271 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
272
273 memcpy(&attr, data, len);
274
275 PRINT_FIELD_FD("{", attr, target_fd, tcp);
276 PRINT_FIELD_XVAL(", ", attr, attach_type, bpf_attach_type, "BPF_???");
277 decode_attr_extra_data(tcp, data, size, sizeof(attr));
278 tprints("}");
279
280 return RVAL_DECODED;
281 }
282
DEF_BPF_CMD_DECODER(BPF_PROG_TEST_RUN)283 DEF_BPF_CMD_DECODER(BPF_PROG_TEST_RUN)
284 {
285 struct {
286 uint32_t prog_fd, retval, data_size_in, data_size_out;
287 uint64_t ATTRIBUTE_ALIGNED(8) data_in, data_out;
288 uint32_t repeat, duration;
289 } attr = {};
290 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
291
292 memcpy(&attr, data, len);
293
294 PRINT_FIELD_FD("{test={", attr, prog_fd, tcp);
295 PRINT_FIELD_U(", ", attr, retval);
296 PRINT_FIELD_U(", ", attr, data_size_in);
297 PRINT_FIELD_U(", ", attr, data_size_out);
298 PRINT_FIELD_X(", ", attr, data_in);
299 PRINT_FIELD_X(", ", attr, data_out);
300 PRINT_FIELD_U(", ", attr, repeat);
301 PRINT_FIELD_U(", ", attr, duration);
302 tprints("}");
303 decode_attr_extra_data(tcp, data, size, sizeof(attr));
304 tprints("}");
305
306 return RVAL_DECODED;
307 }
308
DEF_BPF_CMD_DECODER(BPF_PROG_GET_NEXT_ID)309 DEF_BPF_CMD_DECODER(BPF_PROG_GET_NEXT_ID)
310 {
311 struct {
312 uint32_t start_id, next_id;
313 } attr = {};
314 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
315
316 memcpy(&attr, data, len);
317
318 PRINT_FIELD_U("{", attr, start_id);
319 PRINT_FIELD_U(", ", attr, next_id);
320 decode_attr_extra_data(tcp, data, size, sizeof(attr));
321 tprints("}");
322
323 return RVAL_DECODED;
324 }
325
326 #define decode_BPF_MAP_GET_NEXT_ID decode_BPF_PROG_GET_NEXT_ID
327
DEF_BPF_CMD_DECODER(BPF_PROG_GET_FD_BY_ID)328 DEF_BPF_CMD_DECODER(BPF_PROG_GET_FD_BY_ID)
329 {
330 struct {
331 uint32_t prog_id, next_id;
332 } attr = {};
333 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
334
335 memcpy(&attr, data, len);
336
337 PRINT_FIELD_U("{", attr, prog_id);
338 PRINT_FIELD_U(", ", attr, next_id);
339 decode_attr_extra_data(tcp, data, size, sizeof(attr));
340 tprints("}");
341
342 return RVAL_DECODED;
343 }
344
DEF_BPF_CMD_DECODER(BPF_MAP_GET_FD_BY_ID)345 DEF_BPF_CMD_DECODER(BPF_MAP_GET_FD_BY_ID)
346 {
347 struct {
348 uint32_t map_id, next_id;
349 } attr = {};
350 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
351
352 memcpy(&attr, data, len);
353
354 PRINT_FIELD_U("{", attr, map_id);
355 PRINT_FIELD_U(", ", attr, next_id);
356 decode_attr_extra_data(tcp, data, size, sizeof(attr));
357 tprints("}");
358
359 return RVAL_DECODED;
360 }
361
DEF_BPF_CMD_DECODER(BPF_OBJ_GET_INFO_BY_FD)362 DEF_BPF_CMD_DECODER(BPF_OBJ_GET_INFO_BY_FD)
363 {
364 struct {
365 uint32_t bpf_fd, info_len;
366 uint64_t ATTRIBUTE_ALIGNED(8) info;
367 } attr = {};
368 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
369
370 memcpy(&attr, data, len);
371
372 PRINT_FIELD_FD("{info={", attr, bpf_fd, tcp);
373 PRINT_FIELD_U(", ", attr, info_len);
374 PRINT_FIELD_X(", ", attr, info);
375 tprints("}");
376 decode_attr_extra_data(tcp, data, size, sizeof(attr));
377 tprints("}");
378
379 return RVAL_DECODED | RVAL_FD;
380 }
381
SYS_FUNC(bpf)382 SYS_FUNC(bpf)
383 {
384 static const bpf_cmd_decoder_t bpf_cmd_decoders[] = {
385 BPF_CMD_ENTRY(BPF_MAP_CREATE),
386 BPF_CMD_ENTRY(BPF_MAP_LOOKUP_ELEM),
387 BPF_CMD_ENTRY(BPF_MAP_UPDATE_ELEM),
388 BPF_CMD_ENTRY(BPF_MAP_DELETE_ELEM),
389 BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_KEY),
390 BPF_CMD_ENTRY(BPF_PROG_LOAD),
391 BPF_CMD_ENTRY(BPF_OBJ_PIN),
392 BPF_CMD_ENTRY(BPF_OBJ_GET),
393 BPF_CMD_ENTRY(BPF_PROG_ATTACH),
394 BPF_CMD_ENTRY(BPF_PROG_DETACH),
395 BPF_CMD_ENTRY(BPF_PROG_TEST_RUN),
396 BPF_CMD_ENTRY(BPF_PROG_GET_NEXT_ID),
397 BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_ID),
398 BPF_CMD_ENTRY(BPF_PROG_GET_FD_BY_ID),
399 BPF_CMD_ENTRY(BPF_MAP_GET_FD_BY_ID),
400 BPF_CMD_ENTRY(BPF_OBJ_GET_INFO_BY_FD),
401 };
402
403 const unsigned int cmd = tcp->u_arg[0];
404 const kernel_ulong_t addr = tcp->u_arg[1];
405 const unsigned int size = tcp->u_arg[2];
406 int rc;
407
408 if (entering(tcp)) {
409 static size_t page_size;
410 static char *buf;
411
412 if (!buf) {
413 page_size = get_pagesize();
414 buf = xmalloc(page_size);
415 }
416
417 printxval(bpf_commands, cmd, "BPF_???");
418 tprints(", ");
419
420 if (size > 0
421 && size <= get_pagesize()
422 && cmd < ARRAY_SIZE(bpf_cmd_decoders)
423 && bpf_cmd_decoders[cmd]) {
424 rc = umoven_or_printaddr(tcp, addr, size, buf)
425 ? RVAL_DECODED
426 : bpf_cmd_decoders[cmd](tcp, addr, size, buf);
427 } else {
428 printaddr(addr);
429 rc = RVAL_DECODED;
430 }
431 } else {
432 rc = bpf_cmd_decoders[cmd](tcp, addr, size, NULL) | RVAL_DECODED;
433 }
434
435 if (rc & RVAL_DECODED)
436 tprintf(", %u", size);
437
438 return rc;
439 }
440