2 * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@altlinux.org>
3 * Copyright (c) 2017 Quentin Monnet <quentin.monnet@6wind.com>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
30 #include "print_fields.h"
32 #ifdef HAVE_LINUX_BPF_H
33 # include <linux/bpf.h>
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"
45 #define DECL_BPF_CMD_DECODER(bpf_cmd_decoder) \
47 bpf_cmd_decoder(struct tcb *const tcp, \
48 const kernel_ulong_t addr, \
49 const unsigned int size, \
51 /* End of DECL_BPF_CMD_DECODER definition. */
53 #define DEF_BPF_CMD_DECODER(bpf_cmd) \
54 static DECL_BPF_CMD_DECODER(decode_ ## bpf_cmd)
56 #define BPF_CMD_ENTRY(bpf_cmd) \
57 [bpf_cmd] = decode_ ## bpf_cmd
59 typedef DECL_BPF_CMD_DECODER((*bpf_cmd_decoder_t));
62 decode_attr_extra_data(struct tcb *const tcp,
65 const size_t attr_size)
67 if (size <= attr_size)
74 for (i = 0; i < size; ++i) {
80 print_quoted_string(data, size,
89 DEF_BPF_CMD_DECODER(BPF_MAP_CREATE)
92 uint32_t map_type, key_size, value_size, max_entries,
93 map_flags, inner_map_fd, numa_node;
95 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
97 memcpy(&attr, data, len);
99 PRINT_FIELD_XVAL("{", attr, map_type, bpf_map_types,
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));
111 return RVAL_DECODED | RVAL_FD;
114 DEF_BPF_CMD_DECODER(BPF_MAP_LOOKUP_ELEM)
116 struct bpf_io_elem_struct {
118 uint64_t ATTRIBUTE_ALIGNED(8) key, value;
121 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
123 memcpy(&attr, data, len);
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));
134 DEF_BPF_CMD_DECODER(BPF_MAP_UPDATE_ELEM)
138 uint64_t ATTRIBUTE_ALIGNED(8) key;
139 uint64_t ATTRIBUTE_ALIGNED(8) value;
142 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
144 memcpy(&attr, data, len);
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,
151 decode_attr_extra_data(tcp, data, size, sizeof(attr));
157 DEF_BPF_CMD_DECODER(BPF_MAP_DELETE_ELEM)
161 uint64_t ATTRIBUTE_ALIGNED(8) key;
163 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
165 memcpy(&attr, data, len);
167 PRINT_FIELD_FD("{", attr, map_fd, tcp);
168 PRINT_FIELD_X(", ", attr, key);
169 decode_attr_extra_data(tcp, data, size, sizeof(attr));
175 DEF_BPF_CMD_DECODER(BPF_MAP_GET_NEXT_KEY)
177 struct bpf_io_elem_struct {
179 uint64_t ATTRIBUTE_ALIGNED(8) key, next_key;
182 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
184 memcpy(&attr, data, len);
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));
195 DEF_BPF_CMD_DECODER(BPF_PROG_LOAD)
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;
204 const unsigned int len = MIN(size, sizeof(attr));
206 memcpy(&attr, data, len);
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);
214 /* log_* fields were added in Linux commit v3.18-rc1~52^2~1^2~4. */
215 if (len <= offsetof(struct bpf_prog_load, log_level))
216 goto bpf_prog_load_end;
217 PRINT_FIELD_U(", ", attr, log_level);
218 PRINT_FIELD_U(", ", attr, log_size);
219 PRINT_FIELD_X(", ", attr, log_buf);
221 /* kern_version field was added in Linux commit v4.1-rc1~84^2~50. */
222 if (len <= offsetof(struct bpf_prog_load, kern_version))
223 goto bpf_prog_load_end;
224 tprintf(", kern_version=KERNEL_VERSION(%u, %u, %u)",
225 attr.kern_version >> 16,
226 (attr.kern_version >> 8) & 0xFF,
227 attr.kern_version & 0xFF);
229 /* prog_flags field was added in Linux commit v4.12-rc2~34^2~29^2~2. */
230 if (len <= offsetof(struct bpf_prog_load, prog_flags))
231 goto bpf_prog_load_end;
232 PRINT_FIELD_FLAGS(", ", attr, prog_flags, bpf_prog_flags, "BPF_F_???");
234 decode_attr_extra_data(tcp, data, size, sizeof(attr));
239 return RVAL_DECODED | RVAL_FD;
242 DEF_BPF_CMD_DECODER(BPF_OBJ_PIN)
245 uint64_t ATTRIBUTE_ALIGNED(8) pathname;
248 const size_t attr_size =
249 offsetofend(struct bpf_obj, bpf_fd);
250 const unsigned int len = size < attr_size ? size : attr_size;
252 memcpy(&attr, data, len);
254 PRINT_FIELD_PATH("{", attr, pathname, tcp);
255 PRINT_FIELD_FD(", ", attr, bpf_fd, tcp);
256 decode_attr_extra_data(tcp, data, size, attr_size);
259 return RVAL_DECODED | RVAL_FD;
262 #define decode_BPF_OBJ_GET decode_BPF_OBJ_PIN
264 DEF_BPF_CMD_DECODER(BPF_PROG_ATTACH)
267 uint32_t target_fd, attach_bpf_fd, attach_type, attach_flags;
269 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
271 memcpy(&attr, data, len);
273 PRINT_FIELD_FD("{", attr, target_fd, tcp);
274 PRINT_FIELD_FD(", ", attr, attach_bpf_fd, tcp);
275 PRINT_FIELD_XVAL(", ", attr, attach_type, bpf_attach_type, "BPF_???");
276 PRINT_FIELD_FLAGS(", ", attr, attach_flags, bpf_attach_flags,
278 decode_attr_extra_data(tcp, data, size, sizeof(attr));
284 DEF_BPF_CMD_DECODER(BPF_PROG_DETACH)
287 uint32_t target_fd, dummy, attach_type;
289 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
291 memcpy(&attr, data, len);
293 PRINT_FIELD_FD("{", attr, target_fd, tcp);
294 PRINT_FIELD_XVAL(", ", attr, attach_type, bpf_attach_type, "BPF_???");
295 decode_attr_extra_data(tcp, data, size, sizeof(attr));
301 DEF_BPF_CMD_DECODER(BPF_PROG_TEST_RUN)
304 uint32_t prog_fd, retval, data_size_in, data_size_out;
305 uint64_t ATTRIBUTE_ALIGNED(8) data_in, data_out;
306 uint32_t repeat, duration;
308 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
310 memcpy(&attr, data, len);
312 PRINT_FIELD_FD("{test={", attr, prog_fd, tcp);
313 PRINT_FIELD_U(", ", attr, retval);
314 PRINT_FIELD_U(", ", attr, data_size_in);
315 PRINT_FIELD_U(", ", attr, data_size_out);
316 PRINT_FIELD_X(", ", attr, data_in);
317 PRINT_FIELD_X(", ", attr, data_out);
318 PRINT_FIELD_U(", ", attr, repeat);
319 PRINT_FIELD_U(", ", attr, duration);
321 decode_attr_extra_data(tcp, data, size, sizeof(attr));
327 DEF_BPF_CMD_DECODER(BPF_PROG_GET_NEXT_ID)
330 uint32_t start_id, next_id;
332 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
334 memcpy(&attr, data, len);
336 PRINT_FIELD_U("{", attr, start_id);
337 PRINT_FIELD_U(", ", attr, next_id);
338 decode_attr_extra_data(tcp, data, size, sizeof(attr));
344 #define decode_BPF_MAP_GET_NEXT_ID decode_BPF_PROG_GET_NEXT_ID
346 DEF_BPF_CMD_DECODER(BPF_PROG_GET_FD_BY_ID)
349 uint32_t prog_id, next_id;
351 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
353 memcpy(&attr, data, len);
355 PRINT_FIELD_U("{", attr, prog_id);
356 PRINT_FIELD_U(", ", attr, next_id);
357 decode_attr_extra_data(tcp, data, size, sizeof(attr));
363 DEF_BPF_CMD_DECODER(BPF_MAP_GET_FD_BY_ID)
366 uint32_t map_id, next_id;
368 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
370 memcpy(&attr, data, len);
372 PRINT_FIELD_U("{", attr, map_id);
373 PRINT_FIELD_U(", ", attr, next_id);
374 decode_attr_extra_data(tcp, data, size, sizeof(attr));
380 DEF_BPF_CMD_DECODER(BPF_OBJ_GET_INFO_BY_FD)
383 uint32_t bpf_fd, info_len;
384 uint64_t ATTRIBUTE_ALIGNED(8) info;
386 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
388 memcpy(&attr, data, len);
390 PRINT_FIELD_FD("{info={", attr, bpf_fd, tcp);
391 PRINT_FIELD_U(", ", attr, info_len);
392 PRINT_FIELD_X(", ", attr, info);
394 decode_attr_extra_data(tcp, data, size, sizeof(attr));
397 return RVAL_DECODED | RVAL_FD;
402 static const bpf_cmd_decoder_t bpf_cmd_decoders[] = {
403 BPF_CMD_ENTRY(BPF_MAP_CREATE),
404 BPF_CMD_ENTRY(BPF_MAP_LOOKUP_ELEM),
405 BPF_CMD_ENTRY(BPF_MAP_UPDATE_ELEM),
406 BPF_CMD_ENTRY(BPF_MAP_DELETE_ELEM),
407 BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_KEY),
408 BPF_CMD_ENTRY(BPF_PROG_LOAD),
409 BPF_CMD_ENTRY(BPF_OBJ_PIN),
410 BPF_CMD_ENTRY(BPF_OBJ_GET),
411 BPF_CMD_ENTRY(BPF_PROG_ATTACH),
412 BPF_CMD_ENTRY(BPF_PROG_DETACH),
413 BPF_CMD_ENTRY(BPF_PROG_TEST_RUN),
414 BPF_CMD_ENTRY(BPF_PROG_GET_NEXT_ID),
415 BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_ID),
416 BPF_CMD_ENTRY(BPF_PROG_GET_FD_BY_ID),
417 BPF_CMD_ENTRY(BPF_MAP_GET_FD_BY_ID),
418 BPF_CMD_ENTRY(BPF_OBJ_GET_INFO_BY_FD),
421 const unsigned int cmd = tcp->u_arg[0];
422 const kernel_ulong_t addr = tcp->u_arg[1];
423 const unsigned int size = tcp->u_arg[2];
430 buf = xmalloc(get_pagesize());
432 printxval(bpf_commands, cmd, "BPF_???");
436 && size <= get_pagesize()
437 && cmd < ARRAY_SIZE(bpf_cmd_decoders)
438 && bpf_cmd_decoders[cmd]) {
439 rc = umoven_or_printaddr(tcp, addr, size, buf)
441 : bpf_cmd_decoders[cmd](tcp, addr, size, buf);
447 rc = bpf_cmd_decoders[cmd](tcp, addr, size, NULL) | RVAL_DECODED;
450 if (rc & RVAL_DECODED)
451 tprintf(", %u", size);