]> granicus.if.org Git - strace/blob - bpf.c
mmap_cache: add function to enable mmap_cache
[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 = 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 }