]> granicus.if.org Git - strace/blob - nlattr.c
Add PAF_ARRAY_TRUNCATED flag for print_array_ex
[strace] / nlattr.c
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  * SPDX-License-Identifier: LGPL-2.1-or-later
8  */
9
10 #include "defs.h"
11 #include <endian.h>
12 #include "netlink.h"
13 #include "nlattr.h"
14 #include <netinet/in.h>
15 #include <arpa/inet.h>
16 #include <linux/sock_diag.h>
17 #include "static_assert.h"
18
19 #include "xlat/netlink_sk_meminfo_indices.h"
20
21 static bool
22 fetch_nlattr(struct tcb *const tcp, struct nlattr *const nlattr,
23              const kernel_ulong_t addr, const unsigned int len,
24              const bool in_array)
25 {
26         if (len < sizeof(struct nlattr)) {
27                 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
28                 return false;
29         }
30
31         if (tfetch_obj(tcp, addr, nlattr))
32                 return true;
33
34         if (in_array) {
35                 tprints("...");
36                 printaddr_comment(addr);
37         } else {
38                 printaddr(addr);
39         }
40
41         return false;
42 }
43
44 static void
45 print_nlattr(const struct nlattr *const nla,
46              const struct xlat *const table,
47              const char *const dflt)
48 {
49         static_assert(NLA_TYPE_MASK == ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER),
50                       "wrong NLA_TYPE_MASK");
51
52         tprintf("{nla_len=%u, nla_type=", nla->nla_len);
53         if (nla->nla_type & NLA_F_NESTED) {
54                 print_xlat(NLA_F_NESTED);
55                 tprints("|");
56         }
57         if (nla->nla_type & NLA_F_NET_BYTEORDER) {
58                 print_xlat(NLA_F_NET_BYTEORDER);
59                 tprints("|");
60         }
61         printxval(table, nla->nla_type & NLA_TYPE_MASK, dflt);
62         tprints("}");
63 }
64
65 static void
66 decode_nlattr_with_data(struct tcb *const tcp,
67                         const struct nlattr *const nla,
68                         const kernel_ulong_t addr,
69                         const unsigned int len,
70                         const struct xlat *const table,
71                         const char *const dflt,
72                         const nla_decoder_t *const decoders,
73                         const unsigned int size,
74                         const void *const opaque_data)
75 {
76         const unsigned int nla_len = MIN(nla->nla_len, len);
77
78         if (nla_len > NLA_HDRLEN)
79                 tprints("{");
80
81         print_nlattr(nla, table, dflt);
82
83         if (nla_len > NLA_HDRLEN) {
84                 const unsigned int idx =
85                         size ? nla->nla_type & NLA_TYPE_MASK : 0;
86
87                 tprints(", ");
88                 if (!decoders
89                     || (size && idx >= size)
90                     || !decoders[idx]
91                     || !decoders[idx](
92                                 tcp, addr + NLA_HDRLEN,
93                                 nla_len - NLA_HDRLEN,
94                                 size ? opaque_data
95                                      : (const void *) (uintptr_t) nla->nla_type)
96                     )
97                         printstr_ex(tcp, addr + NLA_HDRLEN,
98                                     nla_len - NLA_HDRLEN, QUOTE_FORCE_HEX);
99                 tprints("}");
100         }
101 }
102
103 void
104 decode_nlattr(struct tcb *const tcp,
105               kernel_ulong_t addr,
106               unsigned int len,
107               const struct xlat *const table,
108               const char *const dflt,
109               const nla_decoder_t *const decoders,
110               const unsigned int size,
111               const void *const opaque_data)
112 {
113         struct nlattr nla;
114         bool is_array = false;
115         unsigned int elt;
116
117         if (decoders && !size && opaque_data)
118                 error_func_msg("[xlat %p, dflt \"%s\", decoders %p] "
119                                "size is zero (going to pass nla_type as "
120                                "decoder argument), but opaque data (%p) is not "
121                                "- will be ignored",
122                                table, dflt, decoders, opaque_data);
123
124         for (elt = 0; fetch_nlattr(tcp, &nla, addr, len, is_array); elt++) {
125                 if (abbrev(tcp) && elt == max_strlen) {
126                         tprints("...");
127                         break;
128                 }
129
130                 const unsigned int nla_len = NLA_ALIGN(nla.nla_len);
131                 kernel_ulong_t next_addr = 0;
132                 unsigned int next_len = 0;
133
134                 if (nla.nla_len >= NLA_HDRLEN) {
135                         next_len = (len >= nla_len) ? len - nla_len : 0;
136
137                         if (next_len && addr + nla_len > addr)
138                                 next_addr = addr + nla_len;
139                 }
140
141                 if (!is_array && next_addr) {
142                         tprints("[");
143                         is_array = true;
144                 }
145
146                 decode_nlattr_with_data(tcp, &nla, addr, len, table, dflt,
147                                         decoders, size, opaque_data);
148
149                 if (!next_addr)
150                         break;
151
152                 tprints(", ");
153                 addr = next_addr;
154                 len = next_len;
155         }
156
157         if (is_array) {
158                 tprints("]");
159         }
160 }
161
162 bool
163 decode_nla_str(struct tcb *const tcp,
164                const kernel_ulong_t addr,
165                const unsigned int len,
166                const void *const opaque_data)
167 {
168         printstr_ex(tcp, addr, len, QUOTE_0_TERMINATED);
169
170         return true;
171 }
172
173 bool
174 decode_nla_strn(struct tcb *const tcp,
175                 const kernel_ulong_t addr,
176                 const unsigned int len,
177                 const void *const opaque_data)
178 {
179         printstrn(tcp, addr, len);
180
181         return true;
182 }
183
184 bool
185 decode_nla_meminfo(struct tcb *const tcp,
186                    const kernel_ulong_t addr,
187                    const unsigned int len,
188                    const void *const opaque_data)
189 {
190         uint32_t mem;
191         const size_t nmemb = len / sizeof(mem);
192
193         if (!nmemb)
194                 return false;
195
196         unsigned int count = 0;
197         print_array_ex(tcp, addr, nmemb, &mem, sizeof(mem),
198                        tfetch_mem, print_uint32_array_member, &count,
199                        PAF_PRINT_INDICES | XLAT_STYLE_FMT_U,
200                        netlink_sk_meminfo_indices, "SK_MEMINFO_???");
201
202         return true;
203 }
204
205 bool
206 decode_nla_fd(struct tcb *const tcp,
207               const kernel_ulong_t addr,
208               const unsigned int len,
209               const void *const opaque_data)
210 {
211         int fd;
212
213         if (len < sizeof(fd))
214                 return false;
215         else if (!umove_or_printaddr(tcp, addr, &fd))
216                 printfd(tcp, fd);
217
218         return true;
219 }
220
221 bool
222 decode_nla_uid(struct tcb *const tcp,
223                const kernel_ulong_t addr,
224                const unsigned int len,
225                const void *const opaque_data)
226 {
227         uint32_t uid;
228
229         if (len < sizeof(uid))
230                 return false;
231         else if (!umove_or_printaddr(tcp, addr, &uid))
232                 printuid("", uid);
233
234         return true;
235 }
236
237 bool
238 decode_nla_gid(struct tcb *const tcp,
239                const kernel_ulong_t addr,
240                const unsigned int len,
241                const void *const opaque_data)
242 {
243         return decode_nla_uid(tcp, addr, len, opaque_data);
244 }
245
246 bool
247 decode_nla_ifindex(struct tcb *const tcp,
248                const kernel_ulong_t addr,
249                const unsigned int len,
250                const void *const opaque_data)
251 {
252         uint32_t ifindex;
253
254         if (len < sizeof(ifindex))
255                 return false;
256         else if (!umove_or_printaddr(tcp, addr, &ifindex))
257                 print_ifindex(ifindex);
258
259         return true;
260 }
261
262 bool
263 decode_nla_xval(struct tcb *const tcp,
264                 const kernel_ulong_t addr,
265                 unsigned int len,
266                 const void *const opaque_data)
267 {
268         const struct decode_nla_xlat_opts * const opts = opaque_data;
269         union {
270                 uint64_t val;
271                 uint8_t  bytes[sizeof(uint64_t)];
272         } data = { .val = 0 };
273
274         if (len > sizeof(data) || len < opts->size)
275                 return false;
276
277         if (opts->size)
278                 len = MIN(len, opts->size);
279
280         const size_t bytes_offs = is_bigendian ? sizeof(data) - len : 0;
281
282         if (!umoven_or_printaddr(tcp, addr, len, data.bytes + bytes_offs)) {
283                 if (opts->process_fn)
284                         data.val = opts->process_fn(data.val);
285                 if (opts->prefix)
286                         tprints(opts->prefix);
287                 printxval_ex(opts->xlat, data.val, opts->dflt, opts->style);
288                 if (opts->suffix)
289                         tprints(opts->suffix);
290         }
291
292         return true;
293 }
294
295 static uint64_t
296 process_host_order(uint64_t val)
297 {
298         return ntohs(val);
299 }
300
301 bool
302 decode_nla_ether_proto(struct tcb *const tcp,
303                        const kernel_ulong_t addr,
304                        const unsigned int len,
305                        const void *const opaque_data)
306 {
307         static const struct decode_nla_xlat_opts opts = {
308                 .xlat = ethernet_protocols,
309                 .dflt = "ETHER_P_???",
310                 .prefix = "htons(",
311                 .suffix = ")",
312                 .size = 2,
313                 .process_fn = process_host_order,
314         };
315
316         return decode_nla_xval(tcp, addr, len, &opts);
317 }
318
319 bool
320 decode_nla_ip_proto(struct tcb *const tcp,
321                     const kernel_ulong_t addr,
322                     const unsigned int len,
323                     const void *const opaque_data)
324 {
325         static const struct decode_nla_xlat_opts opts = {
326                 .xlat = inet_protocols,
327                 .dflt = "IPPROTO_???",
328                 .size = 1,
329         };
330
331         return decode_nla_xval(tcp, addr, len, &opts);
332 }
333
334 bool
335 decode_nla_in_addr(struct tcb *const tcp,
336                    const kernel_ulong_t addr,
337                    const unsigned int len,
338                    const void *const opaque_data)
339 {
340         struct in_addr in;
341
342         if (len < sizeof(in))
343                 return false;
344         else if (!umove_or_printaddr(tcp, addr, &in))
345                 print_inet_addr(AF_INET, &in, sizeof(in), NULL);
346
347         return true;
348 }
349
350 bool
351 decode_nla_in6_addr(struct tcb *const tcp,
352                     const kernel_ulong_t addr,
353                     const unsigned int len,
354                     const void *const opaque_data)
355 {
356         struct in6_addr in6;
357
358         if (len < sizeof(in6))
359                 return false;
360         else if (!umove_or_printaddr(tcp, addr, &in6))
361                 print_inet_addr(AF_INET6, &in6, sizeof(in6), NULL);
362
363         return true;
364 }
365
366 bool
367 decode_nla_flags(struct tcb *const tcp,
368                  const kernel_ulong_t addr,
369                  unsigned int len,
370                  const void *const opaque_data)
371 {
372         const struct decode_nla_xlat_opts * const opts = opaque_data;
373         union {
374                 uint64_t flags;
375                 uint8_t  bytes[sizeof(uint64_t)];
376         } data = { .flags = 0 };
377
378         if (len > sizeof(data) || len < opts->size)
379                 return false;
380
381         if (opts->size)
382                 len = MIN(len, opts->size);
383
384         const size_t bytes_offs = is_bigendian ? sizeof(data) - len : 0;
385
386         if (!umoven_or_printaddr(tcp, addr, len, data.bytes + bytes_offs)) {
387                 if (opts->process_fn)
388                         data.flags = opts->process_fn(data.flags);
389                 if (opts->prefix)
390                         tprints(opts->prefix);
391                 printflags_ex(data.flags, opts->dflt, opts->style, opts->xlat,
392                               NULL);
393                 if (opts->suffix)
394                         tprints(opts->suffix);
395         }
396
397         return true;
398 }
399
400 bool
401 decode_nla_be16(struct tcb *const tcp,
402                 const kernel_ulong_t addr,
403                 const unsigned int len,
404                 const void *const opaque_data)
405 {
406         uint16_t num;
407
408         if (len < sizeof(num))
409                 return false;
410         else if (!umove_or_printaddr(tcp, addr, &num))
411                 tprintf("htons(%u)", ntohs(num));
412
413         return true;
414 }
415
416 bool
417 decode_nla_be64(struct tcb *const tcp,
418                 const kernel_ulong_t addr,
419                 const unsigned int len,
420                 const void *const opaque_data)
421 {
422 #if defined HAVE_BE64TOH || defined be64toh
423         uint64_t num;
424
425         if (len < sizeof(num))
426                 return false;
427         else if (!umove_or_printaddr(tcp, addr, &num))
428                 tprintf("htobe64(%" PRIu64 ")", be64toh(num));
429
430         return true;
431 #else
432         return false;
433 #endif
434 }
435
436 #define DECODE_NLA_INTEGER(name, type, fmt)             \
437 bool                                                    \
438 decode_nla_ ## name(struct tcb *const tcp,              \
439                     const kernel_ulong_t addr,          \
440                     const unsigned int len,             \
441                     const void *const opaque_data)      \
442 {                                                       \
443         type num;                                       \
444                                                         \
445         if (len < sizeof(num))                          \
446                 return false;                           \
447         if (!umove_or_printaddr(tcp, addr, &num))       \
448                 tprintf(fmt, num);                      \
449         return true;                                    \
450 }
451
452 DECODE_NLA_INTEGER(x8, uint8_t, "%#" PRIx8)
453 DECODE_NLA_INTEGER(x16, uint16_t, "%#" PRIx16)
454 DECODE_NLA_INTEGER(x32, uint32_t, "%#" PRIx32)
455 DECODE_NLA_INTEGER(x64, uint64_t, "%#" PRIx64)
456 DECODE_NLA_INTEGER(u8, uint8_t, "%" PRIu8)
457 DECODE_NLA_INTEGER(u16, uint16_t, "%" PRIu16)
458 DECODE_NLA_INTEGER(u32, uint32_t, "%" PRIu32)
459 DECODE_NLA_INTEGER(u64, uint64_t, "%" PRIu64)
460 DECODE_NLA_INTEGER(s8, int8_t, "%" PRId8)
461 DECODE_NLA_INTEGER(s16, int16_t, "%" PRId16)
462 DECODE_NLA_INTEGER(s32, int32_t, "%" PRId32)
463 DECODE_NLA_INTEGER(s64, int64_t, "%" PRId64)