blob: 7734b07ab80e307823cb370b5fc90519d38dcee0 [file] [log] [blame]
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +00001/*
Elliott Hughes77c3ff82017-09-08 17:11:00 -07002 * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@altlinux.org>
Elliott Hughesd35df492017-02-15 15:19:05 -08003 * Copyright (c) 2017 Quentin Monnet <quentin.monnet@6wind.com>
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +00004 * 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"
Elliott Hughes77c3ff82017-09-08 17:11:00 -070030#include "print_fields.h"
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +000031
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"
Elliott Hughes77c3ff82017-09-08 17:11:00 -070038#include "xlat/bpf_map_flags.h"
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +000039#include "xlat/bpf_prog_types.h"
Elliott Hughes77c3ff82017-09-08 17:11:00 -070040#include "xlat/bpf_prog_flags.h"
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +000041#include "xlat/bpf_map_update_elem_flags.h"
Elliott Hughesd35df492017-02-15 15:19:05 -080042#include "xlat/bpf_attach_type.h"
Elliott Hughes39bac052017-05-25 16:56:11 -070043#include "xlat/bpf_attach_flags.h"
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +000044
Elliott Hughes77c3ff82017-09-08 17:11:00 -070045#define DECL_BPF_CMD_DECODER(bpf_cmd_decoder) \
46int \
47bpf_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
59typedef DECL_BPF_CMD_DECODER((*bpf_cmd_decoder_t));
60
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +000061static int
Elliott Hughes77c3ff82017-09-08 17:11:00 -070062decode_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
89DEF_BPF_CMD_DECODER(BPF_MAP_CREATE)
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +000090{
91 struct {
Elliott Hughes77c3ff82017-09-08 17:11:00 -070092 uint32_t map_type, key_size, value_size, max_entries,
93 map_flags, inner_map_fd;
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +000094 } attr = {};
Elliott Hughes77c3ff82017-09-08 17:11:00 -070095 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +000096
Elliott Hughes77c3ff82017-09-08 17:11:00 -070097 memcpy(&attr, data, len);
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +000098
Elliott Hughes77c3ff82017-09-08 17:11:00 -070099 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 decode_attr_extra_data(tcp, data, size, sizeof(attr));
107 tprints("}");
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +0000108
109 return RVAL_DECODED | RVAL_FD;
110}
111
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700112DEF_BPF_CMD_DECODER(BPF_MAP_LOOKUP_ELEM)
113{
114 struct bpf_io_elem_struct {
115 uint32_t map_fd;
116 uint64_t ATTRIBUTE_ALIGNED(8) key, value;
117 } attr = {};
118
119 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
120
121 memcpy(&attr, data, len);
122
123 PRINT_FIELD_FD("{", attr, map_fd, tcp);
124 PRINT_FIELD_X(", ", attr, key);
125 PRINT_FIELD_X(", ", attr, value);
126 decode_attr_extra_data(tcp, data, size, sizeof(attr));
127 tprints("}");
128
129 return RVAL_DECODED;
130}
131
132DEF_BPF_CMD_DECODER(BPF_MAP_UPDATE_ELEM)
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +0000133{
134 struct {
135 uint32_t map_fd;
136 uint64_t ATTRIBUTE_ALIGNED(8) key;
137 uint64_t ATTRIBUTE_ALIGNED(8) value;
138 uint64_t flags;
139 } attr = {};
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700140 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +0000141
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700142 memcpy(&attr, data, len);
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +0000143
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700144 PRINT_FIELD_FD("{", attr, map_fd, tcp);
145 PRINT_FIELD_X(", ", attr, key);
146 PRINT_FIELD_X(", ", attr, value);
147 PRINT_FIELD_XVAL(", ", attr, flags, bpf_map_update_elem_flags,
148 "BPF_???");
149 decode_attr_extra_data(tcp, data, size, sizeof(attr));
Elliott Hughes39bac052017-05-25 16:56:11 -0700150 tprints("}");
Elliott Hughesd35df492017-02-15 15:19:05 -0800151
152 return RVAL_DECODED;
153}
154
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700155DEF_BPF_CMD_DECODER(BPF_MAP_DELETE_ELEM)
Elliott Hughesd35df492017-02-15 15:19:05 -0800156{
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700157 struct {
158 uint32_t map_fd;
159 uint64_t ATTRIBUTE_ALIGNED(8) key;
160 } attr = {};
161 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
162
163 memcpy(&attr, data, len);
164
165 PRINT_FIELD_FD("{", attr, map_fd, tcp);
166 PRINT_FIELD_X(", ", attr, key);
167 decode_attr_extra_data(tcp, data, size, sizeof(attr));
168 tprints("}");
169
170 return RVAL_DECODED;
Elliott Hughesd35df492017-02-15 15:19:05 -0800171}
172
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700173DEF_BPF_CMD_DECODER(BPF_MAP_GET_NEXT_KEY)
Elliott Hughesd35df492017-02-15 15:19:05 -0800174{
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700175 struct bpf_io_elem_struct {
176 uint32_t map_fd;
177 uint64_t ATTRIBUTE_ALIGNED(8) key, next_key;
178 } attr = {};
179
180 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
181
182 memcpy(&attr, data, len);
183
184 PRINT_FIELD_FD("{", attr, map_fd, tcp);
185 PRINT_FIELD_X(", ", attr, key);
186 PRINT_FIELD_X(", ", attr, next_key);
187 decode_attr_extra_data(tcp, data, size, sizeof(attr));
188 tprints("}");
189
190 return RVAL_DECODED;
191}
192
193DEF_BPF_CMD_DECODER(BPF_PROG_LOAD)
194{
195 struct bpf_prog_load {
196 uint32_t prog_type, insn_cnt;
197 uint64_t ATTRIBUTE_ALIGNED(8) insns, license;
198 uint32_t log_level, log_size;
199 uint64_t ATTRIBUTE_ALIGNED(8) log_buf;
200 uint32_t kern_version, prog_flags;
201 } attr = {};
202 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
203
204 memcpy(&attr, data, len);
205
206 PRINT_FIELD_XVAL("{", attr, prog_type, bpf_prog_types,
207 "BPF_PROG_TYPE_???");
208 PRINT_FIELD_U(", ", attr, insn_cnt);
209 PRINT_FIELD_X(", ", attr, insns);
210 PRINT_FIELD_STR(", ", attr, license, tcp);
211 PRINT_FIELD_U(", ", attr, log_level);
212 PRINT_FIELD_U(", ", attr, log_size);
213 PRINT_FIELD_X(", ", attr, log_buf);
214 PRINT_FIELD_U(", ", attr, kern_version);
215 PRINT_FIELD_FLAGS(", ", attr, prog_flags, bpf_prog_flags, "BPF_F_???");
216 decode_attr_extra_data(tcp, data, size, sizeof(attr));
217 tprints("}");
218
219 return RVAL_DECODED | RVAL_FD;
220}
221
222DEF_BPF_CMD_DECODER(BPF_OBJ_PIN)
223{
224 struct bpf_obj {
225 uint64_t ATTRIBUTE_ALIGNED(8) pathname;
226 uint32_t bpf_fd;
227 } attr = {};
228 const size_t attr_size =
229 offsetofend(struct bpf_obj, bpf_fd);
230 const unsigned int len = size < attr_size ? size : attr_size;
231
232 memcpy(&attr, data, len);
233
234 PRINT_FIELD_PATH("{", attr, pathname, tcp);
235 PRINT_FIELD_FD(", ", attr, bpf_fd, tcp);
236 decode_attr_extra_data(tcp, data, size, attr_size);
237 tprints("}");
238
239 return RVAL_DECODED | RVAL_FD;
240}
241
242#define decode_BPF_OBJ_GET decode_BPF_OBJ_PIN
243
244DEF_BPF_CMD_DECODER(BPF_PROG_ATTACH)
245{
246 struct {
247 uint32_t target_fd, attach_bpf_fd, attach_type, attach_flags;
248 } attr = {};
249 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
250
251 memcpy(&attr, data, len);
252
253 PRINT_FIELD_FD("{", attr, target_fd, tcp);
254 PRINT_FIELD_FD(", ", attr, attach_bpf_fd, tcp);
255 PRINT_FIELD_XVAL(", ", attr, attach_type, bpf_attach_type, "BPF_???");
256 PRINT_FIELD_FLAGS(", ", attr, attach_flags, bpf_attach_flags,
257 "BPF_F_???");
258 decode_attr_extra_data(tcp, data, size, sizeof(attr));
259 tprints("}");
260
261 return RVAL_DECODED;
262}
263
264DEF_BPF_CMD_DECODER(BPF_PROG_DETACH)
265{
266 struct {
267 uint32_t target_fd, dummy, attach_type;
268 } attr = {};
269 const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
270
271 memcpy(&attr, data, len);
272
273 PRINT_FIELD_FD("{", attr, target_fd, tcp);
274 PRINT_FIELD_XVAL(", ", attr, attach_type, bpf_attach_type, "BPF_???");
275 decode_attr_extra_data(tcp, data, size, sizeof(attr));
276 tprints("}");
277
278 return RVAL_DECODED;
Elliott Hughesd35df492017-02-15 15:19:05 -0800279}
280
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +0000281SYS_FUNC(bpf)
282{
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700283 static const bpf_cmd_decoder_t bpf_cmd_decoders[] = {
284 BPF_CMD_ENTRY(BPF_MAP_CREATE),
285 BPF_CMD_ENTRY(BPF_MAP_LOOKUP_ELEM),
286 BPF_CMD_ENTRY(BPF_MAP_UPDATE_ELEM),
287 BPF_CMD_ENTRY(BPF_MAP_DELETE_ELEM),
288 BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_KEY),
289 BPF_CMD_ENTRY(BPF_PROG_LOAD),
290 BPF_CMD_ENTRY(BPF_OBJ_PIN),
291 BPF_CMD_ENTRY(BPF_OBJ_GET),
292 BPF_CMD_ENTRY(BPF_PROG_ATTACH),
293 BPF_CMD_ENTRY(BPF_PROG_DETACH),
294 };
295
Elliott Hughesd35df492017-02-15 15:19:05 -0800296 const unsigned int cmd = tcp->u_arg[0];
297 const kernel_ulong_t addr = tcp->u_arg[1];
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +0000298 const unsigned int size = tcp->u_arg[2];
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700299 int rc;
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +0000300
301 if (entering(tcp)) {
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700302 static size_t page_size;
303 static char *buf;
304
305 if (!buf) {
306 page_size = get_pagesize();
307 buf = xmalloc(page_size);
308 }
309
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +0000310 printxval(bpf_commands, cmd, "BPF_???");
311 tprints(", ");
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +0000312
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700313 if (size > 0
314 && size <= get_pagesize()
315 && cmd < ARRAY_SIZE(bpf_cmd_decoders)
316 && bpf_cmd_decoders[cmd]) {
317 rc = umoven_or_printaddr(tcp, addr, size, buf)
318 ? RVAL_DECODED
319 : bpf_cmd_decoders[cmd](tcp, addr, size, buf);
320 } else {
321 printaddr(addr);
322 rc = RVAL_DECODED;
323 }
324 } else {
325 rc = bpf_cmd_decoders[cmd](tcp, addr, size, NULL) | RVAL_DECODED;
Dmitry V. Levinddb53dd2015-07-25 23:55:51 +0000326 }
327
328 if (rc & RVAL_DECODED)
329 tprintf(", %u", size);
330
331 return rc;
332}