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-2017 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 
     38 static bool
     39 fetch_nlattr(struct tcb *const tcp, struct nlattr *const nlattr,
     40 	     const kernel_ulong_t addr, const unsigned int len)
     41 {
     42 	if (len < sizeof(struct nlattr)) {
     43 		printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
     44 		return false;
     45 	}
     46 
     47 	if (umove_or_printaddr(tcp, addr, nlattr))
     48 		return false;
     49 
     50 	return true;
     51 }
     52 
     53 static void
     54 print_nlattr(const struct nlattr *const nla,
     55 	     const struct xlat *const table,
     56 	     const char *const dflt)
     57 {
     58 	tprintf("{nla_len=%u, nla_type=", nla->nla_len);
     59 	if (nla->nla_type & NLA_F_NESTED)
     60 		tprints("NLA_F_NESTED|");
     61 	if (nla->nla_type & NLA_F_NET_BYTEORDER)
     62 		tprints("NLA_F_NET_BYTEORDER|");
     63 	printxval(table, nla->nla_type & NLA_TYPE_MASK, dflt);
     64 	tprints("}");
     65 }
     66 
     67 static void
     68 decode_nlattr_with_data(struct tcb *const tcp,
     69 			const struct nlattr *const nla,
     70 			const kernel_ulong_t addr,
     71 			const unsigned int len,
     72 			const struct xlat *const table,
     73 			const char *const dflt,
     74 			const nla_decoder_t *const decoders,
     75 			const unsigned int size,
     76 			const void *const opaque_data)
     77 {
     78 	const unsigned int nla_len = nla->nla_len > len ? len : nla->nla_len;
     79 
     80 	if (nla_len > NLA_HDRLEN)
     81 		tprints("{");
     82 
     83 	print_nlattr(nla, table, dflt);
     84 
     85 	if (nla_len > NLA_HDRLEN) {
     86 		tprints(", ");
     87 		if (!decoders
     88 		    || nla->nla_type >= size
     89 		    || !decoders[nla->nla_type]
     90 		    || !decoders[nla->nla_type](tcp, addr + NLA_HDRLEN,
     91 						nla_len - NLA_HDRLEN,
     92 						opaque_data))
     93 			printstr_ex(tcp, addr + NLA_HDRLEN,
     94 				    nla_len - NLA_HDRLEN, QUOTE_FORCE_HEX);
     95 		tprints("}");
     96 	}
     97 }
     98 
     99 void
    100 decode_nlattr(struct tcb *const tcp,
    101 	      kernel_ulong_t addr,
    102 	      unsigned int len,
    103 	      const struct xlat *const table,
    104 	      const char *const dflt,
    105 	      const nla_decoder_t *const decoders,
    106 	      const unsigned int size,
    107 	      const void *const opaque_data)
    108 {
    109 	struct nlattr nla;
    110 	bool print_array = false;
    111 	unsigned int elt;
    112 
    113 	for (elt = 0; fetch_nlattr(tcp, &nla, addr, len); elt++) {
    114 		if (abbrev(tcp) && elt == max_strlen) {
    115 			tprints("...");
    116 			break;
    117 		}
    118 
    119 		const unsigned int nla_len = NLA_ALIGN(nla.nla_len);
    120 		kernel_ulong_t next_addr = 0;
    121 		unsigned int next_len = 0;
    122 
    123 		if (nla.nla_len >= NLA_HDRLEN) {
    124 			next_len = (len >= nla_len) ? len - nla_len : 0;
    125 
    126 			if (next_len && addr + nla_len > addr)
    127 				next_addr = addr + nla_len;
    128 		}
    129 
    130 		if (!print_array && next_addr) {
    131 			tprints("[");
    132 			print_array = true;
    133 		}
    134 
    135 		decode_nlattr_with_data(tcp, &nla, addr, len, table, dflt,
    136 					decoders, size, opaque_data);
    137 
    138 		if (!next_addr)
    139 			break;
    140 
    141 		tprints(", ");
    142 		addr = next_addr;
    143 		len = next_len;
    144 	}
    145 
    146 	if (print_array) {
    147 		tprints("]");
    148 	}
    149 }
    150 
    151 bool
    152 decode_nla_str(struct tcb *const tcp,
    153 	       const kernel_ulong_t addr,
    154 	       const unsigned int len,
    155 	       const void *const opaque_data)
    156 {
    157 	printstr_ex(tcp, addr, len, QUOTE_0_TERMINATED);
    158 
    159 	return true;
    160 }
    161 
    162 bool
    163 decode_nla_strn(struct tcb *const tcp,
    164 		const kernel_ulong_t addr,
    165 		const unsigned int len,
    166 		const void *const opaque_data)
    167 {
    168 	printstrn(tcp, addr, len);
    169 
    170 	return true;
    171 }
    172 
    173 static bool
    174 print_meminfo(struct tcb *const tcp,
    175 	      void *const elem_buf,
    176 	      const size_t elem_size,
    177 	      void *const opaque_data)
    178 {
    179 	unsigned int *const count = opaque_data;
    180 
    181 	if ((*count)++ >= SK_MEMINFO_VARS) {
    182 		tprints("...");
    183 		return false;
    184 	}
    185 
    186 	tprintf("%" PRIu32, *(uint32_t *) elem_buf);
    187 
    188 	return true;
    189 }
    190 
    191 bool
    192 decode_nla_meminfo(struct tcb *const tcp,
    193 		   const kernel_ulong_t addr,
    194 		   const unsigned int len,
    195 		   const void *const opaque_data)
    196 {
    197 	uint32_t mem;
    198 	const size_t nmemb = len / sizeof(mem);
    199 
    200 	if (!nmemb)
    201 		return false;
    202 
    203 	unsigned int count = 0;
    204 	print_array(tcp, addr, nmemb, &mem, sizeof(mem),
    205 		    umoven_or_printaddr, print_meminfo, &count);
    206 
    207 	return true;
    208 }
    209 
    210 bool
    211 decode_nla_fd(struct tcb *const tcp,
    212 	      const kernel_ulong_t addr,
    213 	      const unsigned int len,
    214 	      const void *const opaque_data)
    215 {
    216 	int fd;
    217 
    218 	if (len < sizeof(fd))
    219 		return false;
    220 	else if (!umove_or_printaddr(tcp, addr, &fd))
    221 		printfd(tcp, fd);
    222 
    223 	return true;
    224 }
    225 
    226 bool
    227 decode_nla_ifindex(struct tcb *const tcp,
    228 	       const kernel_ulong_t addr,
    229 	       const unsigned int len,
    230 	       const void *const opaque_data)
    231 {
    232 	uint32_t ifindex;
    233 
    234 	if (len < sizeof(ifindex))
    235 		return false;
    236 	else if (!umove_or_printaddr(tcp, addr, &ifindex))
    237 		print_ifindex(ifindex);
    238 
    239 	return true;
    240 }
    241 
    242 bool
    243 decode_nla_be16(struct tcb *const tcp,
    244 		const kernel_ulong_t addr,
    245 		const unsigned int len,
    246 		const void *const opaque_data)
    247 {
    248 	uint16_t num;
    249 
    250 	if (len < sizeof(num))
    251 		return false;
    252 	else if (!umove_or_printaddr(tcp, addr, &num))
    253 		tprintf("htons(%u)", ntohs(num));
    254 
    255 	return true;
    256 }
    257 
    258 bool
    259 decode_nla_be64(struct tcb *const tcp,
    260 		const kernel_ulong_t addr,
    261 		const unsigned int len,
    262 		const void *const opaque_data)
    263 {
    264 #if defined HAVE_BE64TOH || defined be64toh
    265 	uint64_t num;
    266 
    267 	if (len < sizeof(num))
    268 		return false;
    269 	else if (!umove_or_printaddr(tcp, addr, &num))
    270 		tprintf("htobe64(%" PRIu64 ")", be64toh(num));
    271 
    272 	return true;
    273 #else
    274 	return false;
    275 #endif
    276 }
    277 
    278 #define DECODE_NLA_INTEGER(name, type, fmt)		\
    279 bool							\
    280 decode_nla_ ## name(struct tcb *const tcp,		\
    281 		    const kernel_ulong_t addr,		\
    282 		    const unsigned int len,		\
    283 		    const void *const opaque_data)	\
    284 {							\
    285 	type num;					\
    286 							\
    287 	if (len < sizeof(num))				\
    288 		return false;				\
    289 	if (!umove_or_printaddr(tcp, addr, &num))	\
    290 		tprintf(fmt, num);			\
    291 	return true;					\
    292 }
    293 
    294 DECODE_NLA_INTEGER(u8, uint8_t, "%" PRIu8)
    295 DECODE_NLA_INTEGER(u16, uint16_t, "%" PRIu16)
    296 DECODE_NLA_INTEGER(u32, uint32_t, "%" PRIu32)
    297 DECODE_NLA_INTEGER(u64, uint64_t, "%" PRIu64)
    298 DECODE_NLA_INTEGER(s8, int8_t, "%" PRId8)
    299 DECODE_NLA_INTEGER(s16, int16_t, "%" PRId16)
    300 DECODE_NLA_INTEGER(s32, int32_t, "%" PRId32)
    301 DECODE_NLA_INTEGER(s64, int64_t, "%" PRId64)
    302