• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3  * Copyright (c) 2017 JingPiao Chen <chenjingpiao@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
fetch_nlattr(struct tcb * const tcp,struct nlattr * const nlattr,const kernel_ulong_t addr,const unsigned int len)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
print_nlattr(const struct nlattr * const nla,const struct xlat * const table,const char * const dflt)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
decode_nlattr_with_data(struct tcb * const tcp,const struct nlattr * const nla,const kernel_ulong_t addr,const unsigned int len,const struct xlat * const table,const char * const dflt,const nla_decoder_t * const decoders,const unsigned int size,const void * const opaque_data)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
decode_nlattr(struct tcb * const tcp,kernel_ulong_t addr,unsigned int len,const struct xlat * const table,const char * const dflt,const nla_decoder_t * const decoders,const unsigned int size,const void * const opaque_data)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
decode_nla_str(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_strn(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
print_meminfo(struct tcb * const tcp,void * const elem_buf,const size_t elem_size,void * const opaque_data)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
decode_nla_meminfo(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_fd(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_ifindex(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_be16(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_be64(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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