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