1 /* 2 * Copyright (c) 2015-2017 Dmitry V. Levin <ldv (at) altlinux.org> 3 * Copyright (c) 2017 Quentin Monnet <quentin.monnet (at) 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 } 440