Branch data Line data Source code
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 : : #include <linux/sock_diag.h>
34 : :
35 : : static bool
36 : 260 : fetch_nlattr(struct tcb *const tcp, struct nlattr *const nlattr,
37 : : const kernel_ulong_t addr, const unsigned int len)
38 : : {
39 [ + + ]: 260 : if (len < sizeof(struct nlattr)) {
40 : 4 : printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
41 : 4 : return false;
42 : : }
43 : :
44 [ + + ]: 256 : if (umove_or_printaddr(tcp, addr, nlattr))
45 : : return false;
46 : :
47 : 252 : return true;
48 : : }
49 : :
50 : : static void
51 : 250 : print_nlattr(const struct nlattr *const nla,
52 : : const struct xlat *const table,
53 : : const char *const dflt)
54 : : {
55 : 250 : tprintf("{nla_len=%u, nla_type=", nla->nla_len);
56 [ + + ]: 250 : if (nla->nla_type & NLA_F_NESTED)
57 : 6 : tprints("NLA_F_NESTED|");
58 [ + + ]: 250 : if (nla->nla_type & NLA_F_NET_BYTEORDER)
59 : 4 : tprints("NLA_F_NET_BYTEORDER|");
60 : 250 : printxval(table, nla->nla_type & NLA_TYPE_MASK, dflt);
61 : 250 : tprints("}");
62 : 250 : }
63 : :
64 : : static void
65 : 250 : decode_nlattr_with_data(struct tcb *const tcp,
66 : : const struct nlattr *const nla,
67 : : const kernel_ulong_t addr,
68 : : const unsigned int len,
69 : : const struct xlat *const table,
70 : : const char *const dflt,
71 : : const nla_decoder_t *const decoders,
72 : : const unsigned int size,
73 : : const void *const opaque_data)
74 : : {
75 : 250 : const unsigned int nla_len = nla->nla_len > len ? len : nla->nla_len;
76 : :
77 [ + + ]: 250 : if (nla_len > NLA_HDRLEN)
78 : 164 : tprints("{");
79 : :
80 : 250 : print_nlattr(nla, table, dflt);
81 : :
82 [ + + ]: 250 : if (nla_len > NLA_HDRLEN) {
83 : 164 : tprints(", ");
84 [ + - ]: 164 : if (!decoders
85 [ + + ]: 164 : || nla->nla_type >= size
86 [ + - ]: 160 : || !decoders[nla->nla_type]
87 [ + + ]: 160 : || !decoders[nla->nla_type](tcp, addr + NLA_HDRLEN,
88 : : nla_len - NLA_HDRLEN,
89 : : opaque_data))
90 : 38 : printstr_ex(tcp, addr + NLA_HDRLEN,
91 : 38 : len - NLA_HDRLEN, QUOTE_FORCE_HEX);
92 : 164 : tprints("}");
93 : : }
94 : 250 : }
95 : :
96 : : void
97 : 190 : decode_nlattr(struct tcb *const tcp,
98 : : kernel_ulong_t addr,
99 : : unsigned int len,
100 : : const struct xlat *const table,
101 : : const char *const dflt,
102 : : const nla_decoder_t *const decoders,
103 : : const unsigned int size,
104 : : const void *const opaque_data)
105 : : {
106 : : struct nlattr nla;
107 : 190 : bool print_array = false;
108 : : unsigned int elt;
109 : :
110 [ + + ]: 260 : for (elt = 0; fetch_nlattr(tcp, &nla, addr, len); elt++) {
111 [ + + ][ + + ]: 252 : if (abbrev(tcp) && elt == max_strlen) {
112 : 2 : tprints("...");
113 : 2 : break;
114 : : }
115 : :
116 : 250 : const unsigned int nla_len = NLA_ALIGN(nla.nla_len);
117 : 250 : kernel_ulong_t next_addr = 0;
118 : 250 : unsigned int next_len = 0;
119 : :
120 [ + + ]: 250 : if (nla.nla_len >= NLA_HDRLEN) {
121 [ + + ]: 248 : next_len = (len >= nla_len) ? len - nla_len : 0;
122 : :
123 [ + + ][ + - ]: 248 : if (next_len && addr + nla_len > addr)
124 : 70 : next_addr = addr + nla_len;
125 : : }
126 : :
127 [ + + ]: 250 : if (!print_array && next_addr) {
128 : 8 : tprints("[");
129 : 8 : print_array = true;
130 : : }
131 : :
132 : 250 : decode_nlattr_with_data(tcp, &nla, addr, len, table, dflt,
133 : : decoders, size, opaque_data);
134 : :
135 [ + + ]: 250 : if (!next_addr)
136 : : break;
137 : :
138 : 70 : tprints(", ");
139 : 70 : addr = next_addr;
140 : 70 : len = next_len;
141 : : }
142 : :
143 [ + + ]: 190 : if (print_array) {
144 : 8 : tprints("]");
145 : : }
146 : 190 : }
147 : :
148 : : bool
149 : 4 : decode_nla_str(struct tcb *const tcp,
150 : : const kernel_ulong_t addr,
151 : : const unsigned int len,
152 : : const void *const opaque_data)
153 : : {
154 : 4 : printstr_ex(tcp, addr, len, QUOTE_0_TERMINATED);
155 : :
156 : 4 : return true;
157 : : }
158 : :
159 : : bool
160 : 0 : decode_nla_strn(struct tcb *const tcp,
161 : : const kernel_ulong_t addr,
162 : : const unsigned int len,
163 : : const void *const opaque_data)
164 : : {
165 : 0 : printstrn(tcp, addr, len);
166 : :
167 : 0 : return true;
168 : : }
169 : :
170 : : static bool
171 : 28 : print_meminfo(struct tcb *const tcp,
172 : : void *const elem_buf,
173 : : const size_t elem_size,
174 : : void *const opaque_data)
175 : : {
176 : 28 : unsigned int *const count = opaque_data;
177 : :
178 [ + + ]: 28 : if ((*count)++ >= SK_MEMINFO_VARS) {
179 : 2 : tprints("...");
180 : 2 : return false;
181 : : }
182 : :
183 : 26 : tprintf("%" PRIu32, *(uint32_t *) elem_buf);
184 : :
185 : 26 : return true;
186 : : }
187 : :
188 : : bool
189 : 10 : decode_nla_meminfo(struct tcb *const tcp,
190 : : const kernel_ulong_t addr,
191 : : const unsigned int len,
192 : : const void *const opaque_data)
193 : : {
194 : : uint32_t mem;
195 : 10 : const size_t nmemb = len / sizeof(mem);
196 : :
197 [ + + ]: 10 : if (!nmemb)
198 : : return false;
199 : :
200 : 8 : unsigned int count = 0;
201 : 8 : print_array(tcp, addr, nmemb, &mem, sizeof(mem),
202 : : umoven_or_printaddr, print_meminfo, &count);
203 : :
204 : 8 : return true;
205 : : }
206 : :
207 : : #define DECODE_NLA_INTEGER(name, type, fmt) \
208 : : bool \
209 : : decode_nla_ ## name(struct tcb *const tcp, \
210 : : const kernel_ulong_t addr, \
211 : : const unsigned int len, \
212 : : const void *const opaque_data) \
213 : : { \
214 : : type num; \
215 : : \
216 : : if (len < sizeof(num)) \
217 : : return false; \
218 : : if (!umove_or_printaddr(tcp, addr, &num)) \
219 : : tprintf(fmt, num); \
220 : : return true; \
221 : : }
222 : :
223 [ + - ][ + - ]: 4 : DECODE_NLA_INTEGER(u8, uint8_t, "%" PRIu8)
224 [ # # ][ # # ]: 0 : DECODE_NLA_INTEGER(u16, uint16_t, "%" PRIu16)
225 [ + + ][ + + ]: 12 : DECODE_NLA_INTEGER(u32, uint32_t, "%" PRIu32)
226 [ # # ][ # # ]: 0 : DECODE_NLA_INTEGER(u64, uint64_t, "%" PRIu64)
227 [ # # ][ # # ]: 0 : DECODE_NLA_INTEGER(s8, int8_t, "%" PRId8)
228 [ # # ][ # # ]: 0 : DECODE_NLA_INTEGER(s16, int16_t, "%" PRId16)
229 [ # # ][ # # ]: 0 : DECODE_NLA_INTEGER(s32, int32_t, "%" PRId32)
230 [ # # ][ # # ]: 0 : DECODE_NLA_INTEGER(s64, int64_t, "%" PRId64)
|