]> granicus.if.org Git - strace/blob - bpf.c
tests: remove redundant SAMPLE_SIZE definitions
[strace] / bpf.c
1 /*
2  * Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "defs.h"
29
30 #ifdef HAVE_LINUX_BPF_H
31 # include <linux/bpf.h>
32 #endif
33
34 #include "xlat/bpf_commands.h"
35 #include "xlat/bpf_map_types.h"
36 #include "xlat/bpf_prog_types.h"
37 #include "xlat/bpf_map_update_elem_flags.h"
38
39 static int
40 bpf_map_create(struct tcb *const tcp, const kernel_ulong_t addr,
41                unsigned int size)
42 {
43         struct {
44                 uint32_t map_type, key_size, value_size, max_entries;
45         } attr = {};
46
47         if (!size) {
48                 printaddr(addr);
49                 return RVAL_DECODED | RVAL_FD;
50         }
51         if (size > sizeof(attr))
52                 size = sizeof(attr);
53         if (umoven_or_printaddr(tcp, addr, size, &attr))
54                 return RVAL_DECODED | RVAL_FD;
55
56         tprints("{map_type=");
57         printxval(bpf_map_types, attr.map_type, "BPF_MAP_TYPE_???");
58         tprintf(", key_size=%u, value_size=%u, max_entries=%u}",
59                 attr.key_size, attr.value_size, attr.max_entries);
60
61         return RVAL_DECODED | RVAL_FD;
62 }
63
64 static void
65 bpf_map_update_elem(struct tcb *const tcp, const kernel_ulong_t addr,
66                     unsigned int size)
67 {
68         struct {
69                 uint32_t map_fd;
70                 uint64_t ATTRIBUTE_ALIGNED(8) key;
71                 uint64_t ATTRIBUTE_ALIGNED(8) value;
72                 uint64_t flags;
73         } attr = {};
74
75         if (!size) {
76                 printaddr(addr);
77                 return;
78         }
79         if (size > sizeof(attr))
80                 size = sizeof(attr);
81         if (umoven_or_printaddr(tcp, addr, size, &attr))
82                 return;
83
84         tprints("{map_fd=");
85         printfd(tcp, attr.map_fd);
86         tprintf(", key=%#" PRIx64 ", value=%#" PRIx64 ", flags=",
87                 attr.key, attr.value);
88         printxval64(bpf_map_update_elem_flags, attr.flags, "BPF_???");
89         tprints("}");
90 }
91
92 static void
93 bpf_map_delete_elem(struct tcb *const tcp, const kernel_ulong_t addr,
94                     unsigned int size)
95 {
96         struct {
97                 uint32_t map_fd;
98                 uint64_t ATTRIBUTE_ALIGNED(8) key;
99         } attr = {};
100
101         if (!size) {
102                 printaddr(addr);
103                 return;
104         }
105         if (size > sizeof(attr))
106                 size = sizeof(attr);
107         if (umoven_or_printaddr(tcp, addr, size, &attr))
108                 return;
109
110         tprints("{map_fd=");
111         printfd(tcp, attr.map_fd);
112         tprintf(", key=%#" PRIx64 "}", attr.key);
113 }
114
115 static int
116 bpf_map_io(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int size,
117            const char *const text)
118 {
119         struct bpf_io_elem_struct {
120                 uint32_t map_fd;
121                 uint64_t ATTRIBUTE_ALIGNED(8) key;
122                 uint64_t ATTRIBUTE_ALIGNED(8) value;
123         } attr = {};
124
125         if (exiting(tcp)) {
126                 if (!syserror(tcp) && !umove_or_printaddr(tcp, addr, &attr))
127                         tprintf(", %s=%#" PRIx64, text, attr.value);
128                 tprints("}");
129                 return RVAL_DECODED;
130         }
131
132         if (!size) {
133                 printaddr(addr);
134                 return RVAL_DECODED;
135         }
136         if (size > sizeof(attr))
137                 size = sizeof(attr);
138         if (umoven_or_printaddr(tcp, addr, size, &attr))
139                 return RVAL_DECODED;
140
141         tprints("{map_fd=");
142         printfd(tcp, attr.map_fd);
143         tprintf(", key=%#" PRIx64, attr.key);
144
145         return 0;
146 }
147
148 static int
149 bpf_prog_load(struct tcb *const tcp, const kernel_ulong_t addr,
150               unsigned int size)
151 {
152         struct {
153                 uint32_t prog_type, insn_cnt;
154                 uint64_t ATTRIBUTE_ALIGNED(8) insns, license;
155                 uint32_t log_level, log_size;
156                 uint64_t ATTRIBUTE_ALIGNED(8) log_buf;
157                 uint32_t kern_version;
158         } attr = {};
159
160         if (!size) {
161                 printaddr(addr);
162                 return RVAL_DECODED | RVAL_FD;
163         }
164         if (size > sizeof(attr))
165                 size = sizeof(attr);
166         if (umoven_or_printaddr(tcp, addr, size, &attr))
167                 return RVAL_DECODED | RVAL_FD;
168
169         tprints("{prog_type=");
170         printxval(bpf_prog_types, attr.prog_type, "BPF_PROG_TYPE_???");
171         tprintf(", insn_cnt=%u, insns=%#" PRIx64 ", license=",
172                 attr.insn_cnt, attr.insns);
173         printstr(tcp, attr.license);
174         tprintf(", log_level=%u, log_size=%u, log_buf=%#" PRIx64 ", kern_version=%u}",
175                 attr.log_level, attr.log_size, attr.log_buf, attr.kern_version);
176
177         return RVAL_DECODED | RVAL_FD;
178 }
179
180 SYS_FUNC(bpf)
181 {
182         const unsigned int cmd = tcp->u_arg[0];
183         const kernel_ulong_t addr = tcp->u_arg[1];
184         const unsigned int size = tcp->u_arg[2];
185         int rc = RVAL_DECODED;
186
187         if (entering(tcp)) {
188                 printxval(bpf_commands, cmd, "BPF_???");
189                 tprints(", ");
190         }
191
192         switch (cmd) {
193         case BPF_MAP_CREATE:
194                 rc = bpf_map_create(tcp, addr, size);
195                 break;
196         case BPF_MAP_LOOKUP_ELEM:
197                 rc = bpf_map_io(tcp, addr, size, "value");
198                 break;
199         case BPF_MAP_UPDATE_ELEM:
200                 bpf_map_update_elem(tcp, addr, size);
201                 break;
202         case BPF_MAP_DELETE_ELEM:
203                 bpf_map_delete_elem(tcp, addr, size);
204                 break;
205         case BPF_MAP_GET_NEXT_KEY:
206                 rc = bpf_map_io(tcp, addr, size, "next_key");
207                 break;
208         case BPF_PROG_LOAD:
209                 rc = bpf_prog_load(tcp, addr, size);
210                 break;
211         default:
212                 printaddr(addr);
213                 break;
214         }
215
216         if (rc & RVAL_DECODED)
217                 tprintf(", %u", size);
218
219         return rc;
220 }