• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-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
decode_attr_extra_data(struct tcb * const tcp,const char * data,unsigned int size,const size_t attr_size)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
print_ebpf_insn(struct tcb * const tcp,void * const elem_buf,const size_t elem_size,void * const data)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
print_ebpf_prog(struct tcb * const tcp,const uint64_t addr,const uint32_t len)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 
BEGIN_BPF_CMD_DECODER(BPF_MAP_CREATE)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 
BEGIN_BPF_CMD_DECODER(BPF_MAP_LOOKUP_ELEM)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 
BEGIN_BPF_CMD_DECODER(BPF_MAP_UPDATE_ELEM)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 
BEGIN_BPF_CMD_DECODER(BPF_MAP_DELETE_ELEM)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 
BEGIN_BPF_CMD_DECODER(BPF_MAP_GET_NEXT_KEY)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 
BEGIN_BPF_CMD_DECODER(BPF_PROG_LOAD)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 
BEGIN_BPF_CMD_DECODER(BPF_OBJ_PIN)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 
BEGIN_BPF_CMD_DECODER(BPF_PROG_ATTACH)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 
BEGIN_BPF_CMD_DECODER(BPF_PROG_DETACH)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 
BEGIN_BPF_CMD_DECODER(BPF_PROG_TEST_RUN)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 
BEGIN_BPF_CMD_DECODER(BPF_PROG_GET_NEXT_ID)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 
BEGIN_BPF_CMD_DECODER(BPF_PROG_GET_FD_BY_ID)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 
BEGIN_BPF_CMD_DECODER(BPF_MAP_GET_FD_BY_ID)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
print_bpf_map_info(struct tcb * const tcp,uint32_t bpf_fd,const char * info_buf,uint32_t size,struct obj_get_info_saved * saved)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
print_bpf_prog_info(struct tcb * const tcp,uint32_t bpf_fd,const char * info_buf,uint32_t size,struct obj_get_info_saved * saved)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 *
fetch_bpf_obj_info(struct tcb * const tcp,uint64_t info,uint32_t size)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
print_bpf_obj_info_addr(struct tcb * const tcp,uint64_t addr)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
print_bpf_obj_info(struct tcb * const tcp,uint32_t bpf_fd,uint64_t info,uint32_t size,struct obj_get_info_saved * saved)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 
BEGIN_BPF_CMD_DECODER(BPF_OBJ_GET_INFO_BY_FD)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 
BEGIN_BPF_CMD_DECODER(BPF_PROG_QUERY)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 
BEGIN_BPF_CMD_DECODER(BPF_RAW_TRACEPOINT_OPEN)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 
SYS_FUNC(bpf)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