1/* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@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 61struct flock64 { 62 short int l_type, l_whence; 63 int64_t l_start, l_len; 64 int l_pid; 65}; 66# endif 67 68static void 69printflock64(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 89static void 90printflock(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 148int 149sys_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 247int 248sys_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 259int 260sys_close(struct tcb *tcp) 261{ 262 if (entering(tcp)) { 263 printfd(tcp, tcp->u_arg[0]); 264 } 265 return 0; 266} 267 268int 269sys_dup(struct tcb *tcp) 270{ 271 if (entering(tcp)) { 272 printfd(tcp, tcp->u_arg[0]); 273 } 274 return RVAL_FD; 275} 276 277static int 278do_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 292int 293sys_dup2(struct tcb *tcp) 294{ 295 return do_dup2(tcp, -1); 296} 297 298int 299sys_dup3(struct tcb *tcp) 300{ 301 return do_dup2(tcp, 2); 302} 303 304#if defined(ALPHA) 305int 306sys_getdtablesize(struct tcb *tcp) 307{ 308 return 0; 309} 310#endif 311 312static int 313decode_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 444int 445sys_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 457int 458sys_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 */ 470int 471sys_epoll_create(struct tcb *tcp) 472{ 473 return printargs_ld(tcp); 474} 475 476int 477sys_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 485static void 486print_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 497int 498sys_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 526static void 527epoll_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 567int 568sys_epoll_wait(struct tcb *tcp) 569{ 570 epoll_wait_common(tcp); 571 return 0; 572} 573 574int 575sys_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 587int 588sys_select(struct tcb *tcp) 589{ 590 return decode_select(tcp, tcp->u_arg, BITNESS_CURRENT); 591} 592 593int 594sys_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 627static int 628do_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 640int 641sys_eventfd(struct tcb *tcp) 642{ 643 return do_eventfd(tcp, -1); 644} 645 646int 647sys_eventfd2(struct tcb *tcp) 648{ 649 return do_eventfd(tcp, 1); 650} 651 652int 653sys_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