Home | History | Annotate | Download | only in strace
      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