1 /*
2 * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3 * Copyright (c) 2017 JingPiao Chen <chenjingpiao@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
fetch_nlattr(struct tcb * const tcp,struct nlattr * const nlattr,const kernel_ulong_t addr,const unsigned int len,const bool in_array)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
print_nlattr(const struct nlattr * const nla,const struct xlat * const table,const char * const dflt)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
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)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
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)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
decode_nla_str(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_strn(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_meminfo(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_fd(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_uid(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_gid(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_ifindex(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_xval(struct tcb * const tcp,const kernel_ulong_t addr,unsigned int len,const void * const opaque_data)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
process_host_order(uint64_t val)319 process_host_order(uint64_t val)
320 {
321 return ntohs(val);
322 }
323
324 bool
decode_nla_ether_proto(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_ip_proto(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_in_addr(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_in6_addr(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_flags(struct tcb * const tcp,const kernel_ulong_t addr,unsigned int len,const void * const opaque_data)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
decode_nla_be16(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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
decode_nla_be64(struct tcb * const tcp,const kernel_ulong_t addr,const unsigned int len,const void * const opaque_data)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