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 27KB

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