Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bpf.c 28KB

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