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 "netlink.h"
     32 #include "nlattr.h"
     33 
     34 static bool
     35 fetch_nlattr(struct tcb *const tcp, struct nlattr *const nlattr,
     36 	     const kernel_ulong_t addr, const kernel_ulong_t len)
     37 {
     38 	if (len < sizeof(struct nlattr)) {
     39 		printstrn(tcp, addr, len);
     40 		return false;
     41 	}
     42 
     43 	if (umove_or_printaddr(tcp, addr, nlattr))
     44 		return false;
     45 
     46 	return true;
     47 }
     48 
     49 static void
     50 print_nlattr(const struct nlattr *const nla,
     51 	     const struct xlat *const table,
     52 	     const char *const dflt)
     53 {
     54 	tprintf("{nla_len=%u, nla_type=", nla->nla_len);
     55 	if (nla->nla_type & NLA_F_NESTED)
     56 		tprints("NLA_F_NESTED|");
     57 	if (nla->nla_type & NLA_F_NET_BYTEORDER)
     58 		tprints("NLA_F_NET_BYTEORDER|");
     59 	printxval(table, nla->nla_type & NLA_TYPE_MASK, dflt);
     60 	tprints("}");
     61 }
     62 
     63 static void
     64 decode_nlattr_with_data(struct tcb *const tcp,
     65 			const struct nlattr *const nla,
     66 			const kernel_ulong_t addr,
     67 			const kernel_ulong_t len,
     68 			const struct xlat *const table,
     69 			const char *const dflt,
     70 			const nla_decoder_t *const decoders,
     71 			const unsigned int size,
     72 			const void *const opaque_data)
     73 {
     74 	const unsigned int nla_len = nla->nla_len > len ? len : nla->nla_len;
     75 
     76 	if (nla_len > NLA_HDRLEN)
     77 		tprints("{");
     78 
     79 	print_nlattr(nla, table, dflt);
     80 
     81 	if (nla_len > NLA_HDRLEN) {
     82 		tprints(", ");
     83 		if (!decoders
     84 		    || nla->nla_type >= size
     85 		    || !decoders[nla->nla_type]
     86 		    || !decoders[nla->nla_type](tcp, addr + NLA_HDRLEN,
     87 						nla_len - NLA_HDRLEN,
     88 						opaque_data))
     89 			printstrn(tcp, addr + NLA_HDRLEN, len - NLA_HDRLEN);
     90 		tprints("}");
     91 	}
     92 }
     93 
     94 void
     95 decode_nlattr(struct tcb *const tcp,
     96 	      kernel_ulong_t addr,
     97 	      kernel_ulong_t len,
     98 	      const struct xlat *const table,
     99 	      const char *const dflt,
    100 	      const nla_decoder_t *const decoders,
    101 	      const unsigned int size,
    102 	      const void *const opaque_data)
    103 {
    104 	struct nlattr nla;
    105 	bool print_array = false;
    106 	unsigned int elt;
    107 
    108 	for (elt = 0; fetch_nlattr(tcp, &nla, addr, len); elt++) {
    109 		if (abbrev(tcp) && elt == max_strlen) {
    110 			tprints("...");
    111 			break;
    112 		}
    113 
    114 		const unsigned long nla_len = NLA_ALIGN(nla.nla_len);
    115 		kernel_ulong_t next_addr = 0;
    116 		kernel_ulong_t next_len = 0;
    117 
    118 		if (nla.nla_len >= NLA_HDRLEN) {
    119 			next_len = (len >= nla_len) ? len - nla_len : 0;
    120 
    121 			if (next_len && addr + nla_len > addr)
    122 				next_addr = addr + nla_len;
    123 		}
    124 
    125 		if (!print_array && next_addr) {
    126 			tprints("[");
    127 			print_array = true;
    128 		}
    129 
    130 		decode_nlattr_with_data(tcp, &nla, addr, len, table, dflt,
    131 					decoders, size, opaque_data);
    132 
    133 		if (!next_addr)
    134 			break;
    135 
    136 		tprints(", ");
    137 		addr = next_addr;
    138 		len = next_len;
    139 	}
    140 
    141 	if (print_array) {
    142 		tprints("]");
    143 	}
    144 }
    145 
    146 bool
    147 decode_nla_str(struct tcb *const tcp,
    148 	       const kernel_ulong_t addr,
    149 	       const kernel_ulong_t len,
    150 	       const void *const opaque_data)
    151 {
    152 	printstr_ex(tcp, addr, len, QUOTE_0_TERMINATED);
    153 
    154 	return true;
    155 }
    156 
    157 bool
    158 decode_nla_strn(struct tcb *const tcp,
    159 		const kernel_ulong_t addr,
    160 		const kernel_ulong_t len,
    161 		const void *const opaque_data)
    162 {
    163 	printstrn(tcp, addr, len);
    164 
    165 	return true;
    166 }
    167 
    168 #define DECODE_NLA_INTEGER(name, type, fmt)		\
    169 bool							\
    170 decode_nla_ ## name(struct tcb *const tcp,		\
    171 		    const kernel_ulong_t addr,		\
    172 		    const kernel_ulong_t len,		\
    173 		    const void *const opaque_data)	\
    174 {							\
    175 	type num;					\
    176 							\
    177 	if (len < sizeof(num))				\
    178 		return false;				\
    179 	if (!umove_or_printaddr(tcp, addr, &num))	\
    180 		tprintf(fmt, num);			\
    181 	return true;					\
    182 }
    183 
    184 DECODE_NLA_INTEGER(u8, uint8_t, "%" PRIu8)
    185 DECODE_NLA_INTEGER(u16, uint16_t, "%" PRIu16)
    186 DECODE_NLA_INTEGER(u32, uint32_t, "%" PRIu32)
    187 DECODE_NLA_INTEGER(u64, uint64_t, "%" PRIu64)
    188 DECODE_NLA_INTEGER(s8, int8_t, "%" PRId8)
    189 DECODE_NLA_INTEGER(s16, int16_t, "%" PRId16)
    190 DECODE_NLA_INTEGER(s32, int32_t, "%" PRId32)
    191 DECODE_NLA_INTEGER(s64, int64_t, "%" PRId64)
    192