Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 2015-2017 Dmitry V. Levin <ldv (at) altlinux.org>
      3  * Copyright (c) 2017 Quentin Monnet <quentin.monnet (at) 6wind.com>
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. The name of the author may not be used to endorse or promote products
     15  *    derived from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include "defs.h"
     30 #include "print_fields.h"
     31 
     32 #ifdef HAVE_LINUX_BPF_H
     33 # include <linux/bpf.h>
     34 #endif
     35 
     36 #include "xlat/bpf_commands.h"
     37 #include "xlat/bpf_map_types.h"
     38 #include "xlat/bpf_map_flags.h"
     39 #include "xlat/bpf_prog_types.h"
     40 #include "xlat/bpf_prog_flags.h"
     41 #include "xlat/bpf_map_update_elem_flags.h"
     42 #include "xlat/bpf_attach_type.h"
     43 #include "xlat/bpf_attach_flags.h"
     44 
     45 #define DECL_BPF_CMD_DECODER(bpf_cmd_decoder)				\
     46 int									\
     47 bpf_cmd_decoder(struct tcb *const tcp,					\
     48 		const kernel_ulong_t addr,				\
     49 		const unsigned int size,				\
     50 		void *const data)					\
     51 /* End of DECL_BPF_CMD_DECODER definition. */
     52 
     53 #define DEF_BPF_CMD_DECODER(bpf_cmd)					\
     54 	static DECL_BPF_CMD_DECODER(decode_ ## bpf_cmd)
     55 
     56 #define BPF_CMD_ENTRY(bpf_cmd)						\
     57 	[bpf_cmd] = decode_ ## bpf_cmd
     58 
     59 typedef DECL_BPF_CMD_DECODER((*bpf_cmd_decoder_t));
     60 
     61 static int
     62 decode_attr_extra_data(struct tcb *const tcp,
     63 		       const char *data,
     64 		       unsigned int size,
     65 		       const size_t attr_size)
     66 {
     67 	if (size <= attr_size)
     68 		return 0;
     69 
     70 	data += attr_size;
     71 	size -= attr_size;
     72 
     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 				print_quoted_string(data, size,
     81 						    QUOTE_FORCE_HEX);
     82 			return RVAL_DECODED;
     83 		}
     84 	}
     85 
     86 	return 0;
     87 }
     88 
     89 DEF_BPF_CMD_DECODER(BPF_MAP_CREATE)
     90 {
     91 	struct {
     92 		uint32_t map_type, key_size, value_size, max_entries,
     93 			 map_flags, inner_map_fd, numa_node;
     94 	} attr = {};
     95 	const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
     96 
     97 	memcpy(&attr, data, len);
     98 
     99 	PRINT_FIELD_XVAL("{", attr, map_type, bpf_map_types,
    100 			 "BPF_MAP_TYPE_???");
    101 	PRINT_FIELD_U(", ", attr, key_size);
    102 	PRINT_FIELD_U(", ", attr, value_size);
    103 	PRINT_FIELD_U(", ", attr, max_entries);
    104 	PRINT_FIELD_FLAGS(", ", attr, map_flags, bpf_map_flags, "BPF_F_???");
    105 	PRINT_FIELD_FD(", ", attr, inner_map_fd, tcp);
    106 	if (attr.map_flags & BPF_F_NUMA_NODE)
    107 		PRINT_FIELD_U(", ", attr, numa_node);
    108 	decode_attr_extra_data(tcp, data, size, sizeof(attr));
    109 	tprints("}");
    110 
    111 	return RVAL_DECODED | RVAL_FD;
    112 }
    113 
    114 DEF_BPF_CMD_DECODER(BPF_MAP_LOOKUP_ELEM)
    115 {
    116 	struct bpf_io_elem_struct {
    117 		uint32_t map_fd;
    118 		uint64_t ATTRIBUTE_ALIGNED(8) key, value;
    119 	} attr = {};
    120 
    121 	const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
    122 
    123 	memcpy(&attr, data, len);
    124 
    125 	PRINT_FIELD_FD("{", attr, map_fd, tcp);
    126 	PRINT_FIELD_X(", ", attr, key);
    127 	PRINT_FIELD_X(", ", attr, value);
    128 	decode_attr_extra_data(tcp, data, size, sizeof(attr));
    129 	tprints("}");
    130 
    131 	return RVAL_DECODED;
    132 }
    133 
    134 DEF_BPF_CMD_DECODER(BPF_MAP_UPDATE_ELEM)
    135 {
    136 	struct {
    137 		uint32_t map_fd;
    138 		uint64_t ATTRIBUTE_ALIGNED(8) key;
    139 		uint64_t ATTRIBUTE_ALIGNED(8) value;
    140 		uint64_t flags;
    141 	} attr = {};
    142 	const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
    143 
    144 	memcpy(&attr, data, len);
    145 
    146 	PRINT_FIELD_FD("{", attr, map_fd, tcp);
    147 	PRINT_FIELD_X(", ", attr, key);
    148 	PRINT_FIELD_X(", ", attr, value);
    149 	PRINT_FIELD_XVAL(", ", attr, flags, bpf_map_update_elem_flags,
    150 			 "BPF_???");
    151 	decode_attr_extra_data(tcp, data, size, sizeof(attr));
    152 	tprints("}");
    153 
    154 	return RVAL_DECODED;
    155 }
    156 
    157 DEF_BPF_CMD_DECODER(BPF_MAP_DELETE_ELEM)
    158 {
    159 	struct {
    160 		uint32_t map_fd;
    161 		uint64_t ATTRIBUTE_ALIGNED(8) key;
    162 	} attr = {};
    163 	const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
    164 
    165 	memcpy(&attr, data, len);
    166 
    167 	PRINT_FIELD_FD("{", attr, map_fd, tcp);
    168 	PRINT_FIELD_X(", ", attr, key);
    169 	decode_attr_extra_data(tcp, data, size, sizeof(attr));
    170 	tprints("}");
    171 
    172 	return RVAL_DECODED;
    173 }
    174 
    175 DEF_BPF_CMD_DECODER(BPF_MAP_GET_NEXT_KEY)
    176 {
    177 	struct bpf_io_elem_struct {
    178 		uint32_t map_fd;
    179 		uint64_t ATTRIBUTE_ALIGNED(8) key, next_key;
    180 	} attr = {};
    181 
    182 	const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
    183 
    184 	memcpy(&attr, data, len);
    185 
    186 	PRINT_FIELD_FD("{", attr, map_fd, tcp);
    187 	PRINT_FIELD_X(", ", attr, key);
    188 	PRINT_FIELD_X(", ", attr, next_key);
    189 	decode_attr_extra_data(tcp, data, size, sizeof(attr));
    190 	tprints("}");
    191 
    192 	return RVAL_DECODED;
    193 }
    194 
    195 DEF_BPF_CMD_DECODER(BPF_PROG_LOAD)
    196 {
    197 	struct bpf_prog_load {
    198 		uint32_t prog_type, insn_cnt;
    199 		uint64_t ATTRIBUTE_ALIGNED(8) insns, license;
    200 		uint32_t log_level, log_size;
    201 		uint64_t ATTRIBUTE_ALIGNED(8) log_buf;
    202 		uint32_t kern_version, prog_flags;
    203 	} attr = {};
    204 	const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
    205 
    206 	memcpy(&attr, data, len);
    207 
    208 	PRINT_FIELD_XVAL("{", attr, prog_type, bpf_prog_types,
    209 			 "BPF_PROG_TYPE_???");
    210 	PRINT_FIELD_U(", ", attr, insn_cnt);
    211 	PRINT_FIELD_X(", ", attr, insns);
    212 	PRINT_FIELD_STR(", ", attr, license, tcp);
    213 	PRINT_FIELD_U(", ", attr, log_level);
    214 	PRINT_FIELD_U(", ", attr, log_size);
    215 	PRINT_FIELD_X(", ", attr, log_buf);
    216 	PRINT_FIELD_U(", ", attr, kern_version);
    217 	PRINT_FIELD_FLAGS(", ", attr, prog_flags, bpf_prog_flags, "BPF_F_???");
    218 	decode_attr_extra_data(tcp, data, size, sizeof(attr));
    219 	tprints("}");
    220 
    221 	return RVAL_DECODED | RVAL_FD;
    222 }
    223 
    224 DEF_BPF_CMD_DECODER(BPF_OBJ_PIN)
    225 {
    226 	struct bpf_obj {
    227 		uint64_t ATTRIBUTE_ALIGNED(8) pathname;
    228 		uint32_t bpf_fd;
    229 	} attr = {};
    230 	const size_t attr_size =
    231 		offsetofend(struct bpf_obj, bpf_fd);
    232 	const unsigned int len = size < attr_size ? size : attr_size;
    233 
    234 	memcpy(&attr, data, len);
    235 
    236 	PRINT_FIELD_PATH("{", attr, pathname, tcp);
    237 	PRINT_FIELD_FD(", ", attr, bpf_fd, tcp);
    238 	decode_attr_extra_data(tcp, data, size, attr_size);
    239 	tprints("}");
    240 
    241 	return RVAL_DECODED | RVAL_FD;
    242 }
    243 
    244 #define decode_BPF_OBJ_GET decode_BPF_OBJ_PIN
    245 
    246 DEF_BPF_CMD_DECODER(BPF_PROG_ATTACH)
    247 {
    248 	struct {
    249 		uint32_t target_fd, attach_bpf_fd, attach_type, attach_flags;
    250 	} attr = {};
    251 	const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
    252 
    253 	memcpy(&attr, data, len);
    254 
    255 	PRINT_FIELD_FD("{", attr, target_fd, tcp);
    256 	PRINT_FIELD_FD(", ", attr, attach_bpf_fd, tcp);
    257 	PRINT_FIELD_XVAL(", ", attr, attach_type, bpf_attach_type, "BPF_???");
    258 	PRINT_FIELD_FLAGS(", ", attr, attach_flags, bpf_attach_flags,
    259 			  "BPF_F_???");
    260 	decode_attr_extra_data(tcp, data, size, sizeof(attr));
    261 	tprints("}");
    262 
    263 	return RVAL_DECODED;
    264 }
    265 
    266 DEF_BPF_CMD_DECODER(BPF_PROG_DETACH)
    267 {
    268 	struct {
    269 		uint32_t target_fd, dummy, attach_type;
    270 	} attr = {};
    271 	const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
    272 
    273 	memcpy(&attr, data, len);
    274 
    275 	PRINT_FIELD_FD("{", attr, target_fd, tcp);
    276 	PRINT_FIELD_XVAL(", ", attr, attach_type, bpf_attach_type, "BPF_???");
    277 	decode_attr_extra_data(tcp, data, size, sizeof(attr));
    278 	tprints("}");
    279 
    280 	return RVAL_DECODED;
    281 }
    282 
    283 DEF_BPF_CMD_DECODER(BPF_PROG_TEST_RUN)
    284 {
    285 	struct {
    286 		uint32_t prog_fd, retval, data_size_in, data_size_out;
    287 		uint64_t ATTRIBUTE_ALIGNED(8) data_in, data_out;
    288 		uint32_t repeat, duration;
    289 	} attr = {};
    290 	const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
    291 
    292 	memcpy(&attr, data, len);
    293 
    294 	PRINT_FIELD_FD("{test={", attr, prog_fd, tcp);
    295 	PRINT_FIELD_U(", ", attr, retval);
    296 	PRINT_FIELD_U(", ", attr, data_size_in);
    297 	PRINT_FIELD_U(", ", attr, data_size_out);
    298 	PRINT_FIELD_X(", ", attr, data_in);
    299 	PRINT_FIELD_X(", ", attr, data_out);
    300 	PRINT_FIELD_U(", ", attr, repeat);
    301 	PRINT_FIELD_U(", ", attr, duration);
    302 	tprints("}");
    303 	decode_attr_extra_data(tcp, data, size, sizeof(attr));
    304 	tprints("}");
    305 
    306 	return RVAL_DECODED;
    307 }
    308 
    309 DEF_BPF_CMD_DECODER(BPF_PROG_GET_NEXT_ID)
    310 {
    311 	struct {
    312 		uint32_t start_id, next_id;
    313 	} attr = {};
    314 	const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
    315 
    316 	memcpy(&attr, data, len);
    317 
    318 	PRINT_FIELD_U("{", attr, start_id);
    319 	PRINT_FIELD_U(", ", attr, next_id);
    320 	decode_attr_extra_data(tcp, data, size, sizeof(attr));
    321 	tprints("}");
    322 
    323 	return RVAL_DECODED;
    324 }
    325 
    326 #define decode_BPF_MAP_GET_NEXT_ID decode_BPF_PROG_GET_NEXT_ID
    327 
    328 DEF_BPF_CMD_DECODER(BPF_PROG_GET_FD_BY_ID)
    329 {
    330 	struct {
    331 		uint32_t prog_id, next_id;
    332 	} attr = {};
    333 	const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
    334 
    335 	memcpy(&attr, data, len);
    336 
    337 	PRINT_FIELD_U("{", attr, prog_id);
    338 	PRINT_FIELD_U(", ", attr, next_id);
    339 	decode_attr_extra_data(tcp, data, size, sizeof(attr));
    340 	tprints("}");
    341 
    342 	return RVAL_DECODED;
    343 }
    344 
    345 DEF_BPF_CMD_DECODER(BPF_MAP_GET_FD_BY_ID)
    346 {
    347 	struct {
    348 		uint32_t map_id, next_id;
    349 	} attr = {};
    350 	const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
    351 
    352 	memcpy(&attr, data, len);
    353 
    354 	PRINT_FIELD_U("{", attr, map_id);
    355 	PRINT_FIELD_U(", ", attr, next_id);
    356 	decode_attr_extra_data(tcp, data, size, sizeof(attr));
    357 	tprints("}");
    358 
    359 	return RVAL_DECODED;
    360 }
    361 
    362 DEF_BPF_CMD_DECODER(BPF_OBJ_GET_INFO_BY_FD)
    363 {
    364 	struct {
    365 		uint32_t bpf_fd, info_len;
    366 		uint64_t ATTRIBUTE_ALIGNED(8) info;
    367 	} attr = {};
    368 	const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
    369 
    370 	memcpy(&attr, data, len);
    371 
    372 	PRINT_FIELD_FD("{info={", attr, bpf_fd, tcp);
    373 	PRINT_FIELD_U(", ", attr, info_len);
    374 	PRINT_FIELD_X(", ", attr, info);
    375 	tprints("}");
    376 	decode_attr_extra_data(tcp, data, size, sizeof(attr));
    377 	tprints("}");
    378 
    379 	return RVAL_DECODED | RVAL_FD;
    380 }
    381 
    382 SYS_FUNC(bpf)
    383 {
    384 	static const bpf_cmd_decoder_t bpf_cmd_decoders[] = {
    385 		BPF_CMD_ENTRY(BPF_MAP_CREATE),
    386 		BPF_CMD_ENTRY(BPF_MAP_LOOKUP_ELEM),
    387 		BPF_CMD_ENTRY(BPF_MAP_UPDATE_ELEM),
    388 		BPF_CMD_ENTRY(BPF_MAP_DELETE_ELEM),
    389 		BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_KEY),
    390 		BPF_CMD_ENTRY(BPF_PROG_LOAD),
    391 		BPF_CMD_ENTRY(BPF_OBJ_PIN),
    392 		BPF_CMD_ENTRY(BPF_OBJ_GET),
    393 		BPF_CMD_ENTRY(BPF_PROG_ATTACH),
    394 		BPF_CMD_ENTRY(BPF_PROG_DETACH),
    395 		BPF_CMD_ENTRY(BPF_PROG_TEST_RUN),
    396 		BPF_CMD_ENTRY(BPF_PROG_GET_NEXT_ID),
    397 		BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_ID),
    398 		BPF_CMD_ENTRY(BPF_PROG_GET_FD_BY_ID),
    399 		BPF_CMD_ENTRY(BPF_MAP_GET_FD_BY_ID),
    400 		BPF_CMD_ENTRY(BPF_OBJ_GET_INFO_BY_FD),
    401 	};
    402 
    403 	const unsigned int cmd = tcp->u_arg[0];
    404 	const kernel_ulong_t addr = tcp->u_arg[1];
    405 	const unsigned int size = tcp->u_arg[2];
    406 	int rc;
    407 
    408 	if (entering(tcp)) {
    409 		static size_t page_size;
    410 		static char *buf;
    411 
    412 		if (!buf) {
    413 			page_size = get_pagesize();
    414 			buf = xmalloc(page_size);
    415 		}
    416 
    417 		printxval(bpf_commands, cmd, "BPF_???");
    418 		tprints(", ");
    419 
    420 		if (size > 0
    421 		    && size <= get_pagesize()
    422 		    && cmd < ARRAY_SIZE(bpf_cmd_decoders)
    423 		    && bpf_cmd_decoders[cmd]) {
    424 			rc = umoven_or_printaddr(tcp, addr, size, buf)
    425 			     ? RVAL_DECODED
    426 			     : bpf_cmd_decoders[cmd](tcp, addr, size, buf);
    427 		} else {
    428 			printaddr(addr);
    429 			rc = RVAL_DECODED;
    430 		}
    431 	} else {
    432 		rc = bpf_cmd_decoders[cmd](tcp, addr, size, NULL) | RVAL_DECODED;
    433 	}
    434 
    435 	if (rc & RVAL_DECODED)
    436 		tprintf(", %u", size);
    437 
    438 	return rc;
    439 }
    440