1 /* 2 * Copyright (c) 2015-2017 Dmitry V. Levin <ldv (at) altlinux.org> 3 * Copyright (c) 2017 Quentin Monnet <quentin.monnet (at) 6wind.com> 4 * Copyright (c) 2015-2018 The strace developers. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "defs.h" 31 #include "print_fields.h" 32 33 #ifdef HAVE_LINUX_BPF_H 34 # include <linux/bpf.h> 35 #endif 36 #include <linux/filter.h> 37 38 #include "bpf_attr.h" 39 40 #include "xlat/bpf_commands.h" 41 #include "xlat/bpf_file_mode_flags.h" 42 #include "xlat/bpf_map_types.h" 43 #include "xlat/bpf_map_flags.h" 44 #include "xlat/bpf_prog_types.h" 45 #include "xlat/bpf_prog_flags.h" 46 #include "xlat/bpf_map_update_elem_flags.h" 47 #include "xlat/bpf_attach_type.h" 48 #include "xlat/bpf_attach_flags.h" 49 #include "xlat/bpf_query_flags.h" 50 #include "xlat/ebpf_regs.h" 51 #include "xlat/numa_node.h" 52 53 #define DECL_BPF_CMD_DECODER(bpf_cmd_decoder) \ 54 int \ 55 bpf_cmd_decoder(struct tcb *const tcp, \ 56 const kernel_ulong_t addr, \ 57 const unsigned int size, \ 58 void *const data) \ 59 /* End of DECL_BPF_CMD_DECODER definition. */ 60 61 #define BEGIN_BPF_CMD_DECODER(bpf_cmd) \ 62 static DECL_BPF_CMD_DECODER(decode_ ## bpf_cmd) \ 63 { \ 64 struct bpf_cmd ## _struct attr = {}; \ 65 const size_t attr_size = bpf_cmd ## _struct_size; \ 66 const unsigned int len = MIN(size, attr_size); \ 67 memcpy(&attr, data, len); \ 68 do { \ 69 /* End of BEGIN_BPF_CMD_DECODER definition. */ 70 71 #define END_BPF_CMD_DECODER(rval) \ 72 decode_attr_extra_data(tcp, data, size, attr_size); \ 73 } while (0); \ 74 tprints("}"); \ 75 return (rval); \ 76 } \ 77 /* End of END_BPF_CMD_DECODER definition. */ 78 79 #define BPF_CMD_ENTRY(bpf_cmd) \ 80 [bpf_cmd] = decode_ ## bpf_cmd 81 82 typedef DECL_BPF_CMD_DECODER((*bpf_cmd_decoder_t)); 83 84 /* 85 * A note about bpf syscall decoder: it doesn't perform any size sanity checks, 86 * so even if it leads to partial copying of one of the fields, the command 87 * handler will still use the (partially-copied-from-userspace, partially 88 * zeroed) field value. That's why we stop decoding and check for known sizes 89 * that correspond to released versions of the structure used by the specific 90 * command - it looks like the most sensible way to parse this insanity. 91 */ 92 93 static int 94 decode_attr_extra_data(struct tcb *const tcp, 95 const char *data, 96 unsigned int size, 97 const size_t attr_size) 98 { 99 if (size <= attr_size) 100 return 0; 101 102 data += attr_size; 103 size -= attr_size; 104 105 unsigned int i; 106 for (i = 0; i < size; ++i) { 107 if (data[i]) { 108 tprints(", "); 109 if (abbrev(tcp)) { 110 tprints("..."); 111 } else { 112 tprintf("/* bytes %zu..%zu */ ", 113 attr_size, attr_size + size - 1); 114 print_quoted_string(data, size, 115 QUOTE_FORCE_HEX); 116 } 117 return RVAL_DECODED; 118 } 119 } 120 121 return 0; 122 } 123 124 struct ebpf_insn { 125 uint8_t code; 126 uint8_t dst_reg:4; 127 uint8_t src_reg:4; 128 int16_t off; 129 int32_t imm; 130 }; 131 132 struct ebpf_insns_data { 133 unsigned int count; 134 }; 135 136 static bool 137 print_ebpf_insn(struct tcb * const tcp, void * const elem_buf, 138 const size_t elem_size, void * const data) 139 { 140 struct ebpf_insns_data *eid = data; 141 struct ebpf_insn *insn = elem_buf; 142 143 if (eid->count++ >= BPF_MAXINSNS) { 144 tprints("..."); 145 return false; 146 } 147 148 tprints("{code="); 149 print_bpf_filter_code(insn->code, true); 150 151 /* We can't use PRINT_FIELD_XVAL on bit fields */ 152 tprints(", dst_reg="); 153 printxval_index(ebpf_regs, insn->dst_reg, "BPF_REG_???"); 154 tprints(", src_reg="); 155 printxval_index(ebpf_regs, insn->src_reg, "BPF_REG_???"); 156 157 PRINT_FIELD_D(", ", *insn, off); 158 PRINT_FIELD_X(", ", *insn, imm); 159 tprints("}"); 160 161 return true; 162 } 163 164 static void 165 print_ebpf_prog(struct tcb *const tcp, const uint64_t addr, const uint32_t len) 166 { 167 print_big_u64_addr(addr); 168 if (abbrev(tcp)) { 169 printaddr(addr); 170 } else { 171 struct ebpf_insns_data eid = {}; 172 struct ebpf_insn insn; 173 174 print_array(tcp, addr, len, &insn, sizeof(insn), 175 tfetch_mem, print_ebpf_insn, &eid); 176 } 177 } 178 179 BEGIN_BPF_CMD_DECODER(BPF_MAP_CREATE) 180 { 181 PRINT_FIELD_XVAL_INDEX("{", attr, map_type, bpf_map_types, 182 "BPF_MAP_TYPE_???"); 183 PRINT_FIELD_U(", ", attr, key_size); 184 PRINT_FIELD_U(", ", attr, value_size); 185 PRINT_FIELD_U(", ", attr, max_entries); 186 187 /* map_flags field was added in Linux commit v4.6-rc1~91^2~108^2~6. */ 188 if (len <= offsetof(struct BPF_MAP_CREATE_struct, map_flags)) 189 break; 190 PRINT_FIELD_FLAGS(", ", attr, map_flags, bpf_map_flags, "BPF_F_???"); 191 192 /* 193 * inner_map_fd field was added in Linux commit 194 * v4.12-rc1~64^3~373^2~2. 195 */ 196 if (len <= offsetof(struct BPF_MAP_CREATE_struct, inner_map_fd)) 197 break; 198 PRINT_FIELD_FD(", ", attr, inner_map_fd, tcp); 199 200 /* numa_node field was added in Linux commit v4.14-rc1~130^2~196^2~1. */ 201 if (len <= offsetof(struct BPF_MAP_CREATE_struct, numa_node)) 202 break; 203 if (attr.map_flags & BPF_F_NUMA_NODE) { 204 /* 205 * Kernel uses the value of -1 as a designation for "no NUMA 206 * node specified", and even uses NUMA_NO_NODE constant; 207 * however, the constant definition is not a part of UAPI 208 * headers, thus we can't simply print this named constant 209 * instead of the value. Let's force verbose xlat style instead 210 * in order to provide the information for the user while 211 * not hampering the availability to derive the actual value 212 * without the access to the kernel headers. 213 */ 214 tprints(", numa_node="); 215 printxvals_ex(attr.numa_node, NULL, 216 XLAT_STYLE_FMT_U | XLAT_STYLE_VERBOSE, 217 numa_node, NULL); 218 } 219 220 /* map_name field was added in Linux commit v4.15-rc1~84^2~605^2~3. */ 221 if (len <= offsetof(struct BPF_MAP_CREATE_struct, map_name)) 222 break; 223 PRINT_FIELD_CSTRING_SZ(", ", attr, map_name, 224 MIN(sizeof(attr.map_name), 225 len - offsetof(struct BPF_MAP_CREATE_struct, 226 map_name))); 227 228 /* 229 * map_ifindex field was added in Linux commit 230 * v4.16-rc1~123^2~145^2~5^2~8. 231 */ 232 if (len <= offsetof(struct BPF_MAP_CREATE_struct, map_ifindex)) 233 break; 234 PRINT_FIELD_IFINDEX(", ", attr, map_ifindex); 235 } 236 END_BPF_CMD_DECODER(RVAL_DECODED | RVAL_FD) 237 238 BEGIN_BPF_CMD_DECODER(BPF_MAP_LOOKUP_ELEM) 239 { 240 PRINT_FIELD_FD("{", attr, map_fd, tcp); 241 PRINT_FIELD_ADDR64(", ", attr, key); 242 PRINT_FIELD_ADDR64(", ", attr, value); 243 } 244 END_BPF_CMD_DECODER(RVAL_DECODED) 245 246 BEGIN_BPF_CMD_DECODER(BPF_MAP_UPDATE_ELEM) 247 { 248 PRINT_FIELD_FD("{", attr, map_fd, tcp); 249 PRINT_FIELD_ADDR64(", ", attr, key); 250 PRINT_FIELD_ADDR64(", ", attr, value); 251 PRINT_FIELD_XVAL_INDEX(", ", attr, flags, bpf_map_update_elem_flags, 252 "BPF_???"); 253 } 254 END_BPF_CMD_DECODER(RVAL_DECODED) 255 256 BEGIN_BPF_CMD_DECODER(BPF_MAP_DELETE_ELEM) 257 { 258 PRINT_FIELD_FD("{", attr, map_fd, tcp); 259 PRINT_FIELD_ADDR64(", ", attr, key); 260 } 261 END_BPF_CMD_DECODER(RVAL_DECODED) 262 263 BEGIN_BPF_CMD_DECODER(BPF_MAP_GET_NEXT_KEY) 264 { 265 PRINT_FIELD_FD("{", attr, map_fd, tcp); 266 PRINT_FIELD_ADDR64(", ", attr, key); 267 PRINT_FIELD_ADDR64(", ", attr, next_key); 268 } 269 END_BPF_CMD_DECODER(RVAL_DECODED) 270 271 BEGIN_BPF_CMD_DECODER(BPF_PROG_LOAD) 272 { 273 PRINT_FIELD_XVAL_INDEX("{", attr, prog_type, bpf_prog_types, 274 "BPF_PROG_TYPE_???"); 275 PRINT_FIELD_U(", ", attr, insn_cnt); 276 tprints(", insns="); 277 print_ebpf_prog(tcp, attr.insns, attr.insn_cnt); 278 279 tprintf(", license="); 280 print_big_u64_addr(attr.license); 281 printstr(tcp, attr.license); 282 283 /* log_* fields were added in Linux commit v3.18-rc1~52^2~1^2~4. */ 284 if (len <= offsetof(struct BPF_PROG_LOAD_struct, log_level)) 285 break; 286 PRINT_FIELD_U(", ", attr, log_level); 287 PRINT_FIELD_U(", ", attr, log_size); 288 tprintf(", log_buf="); 289 print_big_u64_addr(attr.log_buf); 290 printstr_ex(tcp, attr.log_buf, attr.log_size, QUOTE_0_TERMINATED); 291 292 /* kern_version field was added in Linux commit v4.1-rc1~84^2~50. */ 293 if (len <= offsetof(struct BPF_PROG_LOAD_struct, kern_version)) 294 break; 295 tprintf(", kern_version=KERNEL_VERSION(%u, %u, %u)", 296 attr.kern_version >> 16, 297 (attr.kern_version >> 8) & 0xFF, 298 attr.kern_version & 0xFF); 299 300 /* prog_flags field was added in Linux commit v4.12-rc2~34^2~29^2~2. */ 301 if (len <= offsetof(struct BPF_PROG_LOAD_struct, prog_flags)) 302 break; 303 PRINT_FIELD_FLAGS(", ", attr, prog_flags, bpf_prog_flags, "BPF_F_???"); 304 305 /* prog_name field was added in Linux commit v4.15-rc1~84^2~605^2~4. */ 306 if (len <= offsetof(struct BPF_PROG_LOAD_struct, prog_name)) 307 break; 308 PRINT_FIELD_CSTRING_SZ(", ", attr, prog_name, 309 MIN(sizeof(attr.prog_name), 310 len - offsetof(struct BPF_PROG_LOAD_struct, 311 prog_name))); 312 313 /* 314 * prog_ifindex field was added as prog_target_ifindex in Linux commit 315 * v4.15-rc1~84^2~127^2~13 and renamed to its current name in 316 * v4.15-rc1~15^2~5^2~3^2~7. 317 */ 318 if (len <= offsetof(struct BPF_PROG_LOAD_struct, prog_ifindex)) 319 break; 320 PRINT_FIELD_IFINDEX(", ", attr, prog_ifindex); 321 322 /* 323 * expected_attach_type was added in Linux commit 324 * v4.17-rc1~148^2~19^2^2~8. 325 */ 326 if (len <= offsetof(struct BPF_PROG_LOAD_struct, expected_attach_type)) 327 break; 328 PRINT_FIELD_XVAL(", ", attr, expected_attach_type, bpf_attach_type, 329 "BPF_???"); 330 } 331 END_BPF_CMD_DECODER(RVAL_DECODED | RVAL_FD) 332 333 BEGIN_BPF_CMD_DECODER(BPF_OBJ_PIN) 334 { 335 tprintf("{pathname="); 336 print_big_u64_addr(attr.pathname); 337 printpath(tcp, attr.pathname); 338 339 PRINT_FIELD_FD(", ", attr, bpf_fd, tcp); 340 341 /* file_flags field was added in Linux v4.15-rc1~84^2~384^2~4 */ 342 if (len <= offsetof(struct BPF_OBJ_PIN_struct, file_flags)) 343 break; 344 PRINT_FIELD_FLAGS(", ", attr, file_flags, bpf_file_mode_flags, 345 "BPF_F_???"); 346 } 347 END_BPF_CMD_DECODER(RVAL_DECODED | RVAL_FD) 348 349 #define decode_BPF_OBJ_GET decode_BPF_OBJ_PIN 350 351 BEGIN_BPF_CMD_DECODER(BPF_PROG_ATTACH) 352 { 353 PRINT_FIELD_FD("{", attr, target_fd, tcp); 354 PRINT_FIELD_FD(", ", attr, attach_bpf_fd, tcp); 355 PRINT_FIELD_XVAL_INDEX(", ", attr, attach_type, bpf_attach_type, 356 "BPF_???"); 357 PRINT_FIELD_FLAGS(", ", attr, attach_flags, bpf_attach_flags, 358 "BPF_F_???"); 359 } 360 END_BPF_CMD_DECODER(RVAL_DECODED) 361 362 BEGIN_BPF_CMD_DECODER(BPF_PROG_DETACH) 363 { 364 PRINT_FIELD_FD("{", attr, target_fd, tcp); 365 PRINT_FIELD_XVAL_INDEX(", ", attr, attach_type, bpf_attach_type, 366 "BPF_???"); 367 } 368 END_BPF_CMD_DECODER(RVAL_DECODED) 369 370 BEGIN_BPF_CMD_DECODER(BPF_PROG_TEST_RUN) 371 { 372 PRINT_FIELD_FD("{test={", attr, prog_fd, tcp); 373 PRINT_FIELD_U(", ", attr, retval); 374 PRINT_FIELD_U(", ", attr, data_size_in); 375 PRINT_FIELD_U(", ", attr, data_size_out); 376 PRINT_FIELD_ADDR64(", ", attr, data_in); 377 PRINT_FIELD_ADDR64(", ", attr, data_out); 378 PRINT_FIELD_U(", ", attr, repeat); 379 PRINT_FIELD_U(", ", attr, duration); 380 tprints("}"); 381 } 382 END_BPF_CMD_DECODER(RVAL_DECODED) 383 384 BEGIN_BPF_CMD_DECODER(BPF_PROG_GET_NEXT_ID) 385 { 386 PRINT_FIELD_U("{", attr, start_id); 387 PRINT_FIELD_U(", ", attr, next_id); 388 389 /* open_flags field has been added in Linux v4.15-rc1~84^2~384^2~4 */ 390 if (len <= offsetof(struct BPF_PROG_GET_NEXT_ID_struct, open_flags)) 391 break; 392 PRINT_FIELD_FLAGS(", ", attr, open_flags, bpf_file_mode_flags, 393 "BPF_F_???"); 394 } 395 END_BPF_CMD_DECODER(RVAL_DECODED) 396 397 #define decode_BPF_MAP_GET_NEXT_ID decode_BPF_PROG_GET_NEXT_ID 398 399 BEGIN_BPF_CMD_DECODER(BPF_PROG_GET_FD_BY_ID) 400 { 401 PRINT_FIELD_U("{", attr, prog_id); 402 PRINT_FIELD_U(", ", attr, next_id); 403 404 /* open_flags field has been added in Linux v4.15-rc1~84^2~384^2~4 */ 405 if (len <= offsetof(struct BPF_PROG_GET_FD_BY_ID_struct, open_flags)) 406 break; 407 PRINT_FIELD_FLAGS(", ", attr, open_flags, bpf_file_mode_flags, 408 "BPF_F_???"); 409 } 410 END_BPF_CMD_DECODER(RVAL_DECODED) 411 412 BEGIN_BPF_CMD_DECODER(BPF_MAP_GET_FD_BY_ID) 413 { 414 PRINT_FIELD_U("{", attr, map_id); 415 PRINT_FIELD_U(", ", attr, next_id); 416 417 /* open_flags field has been added in Linux v4.15-rc1~84^2~384^2~4 */ 418 if (len <= offsetof(struct BPF_MAP_GET_FD_BY_ID_struct, open_flags)) 419 break; 420 PRINT_FIELD_FLAGS(", ", attr, open_flags, bpf_file_mode_flags, 421 "BPF_F_???"); 422 } 423 END_BPF_CMD_DECODER(RVAL_DECODED) 424 425 struct obj_get_info_saved; 426 typedef void (*print_bpf_obj_info_fn)(struct tcb *, 427 uint32_t bpf_fd, 428 const char *info_buf, 429 uint32_t size, 430 struct obj_get_info_saved *saved); 431 432 struct obj_get_info_saved { 433 print_bpf_obj_info_fn print_fn; 434 435 uint32_t info_len; 436 437 uint32_t jited_prog_len; 438 uint32_t xlated_prog_len; 439 uint32_t nr_map_ids; 440 }; 441 442 static void 443 print_bpf_map_info(struct tcb * const tcp, uint32_t bpf_fd, 444 const char *info_buf, uint32_t size, 445 struct obj_get_info_saved *saved) 446 { 447 if (entering(tcp)) 448 return; 449 450 struct bpf_map_info_struct info = { 0 }; 451 const unsigned int len = MIN(size, bpf_map_info_struct_size); 452 453 memcpy(&info, info_buf, len); 454 455 PRINT_FIELD_XVAL("{", info, type, bpf_map_types, "BPF_MAP_TYPE_???"); 456 PRINT_FIELD_U(", ", info, id); 457 PRINT_FIELD_U(", ", info, key_size); 458 PRINT_FIELD_U(", ", info, value_size); 459 PRINT_FIELD_U(", ", info, max_entries); 460 PRINT_FIELD_FLAGS(", ", info, map_flags, bpf_map_flags, "BPF_F_???"); 461 462 /* 463 * "name" field was introduced by Linux commit v4.15-rc1~84^2~605^2~3. 464 */ 465 if (len <= offsetof(struct bpf_map_info_struct, name)) 466 goto print_bpf_map_info_end; 467 PRINT_FIELD_CSTRING(", ", info, name); 468 469 /* 470 * ifindex, netns_dev, and netns_ino fields were introduced 471 * by Linux commit v4.16-rc1~123^2~109^2~5^2~4. 472 */ 473 if (len <= offsetof(struct bpf_map_info_struct, ifindex)) 474 goto print_bpf_map_info_end; 475 PRINT_FIELD_IFINDEX(", ", info, ifindex); 476 PRINT_FIELD_DEV(", ", info, netns_dev); 477 PRINT_FIELD_U(", ", info, netns_ino); 478 479 decode_attr_extra_data(tcp, info_buf, size, bpf_map_info_struct_size); 480 481 print_bpf_map_info_end: 482 tprints("}"); 483 } 484 485 static void 486 print_bpf_prog_info(struct tcb * const tcp, uint32_t bpf_fd, 487 const char *info_buf, uint32_t size, 488 struct obj_get_info_saved *saved) 489 { 490 struct bpf_prog_info_struct info = { 0 }; 491 const unsigned int len = MIN(size, bpf_prog_info_struct_size); 492 uint64_t map_id_buf; 493 494 memcpy(&info, info_buf, len); 495 496 if (entering(tcp)) { 497 saved->jited_prog_len = info.jited_prog_len; 498 saved->xlated_prog_len = info.xlated_prog_len; 499 saved->nr_map_ids = info.nr_map_ids; 500 501 return; 502 } 503 504 PRINT_FIELD_XVAL("{", info, type, bpf_prog_types, "BPF_PROG_TYPE_???"); 505 PRINT_FIELD_U(", ", info, id); 506 PRINT_FIELD_HEX_ARRAY(", ", info, tag); 507 508 tprints(", jited_prog_len="); 509 if (saved->jited_prog_len != info.jited_prog_len) 510 tprintf("%" PRIu32 " => ", saved->jited_prog_len); 511 tprintf("%" PRIu32, info.jited_prog_len); 512 513 tprints(", jited_prog_insns="); 514 print_big_u64_addr(info.jited_prog_insns); 515 printstr_ex(tcp, info.jited_prog_insns, info.jited_prog_len, 516 QUOTE_FORCE_HEX); 517 518 tprints(", xlated_prog_len="); 519 if (saved->xlated_prog_len != info.xlated_prog_len) 520 tprintf("%" PRIu32 " => ", saved->xlated_prog_len); 521 tprintf("%" PRIu32, info.xlated_prog_len); 522 523 tprints(", xlated_prog_insns="); 524 print_ebpf_prog(tcp, info.xlated_prog_insns, 525 MIN(saved->xlated_prog_len, info.xlated_prog_len) / 8); 526 527 /* 528 * load_time, created_by_uid, nr_map_ids, map_ids, and name fields 529 * were introduced by Linux commit v4.15-rc1~84^2~605^2~4. 530 */ 531 if (len <= offsetof(struct bpf_prog_info_struct, load_time)) 532 goto print_bpf_prog_info_end; 533 PRINT_FIELD_U(", ", info, load_time); 534 PRINT_FIELD_UID(", ", info, created_by_uid); 535 536 tprints(", nr_map_ids="); 537 if (saved->nr_map_ids != info.nr_map_ids) 538 tprintf("%" PRIu32 " => ", saved->nr_map_ids); 539 tprintf("%" PRIu32, info.nr_map_ids); 540 541 tprints(", map_ids="); 542 print_big_u64_addr(info.map_ids); 543 print_array(tcp, info.map_ids, MIN(saved->nr_map_ids, info.nr_map_ids), 544 &map_id_buf, sizeof(map_id_buf), 545 tfetch_mem, print_uint32_array_member, 0); 546 547 PRINT_FIELD_CSTRING(", ", info, name); 548 549 /* 550 * ifindex, netns_dev, and netns_ino fields were introduced 551 * by Linux commit v4.16-rc1~123^2~227^2~5^2~2. 552 */ 553 if (len <= offsetof(struct bpf_prog_info_struct, ifindex)) 554 goto print_bpf_prog_info_end; 555 PRINT_FIELD_IFINDEX(", ", info, ifindex); 556 PRINT_FIELD_DEV(", ", info, netns_dev); 557 PRINT_FIELD_U(", ", info, netns_ino); 558 559 decode_attr_extra_data(tcp, info_buf, size, bpf_prog_info_struct_size); 560 561 print_bpf_prog_info_end: 562 tprints("}"); 563 } 564 565 static const char * 566 fetch_bpf_obj_info(struct tcb * const tcp, uint64_t info, uint32_t size) 567 { 568 static char *info_buf; 569 570 if (!info_buf) 571 info_buf = xmalloc(get_pagesize()); 572 573 memset(info_buf, 0, get_pagesize()); 574 575 if (size > 0 && size <= get_pagesize() 576 && !umoven(tcp, info, size, info_buf)) 577 return info_buf; 578 579 return NULL; 580 } 581 582 static void 583 print_bpf_obj_info_addr(struct tcb * const tcp, uint64_t addr) 584 { 585 if (exiting(tcp)) 586 printaddr64(addr); 587 } 588 589 static void 590 print_bpf_obj_info(struct tcb * const tcp, uint32_t bpf_fd, uint64_t info, 591 uint32_t size, struct obj_get_info_saved *saved) 592 { 593 if (abbrev(tcp)) { 594 print_bpf_obj_info_addr(tcp, info); 595 return; 596 } 597 598 static struct { 599 const char *id; 600 print_bpf_obj_info_fn print_fn; 601 } obj_printers[] = { 602 { "anon_inode:bpf-map", print_bpf_map_info }, 603 { "anon_inode:bpf-prog", print_bpf_prog_info } 604 }; 605 606 if (entering(tcp)) { 607 char path[PATH_MAX + 1]; 608 609 if (getfdpath(tcp, bpf_fd, path, sizeof(path)) > 0) { 610 for (size_t i = 0; i < ARRAY_SIZE(obj_printers); ++i) { 611 if (!strcmp(path, obj_printers[i].id)) { 612 saved->print_fn = 613 obj_printers[i].print_fn; 614 break; 615 } 616 } 617 } 618 } 619 620 if (!saved || !saved->print_fn) { 621 print_bpf_obj_info_addr(tcp, info); 622 return; 623 } 624 625 const char *info_buf = fetch_bpf_obj_info(tcp, info, size); 626 627 if (info_buf) 628 saved->print_fn(tcp, bpf_fd, info_buf, size, saved); 629 else 630 print_bpf_obj_info_addr(tcp, info); 631 } 632 633 BEGIN_BPF_CMD_DECODER(BPF_OBJ_GET_INFO_BY_FD) 634 { 635 struct obj_get_info_saved *saved; 636 637 if (entering(tcp)) { 638 saved = xcalloc(1, sizeof(*saved)); 639 saved->info_len = attr.info_len; 640 set_tcb_priv_data(tcp, saved, free); 641 642 PRINT_FIELD_FD("{info={", attr, bpf_fd, tcp); 643 PRINT_FIELD_U(", ", attr, info_len); 644 } else { 645 saved = get_tcb_priv_data(tcp); 646 647 if (saved && (saved->info_len != attr.info_len)) 648 tprintf(" => %u", attr.info_len); 649 650 tprintf(", info="); 651 } 652 653 print_bpf_obj_info(tcp, attr.bpf_fd, attr.info, attr.info_len, saved); 654 655 if (entering(tcp)) 656 return 0; 657 658 tprints("}"); 659 } 660 END_BPF_CMD_DECODER(RVAL_DECODED) 661 662 BEGIN_BPF_CMD_DECODER(BPF_PROG_QUERY) 663 { 664 uint32_t prog_id_buf; 665 666 if (entering(tcp)) { 667 PRINT_FIELD_FD("{query={", attr, target_fd, tcp); 668 PRINT_FIELD_XVAL_INDEX(", ", attr, attach_type, bpf_attach_type, 669 "BPF_???"); 670 PRINT_FIELD_FLAGS(", ", attr, query_flags, bpf_query_flags, 671 "BPF_F_QUERY_???"); 672 PRINT_FIELD_FLAGS(", ", attr, attach_flags, bpf_attach_flags, 673 "BPF_F_???"); 674 675 tprints(", prog_ids="); 676 677 set_tcb_priv_ulong(tcp, attr.prog_cnt); 678 679 return 0; 680 } 681 682 print_big_u64_addr(attr.prog_ids); 683 print_array(tcp, attr.prog_ids, attr.prog_cnt, &prog_id_buf, 684 sizeof(prog_id_buf), tfetch_mem, 685 print_uint32_array_member, 0); 686 687 tprints(", prog_cnt="); 688 const uint32_t prog_cnt_entering = get_tcb_priv_ulong(tcp); 689 if (prog_cnt_entering != attr.prog_cnt) 690 tprintf("%" PRIu32 " => ", prog_cnt_entering); 691 tprintf("%" PRIu32, attr.prog_cnt); 692 tprints("}"); 693 } 694 END_BPF_CMD_DECODER(RVAL_DECODED) 695 696 BEGIN_BPF_CMD_DECODER(BPF_RAW_TRACEPOINT_OPEN) 697 { 698 enum { TP_NAME_SIZE = 128 }; 699 700 tprintf("{raw_tracepoint={name="); 701 print_big_u64_addr(attr.name); 702 printstr_ex(tcp, attr.name, TP_NAME_SIZE, QUOTE_0_TERMINATED); 703 704 PRINT_FIELD_FD(", ", attr, prog_fd, tcp); 705 706 tprints("}"); 707 } 708 END_BPF_CMD_DECODER(RVAL_DECODED) 709 710 SYS_FUNC(bpf) 711 { 712 static const bpf_cmd_decoder_t bpf_cmd_decoders[] = { 713 BPF_CMD_ENTRY(BPF_MAP_CREATE), 714 BPF_CMD_ENTRY(BPF_MAP_LOOKUP_ELEM), 715 BPF_CMD_ENTRY(BPF_MAP_UPDATE_ELEM), 716 BPF_CMD_ENTRY(BPF_MAP_DELETE_ELEM), 717 BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_KEY), 718 BPF_CMD_ENTRY(BPF_PROG_LOAD), 719 BPF_CMD_ENTRY(BPF_OBJ_PIN), 720 BPF_CMD_ENTRY(BPF_OBJ_GET), 721 BPF_CMD_ENTRY(BPF_PROG_ATTACH), 722 BPF_CMD_ENTRY(BPF_PROG_DETACH), 723 BPF_CMD_ENTRY(BPF_PROG_TEST_RUN), 724 BPF_CMD_ENTRY(BPF_PROG_GET_NEXT_ID), 725 BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_ID), 726 BPF_CMD_ENTRY(BPF_PROG_GET_FD_BY_ID), 727 BPF_CMD_ENTRY(BPF_MAP_GET_FD_BY_ID), 728 BPF_CMD_ENTRY(BPF_OBJ_GET_INFO_BY_FD), 729 BPF_CMD_ENTRY(BPF_PROG_QUERY), 730 BPF_CMD_ENTRY(BPF_RAW_TRACEPOINT_OPEN), 731 }; 732 733 const unsigned int cmd = tcp->u_arg[0]; 734 const kernel_ulong_t addr = tcp->u_arg[1]; 735 const unsigned int size = tcp->u_arg[2]; 736 int rc = RVAL_DECODED; 737 738 if (entering(tcp)) { 739 printxval_index(bpf_commands, cmd, "BPF_???"); 740 tprints(", "); 741 } 742 743 if (size > 0 744 && size <= get_pagesize() 745 && cmd < ARRAY_SIZE(bpf_cmd_decoders) 746 && bpf_cmd_decoders[cmd]) { 747 static char *buf; 748 749 if (!buf) 750 buf = xmalloc(get_pagesize()); 751 752 if (!umoven_or_printaddr_ignore_syserror(tcp, addr, size, buf)) 753 rc = bpf_cmd_decoders[cmd](tcp, addr, size, buf); 754 } else { 755 printaddr(addr); 756 } 757 758 if (exiting(tcp) || (rc & RVAL_DECODED)) 759 tprintf(", %u", size); 760 761 return rc; 762 } 763