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-1999 Wichert Akkerman <wichert (at) cistron.nl>
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. The name of the author may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "defs.h"
     32 #include <fcntl.h>
     33 #include <sys/file.h>
     34 #ifdef HAVE_SYS_EPOLL_H
     35 # include <sys/epoll.h>
     36 #endif
     37 #ifdef HAVE_LINUX_PERF_EVENT_H
     38 # include  <linux/perf_event.h>
     39 #endif
     40 
     41 #include "xlat/fcntlcmds.h"
     42 #include "xlat/fdflags.h"
     43 #include "xlat/flockcmds.h"
     44 #include "xlat/lockfcmds.h"
     45 #include "xlat/notifyflags.h"
     46 #include "xlat/perf_event_open_flags.h"
     47 
     48 /*
     49  * Assume that F_SETLK64, F_SETLKW64, and F_GETLK64 are either defined
     50  * or not defined altogether.
     51  */
     52 #if defined(F_SETLK64) && F_SETLK64 + 0 != F_SETLK
     53 # define USE_PRINTFLOCK64 1
     54 #else
     55 # define USE_PRINTFLOCK64 0
     56 #endif
     57 
     58 #if USE_PRINTFLOCK64
     59 
     60 # ifndef HAVE_STRUCT_FLOCK64
     61 struct flock64 {
     62 	short int l_type, l_whence;
     63 	int64_t l_start, l_len;
     64 	int l_pid;
     65 };
     66 # endif
     67 
     68 static void
     69 printflock64(struct tcb *tcp, long addr, int getlk)
     70 {
     71 	struct flock64 fl;
     72 
     73 	if (umove(tcp, addr, &fl) < 0) {
     74 		tprints("{...}");
     75 		return;
     76 	}
     77 	tprints("{type=");
     78 	printxval(lockfcmds, fl.l_type, "F_???");
     79 	tprints(", whence=");
     80 	printxval(whence_codes, fl.l_whence, "SEEK_???");
     81 	tprintf(", start=%lld, len=%lld", (long long) fl.l_start, (long long) fl.l_len);
     82 	if (getlk)
     83 		tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
     84 	else
     85 		tprints("}");
     86 }
     87 #endif /* USE_PRINTFLOCK64 */
     88 
     89 static void
     90 printflock(struct tcb *tcp, long addr, int getlk)
     91 {
     92 	struct flock fl;
     93 	int r;
     94 
     95 #if SUPPORTED_PERSONALITIES > 1
     96 	if (
     97 # if SIZEOF_OFF_T > SIZEOF_LONG
     98 	    current_personality > 0 &&
     99 #endif
    100 	    current_wordsize != sizeof(fl.l_start)) {
    101 		if (current_wordsize == 4) {
    102 			/* 32-bit x86 app on x86_64 and similar cases */
    103 			struct {
    104 				short int l_type;
    105 				short int l_whence;
    106 				int32_t l_start; /* off_t */
    107 				int32_t l_len; /* off_t */
    108 				int32_t l_pid; /* pid_t */
    109 			} fl32;
    110 			r = umove(tcp, addr, &fl32);
    111 			if (r >= 0) {
    112 				fl.l_type = fl32.l_type;
    113 				fl.l_whence = fl32.l_whence;
    114 				fl.l_start = fl32.l_start;
    115 				fl.l_len = fl32.l_len;
    116 				fl.l_pid = fl32.l_pid;
    117 			}
    118 		} else {
    119 			/* let people know we have a problem here */
    120 			tprintf("<decode error: unsupported wordsize %d>",
    121 				current_wordsize);
    122 			return;
    123 		}
    124 	} else
    125 #endif
    126 	{
    127 		r = umove(tcp, addr, &fl);
    128 	}
    129 	if (r < 0) {
    130 		tprints("{...}");
    131 		return;
    132 	}
    133 	tprints("{type=");
    134 	printxval(lockfcmds, fl.l_type, "F_???");
    135 	tprints(", whence=");
    136 	printxval(whence_codes, fl.l_whence, "SEEK_???");
    137 #if SIZEOF_OFF_T > SIZEOF_LONG
    138 	tprintf(", start=%lld, len=%lld", fl.l_start, fl.l_len);
    139 #else
    140 	tprintf(", start=%ld, len=%ld", fl.l_start, fl.l_len);
    141 #endif
    142 	if (getlk)
    143 		tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
    144 	else
    145 		tprints("}");
    146 }
    147 
    148 int
    149 sys_fcntl(struct tcb *tcp)
    150 {
    151 	if (entering(tcp)) {
    152 		printfd(tcp, tcp->u_arg[0]);
    153 		tprints(", ");
    154 		printxval(fcntlcmds, tcp->u_arg[1], "F_???");
    155 		switch (tcp->u_arg[1]) {
    156 		case F_SETFD:
    157 			tprints(", ");
    158 			printflags(fdflags, tcp->u_arg[2], "FD_???");
    159 			break;
    160 		case F_SETOWN: case F_DUPFD:
    161 #ifdef F_DUPFD_CLOEXEC
    162 		case F_DUPFD_CLOEXEC:
    163 #endif
    164 			tprintf(", %ld", tcp->u_arg[2]);
    165 			break;
    166 		case F_SETFL:
    167 			tprints(", ");
    168 			tprint_open_modes(tcp->u_arg[2]);
    169 			break;
    170 		case F_SETLK: case F_SETLKW:
    171 			tprints(", ");
    172 			printflock(tcp, tcp->u_arg[2], 0);
    173 			break;
    174 #if USE_PRINTFLOCK64
    175 		case F_SETLK64: case F_SETLKW64:
    176 			tprints(", ");
    177 			printflock64(tcp, tcp->u_arg[2], 0);
    178 			break;
    179 #endif /* USE_PRINTFLOCK64 */
    180 #ifdef F_NOTIFY
    181 		case F_NOTIFY:
    182 			tprints(", ");
    183 			printflags(notifyflags, tcp->u_arg[2], "DN_???");
    184 			break;
    185 #endif
    186 #ifdef F_SETLEASE
    187 		case F_SETLEASE:
    188 			tprints(", ");
    189 			printxval(lockfcmds, tcp->u_arg[2], "F_???");
    190 			break;
    191 #endif
    192 		}
    193 	}
    194 	else {
    195 		switch (tcp->u_arg[1]) {
    196 		case F_DUPFD:
    197 #ifdef F_DUPFD_CLOEXEC
    198 		case F_DUPFD_CLOEXEC:
    199 #endif
    200 		case F_SETFD: case F_SETFL:
    201 		case F_SETLK: case F_SETLKW:
    202 		case F_SETOWN: case F_GETOWN:
    203 #ifdef F_NOTIFY
    204 		case F_NOTIFY:
    205 #endif
    206 #ifdef F_SETLEASE
    207 		case F_SETLEASE:
    208 #endif
    209 			break;
    210 		case F_GETFD:
    211 			if (syserror(tcp) || tcp->u_rval == 0)
    212 				return 0;
    213 			tcp->auxstr = sprintflags("flags ", fdflags, tcp->u_rval);
    214 			return RVAL_HEX|RVAL_STR;
    215 		case F_GETFL:
    216 			if (syserror(tcp))
    217 				return 0;
    218 			tcp->auxstr = sprint_open_modes(tcp->u_rval);
    219 			return RVAL_HEX|RVAL_STR;
    220 		case F_GETLK:
    221 			tprints(", ");
    222 			printflock(tcp, tcp->u_arg[2], 1);
    223 			break;
    224 #if USE_PRINTFLOCK64
    225 		case F_GETLK64:
    226 			tprints(", ");
    227 			printflock64(tcp, tcp->u_arg[2], 1);
    228 			break;
    229 #endif
    230 #ifdef F_GETLEASE
    231 		case F_GETLEASE:
    232 			if (syserror(tcp))
    233 				return 0;
    234 			tcp->auxstr = xlookup(lockfcmds, tcp->u_rval);
    235 			return RVAL_HEX|RVAL_STR;
    236 #endif
    237 		default:
    238 			tprintf(", %#lx", tcp->u_arg[2]);
    239 			break;
    240 		}
    241 	}
    242 	return 0;
    243 }
    244 
    245 #ifdef LOCK_SH
    246 
    247 int
    248 sys_flock(struct tcb *tcp)
    249 {
    250 	if (entering(tcp)) {
    251 		printfd(tcp, tcp->u_arg[0]);
    252 		tprints(", ");
    253 		printflags(flockcmds, tcp->u_arg[1], "LOCK_???");
    254 	}
    255 	return 0;
    256 }
    257 #endif /* LOCK_SH */
    258 
    259 int
    260 sys_close(struct tcb *tcp)
    261 {
    262 	if (entering(tcp)) {
    263 		printfd(tcp, tcp->u_arg[0]);
    264 	}
    265 	return 0;
    266 }
    267 
    268 int
    269 sys_dup(struct tcb *tcp)
    270 {
    271 	if (entering(tcp)) {
    272 		printfd(tcp, tcp->u_arg[0]);
    273 	}
    274 	return RVAL_FD;
    275 }
    276 
    277 static int
    278 do_dup2(struct tcb *tcp, int flags_arg)
    279 {
    280 	if (entering(tcp)) {
    281 		printfd(tcp, tcp->u_arg[0]);
    282 		tprints(", ");
    283 		printfd(tcp, tcp->u_arg[1]);
    284 		if (flags_arg >= 0) {
    285 			tprints(", ");
    286 			printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
    287 		}
    288 	}
    289 	return RVAL_FD;
    290 }
    291 
    292 int
    293 sys_dup2(struct tcb *tcp)
    294 {
    295 	return do_dup2(tcp, -1);
    296 }
    297 
    298 int
    299 sys_dup3(struct tcb *tcp)
    300 {
    301 	return do_dup2(tcp, 2);
    302 }
    303 
    304 #if defined(ALPHA)
    305 int
    306 sys_getdtablesize(struct tcb *tcp)
    307 {
    308 	return 0;
    309 }
    310 #endif
    311 
    312 static int
    313 decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
    314 {
    315 	int i, j;
    316 	int nfds, fdsize;
    317 	fd_set *fds;
    318 	const char *sep;
    319 	long arg;
    320 
    321 	/* Kernel truncates arg[0] to int, we do the same. */
    322 	nfds = (int) args[0];
    323 
    324 	/* Kernel rejects negative nfds, so we don't parse it either. */
    325 	if (nfds < 0) {
    326 		nfds = 0;
    327 		fds = NULL;
    328 	}
    329 	/* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */
    330 	if (nfds > 1024*1024)
    331 		nfds = 1024*1024;
    332 
    333 	/*
    334 	 * We had bugs a-la "while (j < args[0])" and "umoven(args[0])" below.
    335 	 * Instead of args[0], use nfds for fd count, fdsize for array lengths.
    336 	 */
    337 	fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize;
    338 
    339 	if (entering(tcp)) {
    340 		tprintf("%d", (int) args[0]);
    341 
    342 		if (fdsize > 0) {
    343 			fds = malloc(fdsize);
    344 			if (!fds)
    345 				die_out_of_memory();
    346 		}
    347 		for (i = 0; i < 3; i++) {
    348 			arg = args[i+1];
    349 			if (arg == 0) {
    350 				tprints(", NULL");
    351 				continue;
    352 			}
    353 			if (!verbose(tcp) || !fds) {
    354 				tprintf(", %#lx", arg);
    355 				continue;
    356 			}
    357 			if (umoven(tcp, arg, fdsize, (char *) fds) < 0) {
    358 				tprints(", [?]");
    359 				continue;
    360 			}
    361 			tprints(", [");
    362 			for (j = 0, sep = "";; j++) {
    363 				j = next_set_bit(fds, j, nfds);
    364 				if (j < 0)
    365 					break;
    366 				tprints(sep);
    367 				printfd(tcp, j);
    368 				sep = " ";
    369 			}
    370 			tprints("]");
    371 		}
    372 		free(fds);
    373 		tprints(", ");
    374 		printtv_bitness(tcp, args[4], bitness, 0);
    375 	}
    376 	else {
    377 		static char outstr[1024];
    378 		char *outptr;
    379 #define end_outstr (outstr + sizeof(outstr))
    380 		int ready_fds;
    381 
    382 		if (syserror(tcp))
    383 			return 0;
    384 
    385 		ready_fds = tcp->u_rval;
    386 		if (ready_fds == 0) {
    387 			tcp->auxstr = "Timeout";
    388 			return RVAL_STR;
    389 		}
    390 
    391 		fds = malloc(fdsize);
    392 		if (!fds)
    393 			die_out_of_memory();
    394 
    395 		outptr = outstr;
    396 		sep = "";
    397 		for (i = 0; i < 3 && ready_fds > 0; i++) {
    398 			int first = 1;
    399 
    400 			arg = args[i+1];
    401 			if (!arg || umoven(tcp, arg, fdsize, (char *) fds) < 0)
    402 				continue;
    403 			for (j = 0;; j++) {
    404 				j = next_set_bit(fds, j, nfds);
    405 				if (j < 0)
    406 					break;
    407 				/* +2 chars needed at the end: ']',NUL */
    408 				if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) {
    409 					if (first) {
    410 						outptr += sprintf(outptr, "%s%s [%u",
    411 							sep,
    412 							i == 0 ? "in" : i == 1 ? "out" : "except",
    413 							j
    414 						);
    415 						first = 0;
    416 						sep = ", ";
    417 					}
    418 					else {
    419 						outptr += sprintf(outptr, " %u", j);
    420 					}
    421 				}
    422 				if (--ready_fds == 0)
    423 					break;
    424 			}
    425 			if (outptr != outstr)
    426 				*outptr++ = ']';
    427 		}
    428 		free(fds);
    429 		/* This contains no useful information on SunOS.  */
    430 		if (args[4]) {
    431 			if (outptr < end_outstr - (10 + TIMEVAL_TEXT_BUFSIZE)) {
    432 				outptr += sprintf(outptr, "%sleft ", sep);
    433 				outptr = sprinttv(outptr, tcp, args[4], bitness, /*special:*/ 0);
    434 			}
    435 		}
    436 		*outptr = '\0';
    437 		tcp->auxstr = outstr;
    438 		return RVAL_STR;
    439 #undef end_outstr
    440 	}
    441 	return 0;
    442 }
    443 
    444 int
    445 sys_oldselect(struct tcb *tcp)
    446 {
    447 	long args[5];
    448 
    449 	if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) {
    450 		tprints("[...]");
    451 		return 0;
    452 	}
    453 	return decode_select(tcp, args, BITNESS_CURRENT);
    454 }
    455 
    456 #ifdef ALPHA
    457 int
    458 sys_osf_select(struct tcb *tcp)
    459 {
    460 	long *args = tcp->u_arg;
    461 	return decode_select(tcp, args, BITNESS_32);
    462 }
    463 #endif
    464 
    465 #include "xlat/epollctls.h"
    466 #include "xlat/epollevents.h"
    467 #include "xlat/epollflags.h"
    468 
    469 /* Not aliased to printargs_ld: we want it to have a distinct address */
    470 int
    471 sys_epoll_create(struct tcb *tcp)
    472 {
    473 	return printargs_ld(tcp);
    474 }
    475 
    476 int
    477 sys_epoll_create1(struct tcb *tcp)
    478 {
    479 	if (entering(tcp))
    480 		printflags(epollflags, tcp->u_arg[0], "EPOLL_???");
    481 	return 0;
    482 }
    483 
    484 #ifdef HAVE_SYS_EPOLL_H
    485 static void
    486 print_epoll_event(struct epoll_event *ev)
    487 {
    488 	tprints("{");
    489 	printflags(epollevents, ev->events, "EPOLL???");
    490 	/* We cannot know what format the program uses, so print u32 and u64
    491 	   which will cover every value.  */
    492 	tprintf(", {u32=%" PRIu32 ", u64=%" PRIu64 "}}",
    493 		ev->data.u32, ev->data.u64);
    494 }
    495 #endif
    496 
    497 int
    498 sys_epoll_ctl(struct tcb *tcp)
    499 {
    500 	if (entering(tcp)) {
    501 		printfd(tcp, tcp->u_arg[0]);
    502 		tprints(", ");
    503 		printxval(epollctls, tcp->u_arg[1], "EPOLL_CTL_???");
    504 		tprints(", ");
    505 		printfd(tcp, tcp->u_arg[2]);
    506 		tprints(", ");
    507 		if (tcp->u_arg[3] == 0)
    508 			tprints("NULL");
    509 		else {
    510 #ifdef HAVE_SYS_EPOLL_H
    511 			struct epoll_event ev;
    512 			if (
    513 #ifdef EPOLL_CTL_DEL
    514 			    (tcp->u_arg[1] != EPOLL_CTL_DEL) &&
    515 #endif
    516 			    umove(tcp, tcp->u_arg[3], &ev) == 0)
    517 				print_epoll_event(&ev);
    518 			else
    519 #endif
    520 				tprintf("%lx", tcp->u_arg[3]);
    521 		}
    522 	}
    523 	return 0;
    524 }
    525 
    526 static void
    527 epoll_wait_common(struct tcb *tcp)
    528 {
    529 	if (entering(tcp)) {
    530 		printfd(tcp, tcp->u_arg[0]);
    531 		tprints(", ");
    532 	} else {
    533 		if (syserror(tcp))
    534 			tprintf("%lx", tcp->u_arg[1]);
    535 		else if (tcp->u_rval == 0)
    536 			tprints("{}");
    537 		else {
    538 #ifdef HAVE_SYS_EPOLL_H
    539 			struct epoll_event ev, *start, *cur, *end;
    540 			int failed = 0;
    541 
    542 			tprints("{");
    543 			start = (struct epoll_event *) tcp->u_arg[1];
    544 			end = start + tcp->u_rval;
    545 			for (cur = start; cur < end; ++cur) {
    546 				if (cur > start)
    547 					tprints(", ");
    548 				if (umove(tcp, (long) cur, &ev) == 0)
    549 					print_epoll_event(&ev);
    550 				else {
    551 					tprints("?");
    552 					failed = 1;
    553 					break;
    554 				}
    555 			}
    556 			tprints("}");
    557 			if (failed)
    558 				tprintf(" %#lx", (long) start);
    559 #else
    560 			tprints("{...}");
    561 #endif
    562 		}
    563 		tprintf(", %d, %d", (int) tcp->u_arg[2], (int) tcp->u_arg[3]);
    564 	}
    565 }
    566 
    567 int
    568 sys_epoll_wait(struct tcb *tcp)
    569 {
    570 	epoll_wait_common(tcp);
    571 	return 0;
    572 }
    573 
    574 int
    575 sys_epoll_pwait(struct tcb *tcp)
    576 {
    577 	epoll_wait_common(tcp);
    578 	if (exiting(tcp)) {
    579 		tprints(", ");
    580 		/* NB: kernel requires arg[5] == NSIG / 8 */
    581 		print_sigset_addr_len(tcp, tcp->u_arg[4], tcp->u_arg[5]);
    582 		tprintf(", %lu", tcp->u_arg[5]);
    583 	}
    584 	return 0;
    585 }
    586 
    587 int
    588 sys_select(struct tcb *tcp)
    589 {
    590 	return decode_select(tcp, tcp->u_arg, BITNESS_CURRENT);
    591 }
    592 
    593 int
    594 sys_pselect6(struct tcb *tcp)
    595 {
    596 	int rc = decode_select(tcp, tcp->u_arg, BITNESS_CURRENT);
    597 	if (entering(tcp)) {
    598 		long r;
    599 		struct {
    600 			unsigned long ptr;
    601 			unsigned long len;
    602 		} data;
    603 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
    604 		if (current_wordsize == 4) {
    605 			struct {
    606 				uint32_t ptr;
    607 				uint32_t len;
    608 			} data32;
    609 			r = umove(tcp, tcp->u_arg[5], &data32);
    610 			data.ptr = data32.ptr;
    611 			data.len = data32.len;
    612 		} else
    613 #endif
    614 			r = umove(tcp, tcp->u_arg[5], &data);
    615 		if (r < 0)
    616 			tprintf(", %#lx", tcp->u_arg[5]);
    617 		else {
    618 			tprints(", {");
    619 			/* NB: kernel requires data.len == NSIG / 8 */
    620 			print_sigset_addr_len(tcp, data.ptr, data.len);
    621 			tprintf(", %lu}", data.len);
    622 		}
    623 	}
    624 	return rc;
    625 }
    626 
    627 static int
    628 do_eventfd(struct tcb *tcp, int flags_arg)
    629 {
    630 	if (entering(tcp)) {
    631 		tprintf("%lu", tcp->u_arg[0]);
    632 		if (flags_arg >= 0) {
    633 			tprints(", ");
    634 			printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
    635 		}
    636 	}
    637 	return 0;
    638 }
    639 
    640 int
    641 sys_eventfd(struct tcb *tcp)
    642 {
    643 	return do_eventfd(tcp, -1);
    644 }
    645 
    646 int
    647 sys_eventfd2(struct tcb *tcp)
    648 {
    649 	return do_eventfd(tcp, 1);
    650 }
    651 
    652 int
    653 sys_perf_event_open(struct tcb *tcp)
    654 {
    655 	if (entering(tcp)) {
    656 		tprintf("%#lx, %d, %d, %d, ",
    657 			tcp->u_arg[0],
    658 			(int) tcp->u_arg[1],
    659 			(int) tcp->u_arg[2],
    660 			(int) tcp->u_arg[3]);
    661 		printflags(perf_event_open_flags, tcp->u_arg[4],
    662 			   "PERF_FLAG_???");
    663 	}
    664 	return 0;
    665 }
    666