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_scm_timestamp(struct tcb *tcp, const void *cmsg_data,
    100 		    const unsigned int data_len)
    101 {
    102 	print_struct_timeval_data_size(cmsg_data, data_len);
    103 }
    104 
    105 static void
    106 print_scm_timestampns(struct tcb *tcp, const void *cmsg_data,
    107 		      const unsigned int data_len)
    108 {
    109 	print_struct_timespec_data_size(cmsg_data, data_len);
    110 }
    111 
    112 static void
    113 print_scm_timestamping(struct tcb *tcp, const void *cmsg_data,
    114 		       const unsigned int data_len)
    115 {
    116 	print_struct_timespec_array_data_size(cmsg_data, 3, data_len);
    117 }
    118 
    119 static void
    120 print_cmsg_ip_pktinfo(struct tcb *tcp, const void *cmsg_data,
    121 		      const unsigned int data_len)
    122 {
    123 	const struct in_pktinfo *info = cmsg_data;
    124 
    125 	tprints("{ipi_ifindex=");
    126 	print_ifindex(info->ipi_ifindex);
    127 	tprintf(", ipi_spec_dst=inet_addr(\"%s\")",
    128 		inet_ntoa(info->ipi_spec_dst));
    129 	tprintf(", ipi_addr=inet_addr(\"%s\")}",
    130 		inet_ntoa(info->ipi_addr));
    131 }
    132 
    133 static void
    134 print_cmsg_uint(struct tcb *tcp, const void *cmsg_data,
    135 		const unsigned int data_len)
    136 {
    137 	const unsigned int *p = cmsg_data;
    138 
    139 	tprintf("[%u]", *p);
    140 }
    141 
    142 static void
    143 print_cmsg_uint8_t(struct tcb *tcp, const void *cmsg_data,
    144 		   const unsigned int data_len)
    145 {
    146 	const uint8_t *p = cmsg_data;
    147 
    148 	tprintf("[%#x]", *p);
    149 }
    150 
    151 static void
    152 print_cmsg_ip_opts(struct tcb *tcp, const void *cmsg_data,
    153 		   const unsigned int data_len)
    154 {
    155 	const unsigned char *opts = cmsg_data;
    156 	unsigned int i;
    157 
    158 	tprints("[");
    159 	for (i = 0; i < data_len; ++i) {
    160 		if (i)
    161 			tprints(", ");
    162 		if (abbrev(tcp) && i >= max_strlen) {
    163 			tprints("...");
    164 			break;
    165 		}
    166 		tprintf("0x%02x", opts[i]);
    167 	}
    168 	tprints("]");
    169 }
    170 
    171 struct sock_ee {
    172 	uint32_t ee_errno;
    173 	uint8_t  ee_origin;
    174 	uint8_t  ee_type;
    175 	uint8_t  ee_code;
    176 	uint8_t  ee_pad;
    177 	uint32_t ee_info;
    178 	uint32_t ee_data;
    179 	struct sockaddr_in offender;
    180 };
    181 
    182 static void
    183 print_cmsg_ip_recverr(struct tcb *tcp, const void *cmsg_data,
    184 		      const unsigned int data_len)
    185 {
    186 	const struct sock_ee *const err = cmsg_data;
    187 
    188 	tprintf("{ee_errno=%u, ee_origin=%u, ee_type=%u, ee_code=%u"
    189 		", ee_info=%u, ee_data=%u, offender=",
    190 		err->ee_errno, err->ee_origin, err->ee_type,
    191 		err->ee_code, err->ee_info, err->ee_data);
    192 	print_sockaddr(tcp, &err->offender, sizeof(err->offender));
    193 	tprints("}");
    194 }
    195 
    196 static void
    197 print_cmsg_ip_origdstaddr(struct tcb *tcp, const void *cmsg_data,
    198 			  const unsigned int data_len)
    199 {
    200 	const unsigned int addr_len =
    201 		data_len > sizeof(struct sockaddr_storage)
    202 		? sizeof(struct sockaddr_storage) : data_len;
    203 
    204 	print_sockaddr(tcp, cmsg_data, addr_len);
    205 }
    206 
    207 typedef void (* const cmsg_printer)(struct tcb *, const void *, unsigned int);
    208 
    209 static const struct {
    210 	const cmsg_printer printer;
    211 	const unsigned int min_len;
    212 } cmsg_socket_printers[] = {
    213 	[SCM_RIGHTS] = { print_scm_rights, sizeof(int) },
    214 	[SCM_CREDENTIALS] = { print_scm_creds, sizeof(struct ucred) },
    215 	[SCM_SECURITY] = { print_scm_security, 1 },
    216 	[SCM_TIMESTAMP] = { print_scm_timestamp, 1 },
    217 	[SCM_TIMESTAMPNS] = { print_scm_timestampns, 1 },
    218 	[SCM_TIMESTAMPING] = { print_scm_timestamping, 1 }
    219 }, cmsg_ip_printers[] = {
    220 	[IP_PKTINFO] = { print_cmsg_ip_pktinfo, sizeof(struct in_pktinfo) },
    221 	[IP_TTL] = { print_cmsg_uint, sizeof(unsigned int) },
    222 	[IP_TOS] = { print_cmsg_uint8_t, 1 },
    223 	[IP_RECVOPTS] = { print_cmsg_ip_opts, 1 },
    224 	[IP_RETOPTS] = { print_cmsg_ip_opts, 1 },
    225 	[IP_RECVERR] = { print_cmsg_ip_recverr, sizeof(struct sock_ee) },
    226 	[IP_ORIGDSTADDR] = { print_cmsg_ip_origdstaddr, sizeof(struct sockaddr_in) },
    227 	[IP_CHECKSUM] = { print_cmsg_uint, sizeof(unsigned int) },
    228 	[SCM_SECURITY] = { print_scm_security, 1 }
    229 };
    230 
    231 static void
    232 print_cmsg_type_data(struct tcb *tcp, const int cmsg_level, const int cmsg_type,
    233 		     const void *cmsg_data, const unsigned int data_len)
    234 {
    235 	const unsigned int utype = cmsg_type;
    236 	switch (cmsg_level) {
    237 	case SOL_SOCKET:
    238 		printxval(scmvals, cmsg_type, "SCM_???");
    239 		if (utype < ARRAY_SIZE(cmsg_socket_printers)
    240 		    && cmsg_socket_printers[utype].printer
    241 		    && data_len >= cmsg_socket_printers[utype].min_len) {
    242 			tprints(", cmsg_data=");
    243 			cmsg_socket_printers[utype].printer(tcp, cmsg_data, data_len);
    244 		}
    245 		break;
    246 	case SOL_IP:
    247 		printxval(ip_cmsg_types, cmsg_type, "IP_???");
    248 		if (utype < ARRAY_SIZE(cmsg_ip_printers)
    249 		    && cmsg_ip_printers[utype].printer
    250 		    && data_len >= cmsg_ip_printers[utype].min_len) {
    251 			tprints(", cmsg_data=");
    252 			cmsg_ip_printers[utype].printer(tcp, cmsg_data, data_len);
    253 		}
    254 		break;
    255 	default:
    256 		tprintf("%#x", cmsg_type);
    257 	}
    258 }
    259 
    260 static unsigned int
    261 get_optmem_max(void)
    262 {
    263 	static int optmem_max;
    264 
    265 	if (!optmem_max) {
    266 		if (read_int_from_file("/proc/sys/net/core/optmem_max",
    267 				       &optmem_max) || optmem_max <= 0) {
    268 			optmem_max = sizeof(long long) * (2 * IOV_MAX + 512);
    269 		} else {
    270 			optmem_max = (optmem_max + sizeof(long long) - 1)
    271 				     & ~(sizeof(long long) - 1);
    272 		}
    273 	}
    274 
    275 	return optmem_max;
    276 }
    277 
    278 static void
    279 decode_msg_control(struct tcb *const tcp, const kernel_ulong_t addr,
    280 		   const kernel_ulong_t in_control_len)
    281 {
    282 	if (!in_control_len)
    283 		return;
    284 	tprints(", msg_control=");
    285 
    286 	const unsigned int cmsg_size =
    287 #ifndef current_wordsize
    288 		(current_wordsize < sizeof(long)) ? sizeof(struct cmsghdr32) :
    289 #endif
    290 			sizeof(struct cmsghdr);
    291 
    292 	unsigned int control_len = in_control_len > get_optmem_max()
    293 				   ? get_optmem_max() : in_control_len;
    294 	unsigned int buf_len = control_len;
    295 	char *buf = buf_len < cmsg_size ? NULL : malloc(buf_len);
    296 	if (!buf || umoven(tcp, addr, buf_len, buf) < 0) {
    297 		printaddr(addr);
    298 		free(buf);
    299 		return;
    300 	}
    301 
    302 	union_cmsghdr u = { .ptr = buf };
    303 
    304 	tprints("[");
    305 	while (buf_len >= cmsg_size) {
    306 		const kernel_ulong_t cmsg_len =
    307 #ifndef current_wordsize
    308 			(current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_len :
    309 #endif
    310 				u.cmsg->cmsg_len;
    311 		const int cmsg_level =
    312 #ifndef current_wordsize
    313 			(current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_level :
    314 #endif
    315 				u.cmsg->cmsg_level;
    316 		const int cmsg_type =
    317 #ifndef current_wordsize
    318 			(current_wordsize < sizeof(long)) ? u.cmsg32->cmsg_type :
    319 #endif
    320 				u.cmsg->cmsg_type;
    321 
    322 		if (u.ptr != buf)
    323 			tprints(", ");
    324 		tprintf("{cmsg_len=%" PRI_klu ", cmsg_level=", cmsg_len);
    325 		printxval(socketlayers, cmsg_level, "SOL_???");
    326 		tprints(", cmsg_type=");
    327 
    328 		kernel_ulong_t len = cmsg_len > buf_len ? buf_len : cmsg_len;
    329 
    330 		print_cmsg_type_data(tcp, cmsg_level, cmsg_type,
    331 				     (const void *) (u.ptr + cmsg_size),
    332 				     len > cmsg_size ? len - cmsg_size : 0);
    333 		tprints("}");
    334 
    335 		if (len < cmsg_size) {
    336 			buf_len -= cmsg_size;
    337 			break;
    338 		}
    339 		len = (cmsg_len + current_wordsize - 1) &
    340 			~((kernel_ulong_t) current_wordsize - 1);
    341 		if (len >= buf_len) {
    342 			buf_len = 0;
    343 			break;
    344 		}
    345 		u.ptr += len;
    346 		buf_len -= len;
    347 	}
    348 	if (buf_len) {
    349 		tprints(", ");
    350 		printaddr(addr + (control_len - buf_len));
    351 	} else if (control_len < in_control_len) {
    352 		tprints(", ...");
    353 	}
    354 	tprints("]");
    355 	free(buf);
    356 }
    357 
    358 void
    359 print_struct_msghdr(struct tcb *tcp, const struct msghdr *msg,
    360 		    const int *const p_user_msg_namelen,
    361 		    const kernel_ulong_t data_size)
    362 {
    363 	const int msg_namelen =
    364 		p_user_msg_namelen && (int) msg->msg_namelen > *p_user_msg_namelen
    365 		? *p_user_msg_namelen : (int) msg->msg_namelen;
    366 
    367 	tprints("{msg_name=");
    368 	const int family =
    369 		decode_sockaddr(tcp, ptr_to_kulong(msg->msg_name), msg_namelen);
    370 	const enum iov_decode decode =
    371 		(family == AF_NETLINK) ? IOV_DECODE_NETLINK : IOV_DECODE_STR;
    372 
    373 	tprints(", msg_namelen=");
    374 	if (p_user_msg_namelen && *p_user_msg_namelen != (int) msg->msg_namelen)
    375 		tprintf("%d->", *p_user_msg_namelen);
    376 	tprintf("%d", msg->msg_namelen);
    377 
    378 	tprints(", msg_iov=");
    379 
    380 	tprint_iov_upto(tcp, msg->msg_iovlen,
    381 			ptr_to_kulong(msg->msg_iov), decode, data_size);
    382 	tprintf(", msg_iovlen=%" PRI_klu, (kernel_ulong_t) msg->msg_iovlen);
    383 
    384 	decode_msg_control(tcp, ptr_to_kulong(msg->msg_control),
    385 			   msg->msg_controllen);
    386 	tprintf(", msg_controllen=%" PRI_klu, (kernel_ulong_t) msg->msg_controllen);
    387 
    388 	tprints(", msg_flags=");
    389 	printflags(msg_flags, msg->msg_flags, "MSG_???");
    390 	tprints("}");
    391 }
    392 
    393 static bool
    394 fetch_msghdr_namelen(struct tcb *const tcp, const kernel_ulong_t addr,
    395 		     int *const p_msg_namelen)
    396 {
    397 	struct msghdr msg;
    398 
    399 	if (addr && verbose(tcp) && fetch_struct_msghdr(tcp, addr, &msg)) {
    400 		*p_msg_namelen = msg.msg_namelen;
    401 		return true;
    402 	} else {
    403 		return false;
    404 	}
    405 }
    406 
    407 static void
    408 decode_msghdr(struct tcb *const tcp, const int *const p_user_msg_namelen,
    409 	      const kernel_ulong_t addr, const kernel_ulong_t data_size)
    410 {
    411 	struct msghdr msg;
    412 
    413 	if (addr && verbose(tcp) && fetch_struct_msghdr(tcp, addr, &msg))
    414 		print_struct_msghdr(tcp, &msg, p_user_msg_namelen, data_size);
    415 	else
    416 		printaddr(addr);
    417 }
    418 
    419 void
    420 dumpiov_in_msghdr(struct tcb *const tcp, const kernel_ulong_t addr,
    421 		  const kernel_ulong_t data_size)
    422 {
    423 	struct msghdr msg;
    424 
    425 	if (fetch_struct_msghdr(tcp, addr, &msg)) {
    426 		dumpiov_upto(tcp, msg.msg_iovlen,
    427 			     ptr_to_kulong(msg.msg_iov), data_size);
    428 	}
    429 }
    430 
    431 SYS_FUNC(sendmsg)
    432 {
    433 	printfd(tcp, tcp->u_arg[0]);
    434 	tprints(", ");
    435 	decode_msghdr(tcp, 0, tcp->u_arg[1], -1);
    436 	/* flags */
    437 	tprints(", ");
    438 	printflags(msg_flags, tcp->u_arg[2], "MSG_???");
    439 
    440 	return RVAL_DECODED;
    441 }
    442 
    443 SYS_FUNC(recvmsg)
    444 {
    445 	int msg_namelen;
    446 
    447 	if (entering(tcp)) {
    448 		printfd(tcp, tcp->u_arg[0]);
    449 		tprints(", ");
    450 		if (fetch_msghdr_namelen(tcp, tcp->u_arg[1], &msg_namelen)) {
    451 			set_tcb_priv_ulong(tcp, msg_namelen);
    452 			return 0;
    453 		}
    454 		printaddr(tcp->u_arg[1]);
    455 	} else {
    456 		msg_namelen = get_tcb_priv_ulong(tcp);
    457 
    458 		if (syserror(tcp))
    459 			tprintf("{msg_namelen=%d}", msg_namelen);
    460 		else
    461 			decode_msghdr(tcp, &msg_namelen, tcp->u_arg[1],
    462 				      tcp->u_rval);
    463 	}
    464 
    465 	/* flags */
    466 	tprints(", ");
    467 	printflags(msg_flags, tcp->u_arg[2], "MSG_???");
    468 
    469 	return RVAL_DECODED;
    470 }
    471