1 /* 2 * Copyright (c) 2016 Fabien Siron <fabien.siron (at) epita.fr> 3 * Copyright (c) 2017 JingPiao Chen <chenjingpiao (at) 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 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 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 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 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 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 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 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 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 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 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 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 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