]> granicus.if.org Git - strace/blob - bpf.c
Add i18n support
[strace] / bpf.c
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
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 = MIN(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
214         /* log_* fields were added in Linux commit v3.18-rc1~52^2~1^2~4.  */
215         if (len <= offsetof(struct bpf_prog_load, log_level))
216                 goto bpf_prog_load_end;
217         PRINT_FIELD_U(", ", attr, log_level);
218         PRINT_FIELD_U(", ", attr, log_size);
219         PRINT_FIELD_X(", ", attr, log_buf);
220
221         /* kern_version field was added in Linux commit v4.1-rc1~84^2~50.  */
222         if (len <= offsetof(struct bpf_prog_load, kern_version))
223                 goto bpf_prog_load_end;
224         tprintf(", kern_version=KERNEL_VERSION(%u, %u, %u)",
225                 attr.kern_version >> 16,
226                 (attr.kern_version >> 8) & 0xFF,
227                 attr.kern_version & 0xFF);
228
229         /* prog_flags field was added in Linux commit v4.12-rc2~34^2~29^2~2.  */
230         if (len <= offsetof(struct bpf_prog_load, prog_flags))
231                 goto bpf_prog_load_end;
232         PRINT_FIELD_FLAGS(", ", attr, prog_flags, bpf_prog_flags, "BPF_F_???");
233
234         decode_attr_extra_data(tcp, data, size, sizeof(attr));
235
236 bpf_prog_load_end:
237         tprints("}");
238
239         return RVAL_DECODED | RVAL_FD;
240 }
241
242 DEF_BPF_CMD_DECODER(BPF_OBJ_PIN)
243 {
244         struct bpf_obj {
245                 uint64_t ATTRIBUTE_ALIGNED(8) pathname;
246                 uint32_t bpf_fd;
247         } attr = {};
248         const size_t attr_size =
249                 offsetofend(struct bpf_obj, bpf_fd);
250         const unsigned int len = size < attr_size ? size : attr_size;
251
252         memcpy(&attr, data, len);
253
254         PRINT_FIELD_PATH("{", attr, pathname, tcp);
255         PRINT_FIELD_FD(", ", attr, bpf_fd, tcp);
256         decode_attr_extra_data(tcp, data, size, attr_size);
257         tprints("}");
258
259         return RVAL_DECODED | RVAL_FD;
260 }
261
262 #define decode_BPF_OBJ_GET decode_BPF_OBJ_PIN
263
264 DEF_BPF_CMD_DECODER(BPF_PROG_ATTACH)
265 {
266         struct {
267                 uint32_t target_fd, attach_bpf_fd, attach_type, attach_flags;
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_FD(", ", attr, attach_bpf_fd, tcp);
275         PRINT_FIELD_XVAL(", ", attr, attach_type, bpf_attach_type, "BPF_???");
276         PRINT_FIELD_FLAGS(", ", attr, attach_flags, bpf_attach_flags,
277                           "BPF_F_???");
278         decode_attr_extra_data(tcp, data, size, sizeof(attr));
279         tprints("}");
280
281         return RVAL_DECODED;
282 }
283
284 DEF_BPF_CMD_DECODER(BPF_PROG_DETACH)
285 {
286         struct {
287                 uint32_t target_fd, dummy, attach_type;
288         } attr = {};
289         const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
290
291         memcpy(&attr, data, len);
292
293         PRINT_FIELD_FD("{", attr, target_fd, tcp);
294         PRINT_FIELD_XVAL(", ", attr, attach_type, bpf_attach_type, "BPF_???");
295         decode_attr_extra_data(tcp, data, size, sizeof(attr));
296         tprints("}");
297
298         return RVAL_DECODED;
299 }
300
301 DEF_BPF_CMD_DECODER(BPF_PROG_TEST_RUN)
302 {
303         struct {
304                 uint32_t prog_fd, retval, data_size_in, data_size_out;
305                 uint64_t ATTRIBUTE_ALIGNED(8) data_in, data_out;
306                 uint32_t repeat, duration;
307         } attr = {};
308         const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
309
310         memcpy(&attr, data, len);
311
312         PRINT_FIELD_FD("{test={", attr, prog_fd, tcp);
313         PRINT_FIELD_U(", ", attr, retval);
314         PRINT_FIELD_U(", ", attr, data_size_in);
315         PRINT_FIELD_U(", ", attr, data_size_out);
316         PRINT_FIELD_X(", ", attr, data_in);
317         PRINT_FIELD_X(", ", attr, data_out);
318         PRINT_FIELD_U(", ", attr, repeat);
319         PRINT_FIELD_U(", ", attr, duration);
320         tprints("}");
321         decode_attr_extra_data(tcp, data, size, sizeof(attr));
322         tprints("}");
323
324         return RVAL_DECODED;
325 }
326
327 DEF_BPF_CMD_DECODER(BPF_PROG_GET_NEXT_ID)
328 {
329         struct {
330                 uint32_t start_id, next_id;
331         } attr = {};
332         const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
333
334         memcpy(&attr, data, len);
335
336         PRINT_FIELD_U("{", attr, start_id);
337         PRINT_FIELD_U(", ", attr, next_id);
338         decode_attr_extra_data(tcp, data, size, sizeof(attr));
339         tprints("}");
340
341         return RVAL_DECODED;
342 }
343
344 #define decode_BPF_MAP_GET_NEXT_ID decode_BPF_PROG_GET_NEXT_ID
345
346 DEF_BPF_CMD_DECODER(BPF_PROG_GET_FD_BY_ID)
347 {
348         struct {
349                 uint32_t prog_id, next_id;
350         } attr = {};
351         const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
352
353         memcpy(&attr, data, len);
354
355         PRINT_FIELD_U("{", attr, prog_id);
356         PRINT_FIELD_U(", ", attr, next_id);
357         decode_attr_extra_data(tcp, data, size, sizeof(attr));
358         tprints("}");
359
360         return RVAL_DECODED;
361 }
362
363 DEF_BPF_CMD_DECODER(BPF_MAP_GET_FD_BY_ID)
364 {
365         struct {
366                 uint32_t map_id, next_id;
367         } attr = {};
368         const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
369
370         memcpy(&attr, data, len);
371
372         PRINT_FIELD_U("{", attr, map_id);
373         PRINT_FIELD_U(", ", attr, next_id);
374         decode_attr_extra_data(tcp, data, size, sizeof(attr));
375         tprints("}");
376
377         return RVAL_DECODED;
378 }
379
380 DEF_BPF_CMD_DECODER(BPF_OBJ_GET_INFO_BY_FD)
381 {
382         struct {
383                 uint32_t bpf_fd, info_len;
384                 uint64_t ATTRIBUTE_ALIGNED(8) info;
385         } attr = {};
386         const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
387
388         memcpy(&attr, data, len);
389
390         PRINT_FIELD_FD("{info={", attr, bpf_fd, tcp);
391         PRINT_FIELD_U(", ", attr, info_len);
392         PRINT_FIELD_X(", ", attr, info);
393         tprints("}");
394         decode_attr_extra_data(tcp, data, size, sizeof(attr));
395         tprints("}");
396
397         return RVAL_DECODED | RVAL_FD;
398 }
399
400 SYS_FUNC(bpf)
401 {
402         static const bpf_cmd_decoder_t bpf_cmd_decoders[] = {
403                 BPF_CMD_ENTRY(BPF_MAP_CREATE),
404                 BPF_CMD_ENTRY(BPF_MAP_LOOKUP_ELEM),
405                 BPF_CMD_ENTRY(BPF_MAP_UPDATE_ELEM),
406                 BPF_CMD_ENTRY(BPF_MAP_DELETE_ELEM),
407                 BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_KEY),
408                 BPF_CMD_ENTRY(BPF_PROG_LOAD),
409                 BPF_CMD_ENTRY(BPF_OBJ_PIN),
410                 BPF_CMD_ENTRY(BPF_OBJ_GET),
411                 BPF_CMD_ENTRY(BPF_PROG_ATTACH),
412                 BPF_CMD_ENTRY(BPF_PROG_DETACH),
413                 BPF_CMD_ENTRY(BPF_PROG_TEST_RUN),
414                 BPF_CMD_ENTRY(BPF_PROG_GET_NEXT_ID),
415                 BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_ID),
416                 BPF_CMD_ENTRY(BPF_PROG_GET_FD_BY_ID),
417                 BPF_CMD_ENTRY(BPF_MAP_GET_FD_BY_ID),
418                 BPF_CMD_ENTRY(BPF_OBJ_GET_INFO_BY_FD),
419         };
420
421         const unsigned int cmd = tcp->u_arg[0];
422         const kernel_ulong_t addr = tcp->u_arg[1];
423         const unsigned int size = tcp->u_arg[2];
424         int rc;
425
426         if (entering(tcp)) {
427                 static char *buf;
428
429                 if (!buf)
430                         buf = xmalloc(get_pagesize());
431
432                 printxval(bpf_commands, cmd, "BPF_???");
433                 tprints(", ");
434
435                 if (size > 0
436                     && size <= get_pagesize()
437                     && cmd < ARRAY_SIZE(bpf_cmd_decoders)
438                     && bpf_cmd_decoders[cmd]) {
439                         rc = umoven_or_printaddr(tcp, addr, size, buf)
440                              ? RVAL_DECODED
441                              : bpf_cmd_decoders[cmd](tcp, addr, size, buf);
442                 } else {
443                         printaddr(addr);
444                         rc = RVAL_DECODED;
445                 }
446         } else {
447                 rc = bpf_cmd_decoders[cmd](tcp, addr, size, NULL) | RVAL_DECODED;
448         }
449
450         if (rc & RVAL_DECODED)
451                 tprintf(", %u", size);
452
453         return rc;
454 }