]> granicus.if.org Git - strace/blob - nlattr.c
tests: check decoding of netlink smc_diag_msg attributes
[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-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                 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
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                         printstr_ex(tcp, addr + NLA_HDRLEN,
90                                     len - NLA_HDRLEN, QUOTE_FORCE_HEX);
91                 tprints("}");
92         }
93 }
94
95 void
96 decode_nlattr(struct tcb *const tcp,
97               kernel_ulong_t addr,
98               kernel_ulong_t len,
99               const struct xlat *const table,
100               const char *const dflt,
101               const nla_decoder_t *const decoders,
102               const unsigned int size,
103               const void *const opaque_data)
104 {
105         struct nlattr nla;
106         bool print_array = false;
107         unsigned int elt;
108
109         for (elt = 0; fetch_nlattr(tcp, &nla, addr, len); elt++) {
110                 if (abbrev(tcp) && elt == max_strlen) {
111                         tprints("...");
112                         break;
113                 }
114
115                 const unsigned long nla_len = NLA_ALIGN(nla.nla_len);
116                 kernel_ulong_t next_addr = 0;
117                 kernel_ulong_t next_len = 0;
118
119                 if (nla.nla_len >= NLA_HDRLEN) {
120                         next_len = (len >= nla_len) ? len - nla_len : 0;
121
122                         if (next_len && addr + nla_len > addr)
123                                 next_addr = addr + nla_len;
124                 }
125
126                 if (!print_array && next_addr) {
127                         tprints("[");
128                         print_array = true;
129                 }
130
131                 decode_nlattr_with_data(tcp, &nla, addr, len, table, dflt,
132                                         decoders, size, opaque_data);
133
134                 if (!next_addr)
135                         break;
136
137                 tprints(", ");
138                 addr = next_addr;
139                 len = next_len;
140         }
141
142         if (print_array) {
143                 tprints("]");
144         }
145 }
146
147 bool
148 decode_nla_str(struct tcb *const tcp,
149                const kernel_ulong_t addr,
150                const kernel_ulong_t len,
151                const void *const opaque_data)
152 {
153         printstr_ex(tcp, addr, len, QUOTE_0_TERMINATED);
154
155         return true;
156 }
157
158 bool
159 decode_nla_strn(struct tcb *const tcp,
160                 const kernel_ulong_t addr,
161                 const kernel_ulong_t len,
162                 const void *const opaque_data)
163 {
164         printstrn(tcp, addr, len);
165
166         return true;
167 }
168
169 #define DECODE_NLA_INTEGER(name, type, fmt)             \
170 bool                                                    \
171 decode_nla_ ## name(struct tcb *const tcp,              \
172                     const kernel_ulong_t addr,          \
173                     const kernel_ulong_t len,           \
174                     const void *const opaque_data)      \
175 {                                                       \
176         type num;                                       \
177                                                         \
178         if (len < sizeof(num))                          \
179                 return false;                           \
180         if (!umove_or_printaddr(tcp, addr, &num))       \
181                 tprintf(fmt, num);                      \
182         return true;                                    \
183 }
184
185 DECODE_NLA_INTEGER(u8, uint8_t, "%" PRIu8)
186 DECODE_NLA_INTEGER(u16, uint16_t, "%" PRIu16)
187 DECODE_NLA_INTEGER(u32, uint32_t, "%" PRIu32)
188 DECODE_NLA_INTEGER(u64, uint64_t, "%" PRIu64)
189 DECODE_NLA_INTEGER(s8, int8_t, "%" PRId8)
190 DECODE_NLA_INTEGER(s16, int16_t, "%" PRId16)
191 DECODE_NLA_INTEGER(s32, int32_t, "%" PRId32)
192 DECODE_NLA_INTEGER(s64, int64_t, "%" PRId64)