1 /* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com> 5 * Copyright (c) 1996-2000 Wichert Akkerman <wichert (at) cistron.nl> 6 * Copyright (c) 2005-2016 Dmitry V. Levin <ldv (at) altlinux.org> 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "defs.h" 33 #include "msghdr.h" 34 #include <limits.h> 35 #include <arpa/inet.h> 36 #include <netinet/in.h> 37 38 #include "xlat/msg_flags.h" 39 #include "xlat/scmvals.h" 40 #include "xlat/ip_cmsg_types.h" 41 42 #ifndef current_wordsize 43 struct cmsghdr32 { 44 uint32_t cmsg_len; 45 int cmsg_level; 46 int cmsg_type; 47 }; 48 #endif 49 50 typedef union { 51 char *ptr; 52 struct cmsghdr *cmsg; 53 #ifndef current_wordsize 54 struct cmsghdr32 *cmsg32; 55 #endif 56 } union_cmsghdr; 57 58 static void 59 print_scm_rights(struct tcb *tcp, const void *cmsg_data, 60 const unsigned int data_len) 61 { 62 const int *fds = cmsg_data; 63 const unsigned int nfds = data_len / sizeof(*fds); 64 unsigned int i; 65 66 tprints("["); 67 68 for (i = 0; i < nfds; ++i) { 69 if (i) 70 tprints(", "); 71 if (abbrev(tcp) && i >= max_strlen) { 72 tprints("..."); 73 break; 74 } 75 printfd(tcp, fds[i]); 76 } 77 78 tprints("]"); 79 } 80 81 static void 82 print_scm_creds(struct tcb *tcp, const void *cmsg_data, 83 const unsigned int data_len) 84 { 85 const struct ucred *uc = cmsg_data; 86 87 tprintf("{pid=%u, uid=%u, gid=%u}", 88 (unsigned) uc->pid, (unsigned) uc->uid, (unsigned) uc->gid); 89 } 90 91 static void 92 print_scm_security(struct tcb *tcp, const void *cmsg_data, 93 const unsigned int data_len) 94 { 95 print_quoted_string(cmsg_data, data_len, 0); 96 } 97 98 static void 99 print_cmsg_ip_pktinfo(struct tcb *tcp, const void *cmsg_data, 100 const unsigned int data_len) 101 { 102 const struct in_pktinfo *info = cmsg_data; 103 104 tprints("{ipi_ifindex="); 105 print_ifindex(info->ipi_ifindex); 106 tprintf(", ipi_spec_dst=inet_addr(\"%s\")", 107 inet_ntoa(info->ipi_spec_dst)); 108 tprintf(", ipi_addr=inet_addr(\"%s\")}", 109 inet_ntoa(info->ipi_addr)); 110 } 111 112 static void 113 print_cmsg_uint(struct tcb *tcp, const void *cmsg_data, 114 const unsigned int data_len) 115 { 116 const unsigned int *p = cmsg_data; 117 118 tprintf("[%u]", *p); 119 } 120 121 static void 122 print_cmsg_uint8_t(struct tcb *tcp, const void *cmsg_data, 123 const unsigned int data_len) 124 { 125 const uint8_t *p = cmsg_data; 126 127 tprintf("[%#x]", *p); 128 } 129 130 static void 131 print_cmsg_ip_opts(struct tcb *tcp, const void *cmsg_data, 132 const unsigned int data_len) 133 { 134 const unsigned char *opts = cmsg_data; 135 unsigned int i; 136 137 tprints("["); 138 for (i = 0; i < data_len; ++i) { 139 if (i) 140 tprints(", "); 141 if (abbrev(tcp) && i >= max_strlen) { 142 tprints("..."); 143 break; 144 } 145 tprintf("0x%02x", opts[i]); 146 } 147 tprints("]"); 148 } 149 150 struct sock_ee { 151 uint32_t ee_errno; 152 uint8_t ee_origin; 153 uint8_t ee_type; 154 uint8_t ee_code; 155 uint8_t ee_pad; 156 uint32_t ee_info; 157 uint32_t ee_data; 158 struct sockaddr_in offender; 159 }; 160 161 static void 162 print_cmsg_ip_recverr(struct tcb *tcp, const void *cmsg_data, 163 const unsigned int data_len) 164 { 165 const struct sock_ee *const err = cmsg_data; 166 167 tprintf("{ee_errno=%u, ee_origin=%u, ee_type=%u, ee_code=%u" 168 ", ee_info=%u, ee_data=%u, offender=", 169 err->ee_errno, err->ee_origin, err->ee_type, 170 err->ee_code, err->ee_info, err->ee_data); 171 print_sockaddr(tcp, &err->offender, sizeof(err->offender)); 172 tprints("}"); 173 } 174 175 static void 176 print_cmsg_ip_origdstaddr(struct tcb *tcp, const void *cmsg_data, 177 const unsigned int data_len) 178 { 179 const unsigned int addr_len = 180 data_len > sizeof(struct sockaddr_storage) 181 ? sizeof(struct sockaddr_storage) : data_len; 182 183 print_sockaddr(tcp, cmsg_data, addr_len); 184 } 185 186 typedef void (* const cmsg_printer)(struct tcb *, const void *, unsigned int); 187 188 static const struct { 189 const cmsg_printer printer; 190 const unsigned int min_len; 191 } cmsg_socket_printers[] = { 192 [SCM_RIGHTS] = { print_scm_rights, sizeof(int) }, 193 [SCM_CREDENTIALS] = { print_scm_creds, sizeof(struct ucred) }, 194 [SCM_SECURITY] = { print_scm_security, 1 } 195 }, cmsg_ip_printers[] = { 196 [IP_PKTINFO] = { print_cmsg_ip_pktinfo, sizeof(struct in_pktinfo) }, 197 [IP_TTL] = { print_cmsg_uint, sizeof(unsigned int) }, 198 [IP_TOS] = { print_cmsg_uint8_t, 1 }, 199 [IP_RECVOPTS] = { print_cmsg_ip_opts, 1 }, 200 [IP_RETOPTS] = { print_cmsg_ip_opts, 1 }, 201 [IP_RECVERR] = { print_cmsg_ip_recverr, sizeof(struct sock_ee) }, 202 [IP_ORIGDSTADDR] = { print_cmsg_ip_origdstaddr, sizeof(struct sockaddr_in) }, 203 [IP_CHECKSUM] = { print_cmsg_uint, sizeof(unsigned int) }, 204 [SCM_SECURITY] = { print_scm_security, 1 } 205 }; 206 207 static void 208 print_cmsg_type_data(struct tcb *tcp, const int cmsg_level, const int cmsg_type, 209 const void *cmsg_data, const unsigned int data_len) 210 { 211 const unsigned int utype = cmsg_type; 212 switch (cmsg_level) { 213 case SOL_SOCKET: 214 printxval(scmvals, cmsg_type, "SCM_???"); 215 if (utype < ARRAY_SIZE(cmsg_socket_printers) 216 && cmsg_socket_printers[utype].printer 217 && data_len >= cmsg_socket_printers[utype].min_len) { 218 tprints(", cmsg_data="); 219 cmsg_socket_printers[utype].printer(tcp, cmsg_data, data_len); 220 } 221 break; 222 case SOL_IP: 223 printxval(ip_cmsg_types, cmsg_type, "IP_???"); 224 if (utype < ARRAY_SIZE(cmsg_ip_printers) 225 && cmsg_ip_printers[utype].printer 226 && data_len >= cmsg_ip_printers[utype].min_len) { 227 tprints(", cmsg_data="); 228 cmsg_ip_printers[utype].printer(tcp, cmsg_data, data_len); 229 } 230 break; 231 default: 232 tprintf("%#x", cmsg_type); 233 } 234 } 235 236 static unsigned int 237 get_optmem_max(void) 238 { 239 static int optmem_max; 240 241 if (!optmem_max) { 242 if (read_int_from_file("/proc/sys/net/core/optmem_max", 243 &optmem_max) || optmem_max <= 0) { 244 optmem_max = sizeof(long long) * (2 * IOV_MAX + 512); 245 } else { 246 optmem_max = (optmem_max + sizeof(long long) - 1) 247 & ~(sizeof(long long) - 1); 248 } 249 } 250 251 return optmem_max; 252 } 253 254 static void 255 decode_msg_control(struct tcb *const tcp, const kernel_ulong_t addr, 256 const kernel_ulong_t in_control_len) 257 { 258 if (!in_control_len) 259 return; 260 tprints(", msg_control="); 261 262 const unsigned int cmsg_size = 263 #ifndef current_wordsize 264 (current_wordsize < sizeof(long)) ? sizeof(struct cmsghdr32) : 265 #endif 266 sizeof(struct cmsghdr); 267 268 unsigned int control_len = in_control_len > get_optmem_max() 269 ? get_optmem_max() : in_control_len; 270 unsigned int buf_len = control_len; 271 char *buf = buf_len < cmsg_size ? NULL : malloc(buf_len); 272 if (!buf || umoven(tcp, addr, buf_len, buf) < 0) { 273 printaddr(addr); 274 free(buf); 275 return; 276 } 277 278 union_cmsghdr u = { .ptr = buf }; 279 280 tprints("["); 281 while (buf_len >= cmsg_size) { 282 const kernel_ulong_t cmsg_len = 283 #ifndef current_wordsize 284 (current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_len : 285 #endif 286 u.cmsg->cmsg_len; 287 const int cmsg_level = 288 #ifndef current_wordsize 289 (current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_level : 290 #endif 291 u.cmsg->cmsg_level; 292 const int cmsg_type = 293 #ifndef current_wordsize 294 (current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_type : 295 #endif 296 u.cmsg->cmsg_type; 297 298 if (u.ptr != buf) 299 tprints(", "); 300 tprintf("{cmsg_len=%" PRI_klu ", cmsg_level=", cmsg_len); 301 printxval(socketlayers, cmsg_level, "SOL_???"); 302 tprints(", cmsg_type="); 303 304 kernel_ulong_t len = cmsg_len > buf_len ? buf_len : cmsg_len; 305 306 print_cmsg_type_data(tcp, cmsg_level, cmsg_type, 307 (const void *) (u.ptr + cmsg_size), 308 len > cmsg_size ? len - cmsg_size: 0); 309 tprints("}"); 310 311 if (len < cmsg_size) { 312 buf_len -= cmsg_size; 313 break; 314 } 315 len = (cmsg_len + current_wordsize - 1) & 316 ~((kernel_ulong_t) current_wordsize - 1); 317 if (len >= buf_len) { 318 buf_len = 0; 319 break; 320 } 321 u.ptr += len; 322 buf_len -= len; 323 } 324 if (buf_len) { 325 tprints(", "); 326 printaddr(addr + (control_len - buf_len)); 327 } else if (control_len < in_control_len) { 328 tprints(", ..."); 329 } 330 tprints("]"); 331 free(buf); 332 } 333 334 void 335 print_struct_msghdr(struct tcb *tcp, const struct msghdr *msg, 336 const int *const p_user_msg_namelen, 337 const kernel_ulong_t data_size) 338 { 339 const int msg_namelen = 340 p_user_msg_namelen && (int) msg->msg_namelen > *p_user_msg_namelen 341 ? *p_user_msg_namelen : (int) msg->msg_namelen; 342 343 tprints("{msg_name="); 344 const int family = 345 decode_sockaddr(tcp, ptr_to_kulong(msg->msg_name), msg_namelen); 346 const enum iov_decode decode = 347 (family == AF_NETLINK) ? IOV_DECODE_NETLINK : IOV_DECODE_STR; 348 349 tprints(", msg_namelen="); 350 if (p_user_msg_namelen && *p_user_msg_namelen != (int) msg->msg_namelen) 351 tprintf("%d->", *p_user_msg_namelen); 352 tprintf("%d", msg->msg_namelen); 353 354 tprints(", msg_iov="); 355 356 tprint_iov_upto(tcp, msg->msg_iovlen, 357 ptr_to_kulong(msg->msg_iov), decode, data_size); 358 tprintf(", msg_iovlen=%" PRI_klu, (kernel_ulong_t) msg->msg_iovlen); 359 360 decode_msg_control(tcp, ptr_to_kulong(msg->msg_control), 361 msg->msg_controllen); 362 tprintf(", msg_controllen=%" PRI_klu, (kernel_ulong_t) msg->msg_controllen); 363 364 tprints(", msg_flags="); 365 printflags(msg_flags, msg->msg_flags, "MSG_???"); 366 tprints("}"); 367 } 368 369 static bool 370 fetch_msghdr_namelen(struct tcb *const tcp, const kernel_ulong_t addr, 371 int *const p_msg_namelen) 372 { 373 struct msghdr msg; 374 375 if (addr && verbose(tcp) && fetch_struct_msghdr(tcp, addr, &msg)) { 376 *p_msg_namelen = msg.msg_namelen; 377 return true; 378 } else { 379 return false; 380 } 381 } 382 383 static void 384 decode_msghdr(struct tcb *const tcp, const int *const p_user_msg_namelen, 385 const kernel_ulong_t addr, const kernel_ulong_t data_size) 386 { 387 struct msghdr msg; 388 389 if (addr && verbose(tcp) && fetch_struct_msghdr(tcp, addr, &msg)) 390 print_struct_msghdr(tcp, &msg, p_user_msg_namelen, data_size); 391 else 392 printaddr(addr); 393 } 394 395 void 396 dumpiov_in_msghdr(struct tcb *const tcp, const kernel_ulong_t addr, 397 const kernel_ulong_t data_size) 398 { 399 struct msghdr msg; 400 401 if (fetch_struct_msghdr(tcp, addr, &msg)) { 402 dumpiov_upto(tcp, msg.msg_iovlen, 403 ptr_to_kulong(msg.msg_iov), data_size); 404 } 405 } 406 407 SYS_FUNC(sendmsg) 408 { 409 printfd(tcp, tcp->u_arg[0]); 410 tprints(", "); 411 decode_msghdr(tcp, 0, tcp->u_arg[1], -1); 412 /* flags */ 413 tprints(", "); 414 printflags(msg_flags, tcp->u_arg[2], "MSG_???"); 415 416 return RVAL_DECODED; 417 } 418 419 SYS_FUNC(recvmsg) 420 { 421 int msg_namelen; 422 423 if (entering(tcp)) { 424 printfd(tcp, tcp->u_arg[0]); 425 tprints(", "); 426 if (fetch_msghdr_namelen(tcp, tcp->u_arg[1], &msg_namelen)) { 427 set_tcb_priv_ulong(tcp, msg_namelen); 428 return 0; 429 } 430 printaddr(tcp->u_arg[1]); 431 } else { 432 msg_namelen = get_tcb_priv_ulong(tcp); 433 434 if (syserror(tcp)) 435 tprintf("{msg_namelen=%d}", msg_namelen); 436 else 437 decode_msghdr(tcp, &msg_namelen, tcp->u_arg[1], 438 tcp->u_rval); 439 } 440 441 /* flags */ 442 tprints(", "); 443 printflags(msg_flags, tcp->u_arg[2], "MSG_???"); 444 445 return RVAL_DECODED; 446 } 447