• 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  * 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
decode_attr_extra_data(struct tcb * const tcp,const char * data,unsigned int size,const size_t attr_size)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 
DEF_BPF_CMD_DECODER(BPF_MAP_CREATE)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 
DEF_BPF_CMD_DECODER(BPF_MAP_LOOKUP_ELEM)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 
DEF_BPF_CMD_DECODER(BPF_MAP_UPDATE_ELEM)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 
DEF_BPF_CMD_DECODER(BPF_MAP_DELETE_ELEM)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 
DEF_BPF_CMD_DECODER(BPF_MAP_GET_NEXT_KEY)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 
DEF_BPF_CMD_DECODER(BPF_PROG_LOAD)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 
DEF_BPF_CMD_DECODER(BPF_OBJ_PIN)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 
DEF_BPF_CMD_DECODER(BPF_PROG_ATTACH)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 
DEF_BPF_CMD_DECODER(BPF_PROG_DETACH)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 
DEF_BPF_CMD_DECODER(BPF_PROG_TEST_RUN)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 
DEF_BPF_CMD_DECODER(BPF_PROG_GET_NEXT_ID)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 
DEF_BPF_CMD_DECODER(BPF_PROG_GET_FD_BY_ID)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 
DEF_BPF_CMD_DECODER(BPF_MAP_GET_FD_BY_ID)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 
DEF_BPF_CMD_DECODER(BPF_OBJ_GET_INFO_BY_FD)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 
SYS_FUNC(bpf)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