Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 2016 Fabien Siron <fabien.siron (at) epita.fr>
      3  * Copyright (c) 2017 JingPiao Chen <chenjingpiao (at) gmail.com>
      4  * Copyright (c) 2016-2018 The strace developers.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. The name of the author may not be used to endorse or promote products
     16  *    derived from this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 #include "defs.h"
     31 #include <endian.h>
     32 #include "netlink.h"
     33 #include "nlattr.h"
     34 #include <netinet/in.h>
     35 #include <arpa/inet.h>
     36 #include <linux/sock_diag.h>
     37 #include "static_assert.h"
     38 
     39 #include "xlat/netlink_sk_meminfo_indices.h"
     40 
     41 static bool
     42 fetch_nlattr(struct tcb *const tcp, struct nlattr *const nlattr,
     43 	     const kernel_ulong_t addr, const unsigned int len,
     44 	     const bool in_array)
     45 {
     46 	if (len < sizeof(struct nlattr)) {
     47 		printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
     48 		return false;
     49 	}
     50 
     51 	if (tfetch_obj(tcp, addr, nlattr))
     52 		return true;
     53 
     54 	if (in_array) {
     55 		tprints("...");
     56 		printaddr_comment(addr);
     57 	} else {
     58 		printaddr(addr);
     59 	}
     60 
     61 	return false;
     62 }
     63 
     64 static void
     65 print_nlattr(const struct nlattr *const nla,
     66 	     const struct xlat *const table,
     67 	     const char *const dflt)
     68 {
     69 	static_assert(NLA_TYPE_MASK == ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER),
     70 		      "wrong NLA_TYPE_MASK");
     71 
     72 	tprintf("{nla_len=%u, nla_type=", nla->nla_len);
     73 	if (nla->nla_type & NLA_F_NESTED) {
     74 		print_xlat(NLA_F_NESTED);
     75 		tprints("|");
     76 	}
     77 	if (nla->nla_type & NLA_F_NET_BYTEORDER) {
     78 		print_xlat(NLA_F_NET_BYTEORDER);
     79 		tprints("|");
     80 	}
     81 	printxval(table, nla->nla_type & NLA_TYPE_MASK, dflt);
     82 	tprints("}");
     83 }
     84 
     85 static void
     86 decode_nlattr_with_data(struct tcb *const tcp,
     87 			const struct nlattr *const nla,
     88 			const kernel_ulong_t addr,
     89 			const unsigned int len,
     90 			const struct xlat *const table,
     91 			const char *const dflt,
     92 			const nla_decoder_t *const decoders,
     93 			const unsigned int size,
     94 			const void *const opaque_data)
     95 {
     96 	const unsigned int nla_len = MIN(nla->nla_len, len);
     97 
     98 	if (nla_len > NLA_HDRLEN)
     99 		tprints("{");
    100 
    101 	print_nlattr(nla, table, dflt);
    102 
    103 	if (nla_len > NLA_HDRLEN) {
    104 		const unsigned int idx =
    105 			size ? nla->nla_type & NLA_TYPE_MASK : 0;
    106 
    107 		tprints(", ");
    108 		if (!decoders
    109 		    || (size && idx >= size)
    110 		    || !decoders[idx]
    111 		    || !decoders[idx](
    112 				tcp, addr + NLA_HDRLEN,
    113 				nla_len - NLA_HDRLEN,
    114 				size ? opaque_data
    115 				     : (const void *) (uintptr_t) nla->nla_type)
    116 		    )
    117 			printstr_ex(tcp, addr + NLA_HDRLEN,
    118 				    nla_len - NLA_HDRLEN, QUOTE_FORCE_HEX);
    119 		tprints("}");
    120 	}
    121 }
    122 
    123 void
    124 decode_nlattr(struct tcb *const tcp,
    125 	      kernel_ulong_t addr,
    126 	      unsigned int len,
    127 	      const struct xlat *const table,
    128 	      const char *const dflt,
    129 	      const nla_decoder_t *const decoders,
    130 	      const unsigned int size,
    131 	      const void *const opaque_data)
    132 {
    133 	struct nlattr nla;
    134 	bool is_array = false;
    135 	unsigned int elt;
    136 
    137 	if (decoders && !size && opaque_data)
    138 		error_func_msg("[xlat %p, dflt \"%s\", decoders %p] "
    139 			       "size is zero (going to pass nla_type as "
    140 			       "decoder argument), but opaque data (%p) is not "
    141 			       "- will be ignored",
    142 			       table, dflt, decoders, opaque_data);
    143 
    144 	for (elt = 0; fetch_nlattr(tcp, &nla, addr, len, is_array); elt++) {
    145 		if (abbrev(tcp) && elt == max_strlen) {
    146 			tprints("...");
    147 			break;
    148 		}
    149 
    150 		const unsigned int nla_len = NLA_ALIGN(nla.nla_len);
    151 		kernel_ulong_t next_addr = 0;
    152 		unsigned int next_len = 0;
    153 
    154 		if (nla.nla_len >= NLA_HDRLEN) {
    155 			next_len = (len >= nla_len) ? len - nla_len : 0;
    156 
    157 			if (next_len && addr + nla_len > addr)
    158 				next_addr = addr + nla_len;
    159 		}
    160 
    161 		if (!is_array && next_addr) {
    162 			tprints("[");
    163 			is_array = true;
    164 		}
    165 
    166 		decode_nlattr_with_data(tcp, &nla, addr, len, table, dflt,
    167 					decoders, size, opaque_data);
    168 
    169 		if (!next_addr)
    170 			break;
    171 
    172 		tprints(", ");
    173 		addr = next_addr;
    174 		len = next_len;
    175 	}
    176 
    177 	if (is_array) {
    178 		tprints("]");
    179 	}
    180 }
    181 
    182 bool
    183 decode_nla_str(struct tcb *const tcp,
    184 	       const kernel_ulong_t addr,
    185 	       const unsigned int len,
    186 	       const void *const opaque_data)
    187 {
    188 	printstr_ex(tcp, addr, len, QUOTE_0_TERMINATED);
    189 
    190 	return true;
    191 }
    192 
    193 bool
    194 decode_nla_strn(struct tcb *const tcp,
    195 		const kernel_ulong_t addr,
    196 		const unsigned int len,
    197 		const void *const opaque_data)
    198 {
    199 	printstrn(tcp, addr, len);
    200 
    201 	return true;
    202 }
    203 
    204 bool
    205 decode_nla_meminfo(struct tcb *const tcp,
    206 		   const kernel_ulong_t addr,
    207 		   const unsigned int len,
    208 		   const void *const opaque_data)
    209 {
    210 	uint32_t mem;
    211 	const size_t nmemb = len / sizeof(mem);
    212 
    213 	if (!nmemb)
    214 		return false;
    215 
    216 	unsigned int count = 0;
    217 	print_array_ex(tcp, addr, nmemb, &mem, sizeof(mem),
    218 		       tfetch_mem, print_uint32_array_member, &count,
    219 		       PAF_PRINT_INDICES | PAF_INDEX_XLAT_VALUE_INDEXED
    220 			| XLAT_STYLE_FMT_U,
    221 		       ARRSZ_PAIR(netlink_sk_meminfo_indices),
    222 		       "SK_MEMINFO_???");
    223 
    224 	return true;
    225 }
    226 
    227 bool
    228 decode_nla_fd(struct tcb *const tcp,
    229 	      const kernel_ulong_t addr,
    230 	      const unsigned int len,
    231 	      const void *const opaque_data)
    232 {
    233 	int fd;
    234 
    235 	if (len < sizeof(fd))
    236 		return false;
    237 	else if (!umove_or_printaddr(tcp, addr, &fd))
    238 		printfd(tcp, fd);
    239 
    240 	return true;
    241 }
    242 
    243 bool
    244 decode_nla_uid(struct tcb *const tcp,
    245 	       const kernel_ulong_t addr,
    246 	       const unsigned int len,
    247 	       const void *const opaque_data)
    248 {
    249 	uint32_t uid;
    250 
    251 	if (len < sizeof(uid))
    252 		return false;
    253 	else if (!umove_or_printaddr(tcp, addr, &uid))
    254 		printuid("", uid);
    255 
    256 	return true;
    257 }
    258 
    259 bool
    260 decode_nla_gid(struct tcb *const tcp,
    261 	       const kernel_ulong_t addr,
    262 	       const unsigned int len,
    263 	       const void *const opaque_data)
    264 {
    265 	return decode_nla_uid(tcp, addr, len, opaque_data);
    266 }
    267 
    268 bool
    269 decode_nla_ifindex(struct tcb *const tcp,
    270 	       const kernel_ulong_t addr,
    271 	       const unsigned int len,
    272 	       const void *const opaque_data)
    273 {
    274 	uint32_t ifindex;
    275 
    276 	if (len < sizeof(ifindex))
    277 		return false;
    278 	else if (!umove_or_printaddr(tcp, addr, &ifindex))
    279 		print_ifindex(ifindex);
    280 
    281 	return true;
    282 }
    283 
    284 bool
    285 decode_nla_xval(struct tcb *const tcp,
    286 		const kernel_ulong_t addr,
    287 		unsigned int len,
    288 		const void *const opaque_data)
    289 {
    290 	const struct decode_nla_xlat_opts * const opts = opaque_data;
    291 	union {
    292 		uint64_t val;
    293 		uint8_t  bytes[sizeof(uint64_t)];
    294 	} data = { .val = 0 };
    295 
    296 	if (len > sizeof(data) || len < opts->size)
    297 		return false;
    298 
    299 	if (opts->size)
    300 		len = MIN(len, opts->size);
    301 
    302 	const size_t bytes_offs = is_bigendian ? sizeof(data) - len : 0;
    303 
    304 	if (!umoven_or_printaddr(tcp, addr, len, data.bytes + bytes_offs)) {
    305 		if (opts->process_fn)
    306 			data.val = opts->process_fn(data.val);
    307 		if (opts->prefix)
    308 			tprints(opts->prefix);
    309 		printxval_dispatch_ex(opts->xlat, opts->xlat_size, data.val,
    310 				      opts->dflt, opts->xt, opts->style);
    311 		if (opts->suffix)
    312 			tprints(opts->suffix);
    313 	}
    314 
    315 	return true;
    316 }
    317 
    318 static uint64_t
    319 process_host_order(uint64_t val)
    320 {
    321 	return ntohs(val);
    322 }
    323 
    324 bool
    325 decode_nla_ether_proto(struct tcb *const tcp,
    326 		       const kernel_ulong_t addr,
    327 		       const unsigned int len,
    328 		       const void *const opaque_data)
    329 {
    330 	const struct decode_nla_xlat_opts opts = {
    331 		.xlat = ethernet_protocols,
    332 		.xlat_size = ethernet_protocols_size,
    333 		.dflt = "ETHER_P_???",
    334 		.xt = XT_SORTED,
    335 		.prefix = "htons(",
    336 		.suffix = ")",
    337 		.size = 2,
    338 		.process_fn = process_host_order,
    339 	};
    340 
    341 	return decode_nla_xval(tcp, addr, len, &opts);
    342 }
    343 
    344 bool
    345 decode_nla_ip_proto(struct tcb *const tcp,
    346 		    const kernel_ulong_t addr,
    347 		    const unsigned int len,
    348 		    const void *const opaque_data)
    349 {
    350 	const struct decode_nla_xlat_opts opts = {
    351 		.xlat = inet_protocols,
    352 		.xlat_size = inet_protocols_size,
    353 		.xt = XT_SORTED,
    354 		.dflt = "IPPROTO_???",
    355 		.size = 1,
    356 	};
    357 
    358 	return decode_nla_xval(tcp, addr, len, &opts);
    359 }
    360 
    361 bool
    362 decode_nla_in_addr(struct tcb *const tcp,
    363 		   const kernel_ulong_t addr,
    364 		   const unsigned int len,
    365 		   const void *const opaque_data)
    366 {
    367 	struct in_addr in;
    368 
    369 	if (len < sizeof(in))
    370 		return false;
    371 	else if (!umove_or_printaddr(tcp, addr, &in))
    372 		print_inet_addr(AF_INET, &in, sizeof(in), NULL);
    373 
    374 	return true;
    375 }
    376 
    377 bool
    378 decode_nla_in6_addr(struct tcb *const tcp,
    379 		    const kernel_ulong_t addr,
    380 		    const unsigned int len,
    381 		    const void *const opaque_data)
    382 {
    383 	struct in6_addr in6;
    384 
    385 	if (len < sizeof(in6))
    386 		return false;
    387 	else if (!umove_or_printaddr(tcp, addr, &in6))
    388 		print_inet_addr(AF_INET6, &in6, sizeof(in6), NULL);
    389 
    390 	return true;
    391 }
    392 
    393 bool
    394 decode_nla_flags(struct tcb *const tcp,
    395 		 const kernel_ulong_t addr,
    396 		 unsigned int len,
    397 		 const void *const opaque_data)
    398 {
    399 	const struct decode_nla_xlat_opts * const opts = opaque_data;
    400 	union {
    401 		uint64_t flags;
    402 		uint8_t  bytes[sizeof(uint64_t)];
    403 	} data = { .flags = 0 };
    404 
    405 	if (len > sizeof(data) || len < opts->size)
    406 		return false;
    407 
    408 	if (opts->size)
    409 		len = MIN(len, opts->size);
    410 
    411 	const size_t bytes_offs = is_bigendian ? sizeof(data) - len : 0;
    412 
    413 	if (opts->xt == XT_INDEXED)
    414 		error_func_msg("indexed xlats are currently incompatible with "
    415 			       "printflags");
    416 
    417 	if (!umoven_or_printaddr(tcp, addr, len, data.bytes + bytes_offs)) {
    418 		if (opts->process_fn)
    419 			data.flags = opts->process_fn(data.flags);
    420 		if (opts->prefix)
    421 			tprints(opts->prefix);
    422 		printflags_ex(data.flags, opts->dflt, opts->style, opts->xlat,
    423 			      NULL);
    424 		if (opts->suffix)
    425 			tprints(opts->suffix);
    426 	}
    427 
    428 	return true;
    429 }
    430 
    431 bool
    432 decode_nla_be16(struct tcb *const tcp,
    433 		const kernel_ulong_t addr,
    434 		const unsigned int len,
    435 		const void *const opaque_data)
    436 {
    437 	uint16_t num;
    438 
    439 	if (len < sizeof(num))
    440 		return false;
    441 	else if (!umove_or_printaddr(tcp, addr, &num))
    442 		tprintf("htons(%u)", ntohs(num));
    443 
    444 	return true;
    445 }
    446 
    447 bool
    448 decode_nla_be64(struct tcb *const tcp,
    449 		const kernel_ulong_t addr,
    450 		const unsigned int len,
    451 		const void *const opaque_data)
    452 {
    453 #if defined HAVE_BE64TOH || defined be64toh
    454 	uint64_t num;
    455 
    456 	if (len < sizeof(num))
    457 		return false;
    458 	else if (!umove_or_printaddr(tcp, addr, &num))
    459 		tprintf("htobe64(%" PRIu64 ")", be64toh(num));
    460 
    461 	return true;
    462 #else
    463 	return false;
    464 #endif
    465 }
    466 
    467 #define DECODE_NLA_INTEGER(name, type, fmt)		\
    468 bool							\
    469 decode_nla_ ## name(struct tcb *const tcp,		\
    470 		    const kernel_ulong_t addr,		\
    471 		    const unsigned int len,		\
    472 		    const void *const opaque_data)	\
    473 {							\
    474 	type num;					\
    475 							\
    476 	if (len < sizeof(num))				\
    477 		return false;				\
    478 	if (!umove_or_printaddr(tcp, addr, &num))	\
    479 		tprintf(fmt, num);			\
    480 	return true;					\
    481 }
    482 
    483 DECODE_NLA_INTEGER(x8, uint8_t, "%#" PRIx8)
    484 DECODE_NLA_INTEGER(x16, uint16_t, "%#" PRIx16)
    485 DECODE_NLA_INTEGER(x32, uint32_t, "%#" PRIx32)
    486 DECODE_NLA_INTEGER(x64, uint64_t, "%#" PRIx64)
    487 DECODE_NLA_INTEGER(u8, uint8_t, "%" PRIu8)
    488 DECODE_NLA_INTEGER(u16, uint16_t, "%" PRIu16)
    489 DECODE_NLA_INTEGER(u32, uint32_t, "%" PRIu32)
    490 DECODE_NLA_INTEGER(u64, uint64_t, "%" PRIu64)
    491 DECODE_NLA_INTEGER(s8, int8_t, "%" PRId8)
    492 DECODE_NLA_INTEGER(s16, int16_t, "%" PRId16)
    493 DECODE_NLA_INTEGER(s32, int32_t, "%" PRId32)
    494 DECODE_NLA_INTEGER(s64, int64_t, "%" PRId64)
    495