Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 2015 Dmitry V. Levin <ldv (at) 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 *tcp, const long addr, unsigned int size)
     41 {
     42 	struct {
     43 		uint32_t map_type, key_size, value_size, max_entries;
     44 	} attr = {};
     45 
     46 	if (!size) {
     47 		printaddr(addr);
     48 		return RVAL_DECODED | RVAL_FD;
     49 	}
     50 	if (size > sizeof(attr))
     51 		size = sizeof(attr);
     52 	if (umoven_or_printaddr(tcp, addr, size, &attr))
     53 		return RVAL_DECODED | RVAL_FD;
     54 
     55 	tprints("{map_type=");
     56 	printxval(bpf_map_types, attr.map_type, "BPF_MAP_TYPE_???");
     57 	tprintf(", key_size=%u, value_size=%u, max_entries=%u}",
     58 		attr.key_size, attr.value_size, attr.max_entries);
     59 
     60 	return RVAL_DECODED | RVAL_FD;
     61 }
     62 
     63 static void
     64 bpf_map_update_elem(struct tcb *tcp, const long addr, unsigned int size)
     65 {
     66 	struct {
     67 		uint32_t map_fd;
     68 		uint64_t ATTRIBUTE_ALIGNED(8) key;
     69 		uint64_t ATTRIBUTE_ALIGNED(8) value;
     70 		uint64_t flags;
     71 	} attr = {};
     72 
     73 	if (!size) {
     74 		printaddr(addr);
     75 		return;
     76 	}
     77 	if (size > sizeof(attr))
     78 		size = sizeof(attr);
     79 	if (umoven_or_printaddr(tcp, addr, size, &attr))
     80 		return;
     81 
     82 	tprints("{map_fd=");
     83 	printfd(tcp, attr.map_fd);
     84 	tprintf(", key=%#" PRIx64 ", value=%#" PRIx64 ", flags=",
     85 		attr.key, attr.value);
     86 	printxval(bpf_map_update_elem_flags, attr.flags, "BPF_???");
     87 	tprints("}");
     88 }
     89 
     90 static void
     91 bpf_map_delete_elem(struct tcb *tcp, const long addr, unsigned int size)
     92 {
     93 	struct {
     94 		uint32_t map_fd;
     95 		uint64_t ATTRIBUTE_ALIGNED(8) key;
     96 	} attr = {};
     97 
     98 	if (!size) {
     99 		printaddr(addr);
    100 		return;
    101 	}
    102 	if (size > sizeof(attr))
    103 		size = sizeof(attr);
    104 	if (umoven_or_printaddr(tcp, addr, size, &attr))
    105 		return;
    106 
    107 	tprints("{map_fd=");
    108 	printfd(tcp, attr.map_fd);
    109 	tprintf(", key=%#" PRIx64 "}", attr.key);
    110 }
    111 
    112 static int
    113 bpf_map_io(struct tcb *tcp, const long addr, unsigned int size, const char *text)
    114 {
    115 	struct bpf_io_elem_struct {
    116 		uint32_t map_fd;
    117 		uint64_t ATTRIBUTE_ALIGNED(8) key;
    118 		uint64_t ATTRIBUTE_ALIGNED(8) value;
    119 	} attr = {};
    120 
    121 	if (exiting(tcp)) {
    122 		if (!syserror(tcp) && !umove_or_printaddr(tcp, addr, &attr))
    123 			tprintf(", %s=%#" PRIx64, text, attr.value);
    124 		tprints("}");
    125 		return RVAL_DECODED;
    126 	}
    127 
    128 	if (!size) {
    129 		printaddr(addr);
    130 		return RVAL_DECODED;
    131 	}
    132 	if (size > sizeof(attr))
    133 		size = sizeof(attr);
    134 	if (umoven_or_printaddr(tcp, addr, size, &attr))
    135 		return RVAL_DECODED;
    136 
    137 	tprints("{map_fd=");
    138 	printfd(tcp, attr.map_fd);
    139 	tprintf(", key=%#" PRIx64, attr.key);
    140 
    141 	return 0;
    142 }
    143 
    144 static int
    145 bpf_prog_load(struct tcb *tcp, const long addr, unsigned int size)
    146 {
    147 	struct {
    148 		uint32_t prog_type, insn_cnt;
    149 		uint64_t ATTRIBUTE_ALIGNED(8) insns, license;
    150 		uint32_t log_level, log_size;
    151 		uint64_t ATTRIBUTE_ALIGNED(8) log_buf;
    152 		uint32_t kern_version;
    153 	} attr = {};
    154 
    155 	if (!size) {
    156 		printaddr(addr);
    157 		return RVAL_DECODED | RVAL_FD;
    158 	}
    159 	if (size > sizeof(attr))
    160 		size = sizeof(attr);
    161 	if (umoven_or_printaddr(tcp, addr, size, &attr))
    162 		return RVAL_DECODED | RVAL_FD;
    163 
    164 	tprints("{prog_type=");
    165 	printxval(bpf_prog_types, attr.prog_type, "BPF_PROG_TYPE_???");
    166 	tprintf(", insn_cnt=%u, insns=%#" PRIx64 ", license=",
    167 		attr.insn_cnt, attr.insns);
    168 	printstr(tcp, attr.license, -1);
    169 	tprintf(", log_level=%u, log_size=%u, log_buf=%#" PRIx64 ", kern_version=%u}",
    170 		attr.log_level, attr.log_size, attr.log_buf, attr.kern_version);
    171 
    172 	return RVAL_DECODED | RVAL_FD;
    173 }
    174 
    175 SYS_FUNC(bpf)
    176 {
    177 	const int cmd = tcp->u_arg[0];
    178 	const long addr = tcp->u_arg[1];
    179 	const unsigned int size = tcp->u_arg[2];
    180 	int rc = RVAL_DECODED;
    181 
    182 	if (entering(tcp)) {
    183 		printxval(bpf_commands, cmd, "BPF_???");
    184 		tprints(", ");
    185 	}
    186 
    187 	switch (cmd) {
    188 	case BPF_MAP_CREATE:
    189 		rc = bpf_map_create(tcp, addr, size);
    190 		break;
    191 	case BPF_MAP_LOOKUP_ELEM:
    192 		rc = bpf_map_io(tcp, addr, size, "value");
    193 		break;
    194 	case BPF_MAP_UPDATE_ELEM:
    195 		bpf_map_update_elem(tcp, addr, size);
    196 		break;
    197 	case BPF_MAP_DELETE_ELEM:
    198 		bpf_map_delete_elem(tcp, addr, size);
    199 		break;
    200 	case BPF_MAP_GET_NEXT_KEY:
    201 		rc = bpf_map_io(tcp, addr, size, "next_key");
    202 		break;
    203 	case BPF_PROG_LOAD:
    204 		rc = bpf_prog_load(tcp, addr, size);
    205 		break;
    206 	default:
    207 		printaddr(addr);
    208 		break;
    209 	}
    210 
    211 	if (rc & RVAL_DECODED)
    212 		tprintf(", %u", size);
    213 
    214 	return rc;
    215 }
    216