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