]> granicus.if.org Git - strace/blob - bpf.c
Update MADV_* constants
[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;
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         decode_attr_extra_data(tcp, data, size, sizeof(attr));
107         tprints("}");
108
109         return RVAL_DECODED | RVAL_FD;
110 }
111
112 DEF_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
132 DEF_BPF_CMD_DECODER(BPF_MAP_UPDATE_ELEM)
133 {
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 = {};
140         const unsigned int len = size < sizeof(attr) ? size : sizeof(attr);
141
142         memcpy(&attr, data, len);
143
144         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));
150         tprints("}");
151
152         return RVAL_DECODED;
153 }
154
155 DEF_BPF_CMD_DECODER(BPF_MAP_DELETE_ELEM)
156 {
157         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;
171 }
172
173 DEF_BPF_CMD_DECODER(BPF_MAP_GET_NEXT_KEY)
174 {
175         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
193 DEF_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
222 DEF_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
244 DEF_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
264 DEF_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;
279 }
280
281 SYS_FUNC(bpf)
282 {
283         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
296         const unsigned int cmd = tcp->u_arg[0];
297         const kernel_ulong_t addr = tcp->u_arg[1];
298         const unsigned int size = tcp->u_arg[2];
299         int rc;
300
301         if (entering(tcp)) {
302                 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
310                 printxval(bpf_commands, cmd, "BPF_???");
311                 tprints(", ");
312
313                 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;
326         }
327
328         if (rc & RVAL_DECODED)
329                 tprintf(", %u", size);
330
331         return rc;
332 }