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 SYS_FUNC(fcntl) 149 { 150 if (entering(tcp)) { 151 printfd(tcp, tcp->u_arg[0]); 152 tprints(", "); 153 printxval(fcntlcmds, tcp->u_arg[1], "F_???"); 154 switch (tcp->u_arg[1]) { 155 case F_SETFD: 156 tprints(", "); 157 printflags(fdflags, tcp->u_arg[2], "FD_???"); 158 break; 159 case F_SETOWN: case F_DUPFD: 160 #ifdef F_DUPFD_CLOEXEC 161 case F_DUPFD_CLOEXEC: 162 #endif 163 tprintf(", %ld", tcp->u_arg[2]); 164 break; 165 case F_SETFL: 166 tprints(", "); 167 tprint_open_modes(tcp->u_arg[2]); 168 break; 169 case F_SETLK: case F_SETLKW: 170 tprints(", "); 171 printflock(tcp, tcp->u_arg[2], 0); 172 break; 173 #if USE_PRINTFLOCK64 174 case F_SETLK64: case F_SETLKW64: 175 tprints(", "); 176 printflock64(tcp, tcp->u_arg[2], 0); 177 break; 178 #endif /* USE_PRINTFLOCK64 */ 179 #ifdef F_NOTIFY 180 case F_NOTIFY: 181 tprints(", "); 182 printflags(notifyflags, tcp->u_arg[2], "DN_???"); 183 break; 184 #endif 185 #ifdef F_SETLEASE 186 case F_SETLEASE: 187 tprints(", "); 188 printxval(lockfcmds, tcp->u_arg[2], "F_???"); 189 break; 190 #endif 191 } 192 } 193 else { 194 switch (tcp->u_arg[1]) { 195 case F_DUPFD: 196 #ifdef F_DUPFD_CLOEXEC 197 case F_DUPFD_CLOEXEC: 198 #endif 199 case F_SETFD: case F_SETFL: 200 case F_SETLK: case F_SETLKW: 201 case F_SETOWN: case F_GETOWN: 202 #ifdef F_NOTIFY 203 case F_NOTIFY: 204 #endif 205 #ifdef F_SETLEASE 206 case F_SETLEASE: 207 #endif 208 break; 209 case F_GETFD: 210 if (syserror(tcp) || tcp->u_rval == 0) 211 return 0; 212 tcp->auxstr = sprintflags("flags ", fdflags, tcp->u_rval); 213 return RVAL_HEX|RVAL_STR; 214 case F_GETFL: 215 if (syserror(tcp)) 216 return 0; 217 tcp->auxstr = sprint_open_modes(tcp->u_rval); 218 return RVAL_HEX|RVAL_STR; 219 case F_GETLK: 220 tprints(", "); 221 printflock(tcp, tcp->u_arg[2], 1); 222 break; 223 #if USE_PRINTFLOCK64 224 case F_GETLK64: 225 tprints(", "); 226 printflock64(tcp, tcp->u_arg[2], 1); 227 break; 228 #endif 229 #ifdef F_GETLEASE 230 case F_GETLEASE: 231 if (syserror(tcp)) 232 return 0; 233 tcp->auxstr = xlookup(lockfcmds, tcp->u_rval); 234 return RVAL_HEX|RVAL_STR; 235 #endif 236 default: 237 tprintf(", %#lx", tcp->u_arg[2]); 238 break; 239 } 240 } 241 return 0; 242 } 243 244 #ifdef LOCK_SH 245 246 SYS_FUNC(flock) 247 { 248 if (entering(tcp)) { 249 printfd(tcp, tcp->u_arg[0]); 250 tprints(", "); 251 printflags(flockcmds, tcp->u_arg[1], "LOCK_???"); 252 } 253 return 0; 254 } 255 #endif /* LOCK_SH */ 256 257 SYS_FUNC(close) 258 { 259 if (entering(tcp)) { 260 printfd(tcp, tcp->u_arg[0]); 261 } 262 return 0; 263 } 264 265 SYS_FUNC(dup) 266 { 267 if (entering(tcp)) { 268 printfd(tcp, tcp->u_arg[0]); 269 } 270 return RVAL_FD; 271 } 272 273 static int 274 do_dup2(struct tcb *tcp, int flags_arg) 275 { 276 if (entering(tcp)) { 277 printfd(tcp, tcp->u_arg[0]); 278 tprints(", "); 279 printfd(tcp, tcp->u_arg[1]); 280 if (flags_arg >= 0) { 281 tprints(", "); 282 printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???"); 283 } 284 } 285 return RVAL_FD; 286 } 287 288 SYS_FUNC(dup2) 289 { 290 return do_dup2(tcp, -1); 291 } 292 293 SYS_FUNC(dup3) 294 { 295 return do_dup2(tcp, 2); 296 } 297 298 #if defined(ALPHA) 299 SYS_FUNC(getdtablesize) 300 { 301 return 0; 302 } 303 #endif 304 305 static int 306 decode_select(struct tcb *tcp, long *args, enum bitness_t bitness) 307 { 308 int i, j; 309 int nfds, fdsize; 310 fd_set *fds = NULL; 311 const char *sep; 312 long arg; 313 314 /* Kernel truncates arg[0] to int, we do the same. */ 315 nfds = (int) args[0]; 316 317 /* Kernel rejects negative nfds, so we don't parse it either. */ 318 if (nfds < 0) 319 nfds = 0; 320 321 /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */ 322 if (nfds > 1024*1024) 323 nfds = 1024*1024; 324 325 /* 326 * We had bugs a-la "while (j < args[0])" and "umoven(args[0])" below. 327 * Instead of args[0], use nfds for fd count, fdsize for array lengths. 328 */ 329 fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize; 330 331 if (entering(tcp)) { 332 tprintf("%d", (int) args[0]); 333 334 if (verbose(tcp) && fdsize > 0) { 335 fds = malloc(fdsize); 336 if (!fds) 337 die_out_of_memory(); 338 } 339 for (i = 0; i < 3; i++) { 340 arg = args[i+1]; 341 if (arg == 0) { 342 tprints(", NULL"); 343 continue; 344 } 345 if (!fds) { 346 tprintf(", %#lx", arg); 347 continue; 348 } 349 if (umoven(tcp, arg, fdsize, fds) < 0) { 350 tprints(", [?]"); 351 continue; 352 } 353 tprints(", ["); 354 for (j = 0, sep = "";; j++) { 355 j = next_set_bit(fds, j, nfds); 356 if (j < 0) 357 break; 358 tprints(sep); 359 printfd(tcp, j); 360 sep = " "; 361 } 362 tprints("]"); 363 } 364 free(fds); 365 tprints(", "); 366 printtv_bitness(tcp, args[4], bitness, 0); 367 } 368 else { 369 static char outstr[1024]; 370 char *outptr; 371 #define end_outstr (outstr + sizeof(outstr)) 372 int ready_fds; 373 374 if (syserror(tcp)) 375 return 0; 376 377 ready_fds = tcp->u_rval; 378 if (ready_fds == 0) { 379 tcp->auxstr = "Timeout"; 380 return RVAL_STR; 381 } 382 383 fds = malloc(fdsize); 384 if (!fds) 385 die_out_of_memory(); 386 387 outptr = outstr; 388 sep = ""; 389 for (i = 0; i < 3 && ready_fds > 0; i++) { 390 int first = 1; 391 392 arg = args[i+1]; 393 if (!arg || umoven(tcp, arg, fdsize, fds) < 0) 394 continue; 395 for (j = 0;; j++) { 396 j = next_set_bit(fds, j, nfds); 397 if (j < 0) 398 break; 399 /* +2 chars needed at the end: ']',NUL */ 400 if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) { 401 if (first) { 402 outptr += sprintf(outptr, "%s%s [%u", 403 sep, 404 i == 0 ? "in" : i == 1 ? "out" : "except", 405 j 406 ); 407 first = 0; 408 sep = ", "; 409 } 410 else { 411 outptr += sprintf(outptr, " %u", j); 412 } 413 } 414 if (--ready_fds == 0) 415 break; 416 } 417 if (outptr != outstr) 418 *outptr++ = ']'; 419 } 420 free(fds); 421 /* This contains no useful information on SunOS. */ 422 if (args[4]) { 423 if (outptr < end_outstr - (10 + TIMEVAL_TEXT_BUFSIZE)) { 424 outptr += sprintf(outptr, "%sleft ", sep); 425 outptr = sprinttv(outptr, tcp, args[4], bitness, /*special:*/ 0); 426 } 427 } 428 *outptr = '\0'; 429 tcp->auxstr = outstr; 430 return RVAL_STR; 431 #undef end_outstr 432 } 433 return 0; 434 } 435 436 SYS_FUNC(oldselect) 437 { 438 long args[5]; 439 440 if (umoven(tcp, tcp->u_arg[0], sizeof args, args) < 0) { 441 tprints("[...]"); 442 return 0; 443 } 444 return decode_select(tcp, args, BITNESS_CURRENT); 445 } 446 447 #ifdef ALPHA 448 SYS_FUNC(osf_select) 449 { 450 long *args = tcp->u_arg; 451 return decode_select(tcp, args, BITNESS_32); 452 } 453 #endif 454 455 #include "xlat/epollctls.h" 456 #include "xlat/epollevents.h" 457 #include "xlat/epollflags.h" 458 459 /* Not aliased to printargs_ld: we want it to have a distinct address */ 460 SYS_FUNC(epoll_create) 461 { 462 return printargs_ld(tcp); 463 } 464 465 SYS_FUNC(epoll_create1) 466 { 467 if (entering(tcp)) 468 printflags(epollflags, tcp->u_arg[0], "EPOLL_???"); 469 return 0; 470 } 471 472 #ifdef HAVE_SYS_EPOLL_H 473 static void 474 print_epoll_event(struct epoll_event *ev) 475 { 476 tprints("{"); 477 printflags(epollevents, ev->events, "EPOLL???"); 478 /* We cannot know what format the program uses, so print u32 and u64 479 which will cover every value. */ 480 tprintf(", {u32=%" PRIu32 ", u64=%" PRIu64 "}}", 481 ev->data.u32, ev->data.u64); 482 } 483 #endif 484 485 SYS_FUNC(epoll_ctl) 486 { 487 if (entering(tcp)) { 488 printfd(tcp, tcp->u_arg[0]); 489 tprints(", "); 490 printxval(epollctls, tcp->u_arg[1], "EPOLL_CTL_???"); 491 tprints(", "); 492 printfd(tcp, tcp->u_arg[2]); 493 tprints(", "); 494 if (tcp->u_arg[3] == 0) 495 tprints("NULL"); 496 else { 497 #ifdef HAVE_SYS_EPOLL_H 498 struct epoll_event ev; 499 if ( 500 #ifdef EPOLL_CTL_DEL 501 (tcp->u_arg[1] != EPOLL_CTL_DEL) && 502 #endif 503 umove(tcp, tcp->u_arg[3], &ev) == 0) 504 print_epoll_event(&ev); 505 else 506 #endif 507 tprintf("%lx", tcp->u_arg[3]); 508 } 509 } 510 return 0; 511 } 512 513 static void 514 epoll_wait_common(struct tcb *tcp) 515 { 516 if (entering(tcp)) { 517 printfd(tcp, tcp->u_arg[0]); 518 tprints(", "); 519 } else { 520 if (syserror(tcp)) 521 tprintf("%lx", tcp->u_arg[1]); 522 else if (tcp->u_rval == 0) 523 tprints("{}"); 524 else { 525 #ifdef HAVE_SYS_EPOLL_H 526 struct epoll_event ev, *start, *cur, *end; 527 int failed = 0; 528 529 tprints("{"); 530 start = (struct epoll_event *) tcp->u_arg[1]; 531 end = start + tcp->u_rval; 532 for (cur = start; cur < end; ++cur) { 533 if (cur > start) 534 tprints(", "); 535 if (umove(tcp, (long) cur, &ev) == 0) 536 print_epoll_event(&ev); 537 else { 538 tprints("?"); 539 failed = 1; 540 break; 541 } 542 } 543 tprints("}"); 544 if (failed) 545 tprintf(" %#lx", (long) start); 546 #else 547 tprints("{...}"); 548 #endif 549 } 550 tprintf(", %d, %d", (int) tcp->u_arg[2], (int) tcp->u_arg[3]); 551 } 552 } 553 554 SYS_FUNC(epoll_wait) 555 { 556 epoll_wait_common(tcp); 557 return 0; 558 } 559 560 SYS_FUNC(epoll_pwait) 561 { 562 epoll_wait_common(tcp); 563 if (exiting(tcp)) { 564 tprints(", "); 565 /* NB: kernel requires arg[5] == NSIG / 8 */ 566 print_sigset_addr_len(tcp, tcp->u_arg[4], tcp->u_arg[5]); 567 tprintf(", %lu", tcp->u_arg[5]); 568 } 569 return 0; 570 } 571 572 SYS_FUNC(select) 573 { 574 return decode_select(tcp, tcp->u_arg, BITNESS_CURRENT); 575 } 576 577 SYS_FUNC(pselect6) 578 { 579 int rc = decode_select(tcp, tcp->u_arg, BITNESS_CURRENT); 580 if (entering(tcp)) { 581 long r; 582 struct { 583 unsigned long ptr; 584 unsigned long len; 585 } data; 586 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 587 if (current_wordsize == 4) { 588 struct { 589 uint32_t ptr; 590 uint32_t len; 591 } data32; 592 r = umove(tcp, tcp->u_arg[5], &data32); 593 data.ptr = data32.ptr; 594 data.len = data32.len; 595 } else 596 #endif 597 r = umove(tcp, tcp->u_arg[5], &data); 598 if (r < 0) 599 tprintf(", %#lx", tcp->u_arg[5]); 600 else { 601 tprints(", {"); 602 /* NB: kernel requires data.len == NSIG / 8 */ 603 print_sigset_addr_len(tcp, data.ptr, data.len); 604 tprintf(", %lu}", data.len); 605 } 606 } 607 return rc; 608 } 609 610 static int 611 do_eventfd(struct tcb *tcp, int flags_arg) 612 { 613 if (entering(tcp)) { 614 tprintf("%lu", tcp->u_arg[0]); 615 if (flags_arg >= 0) { 616 tprints(", "); 617 printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???"); 618 } 619 } 620 return 0; 621 } 622 623 SYS_FUNC(eventfd) 624 { 625 return do_eventfd(tcp, -1); 626 } 627 628 SYS_FUNC(eventfd2) 629 { 630 return do_eventfd(tcp, 1); 631 } 632 633 SYS_FUNC(perf_event_open) 634 { 635 if (entering(tcp)) { 636 tprintf("%#lx, %d, %d, %d, ", 637 tcp->u_arg[0], 638 (int) tcp->u_arg[1], 639 (int) tcp->u_arg[2], 640 (int) tcp->u_arg[3]); 641 printflags(perf_event_open_flags, tcp->u_arg[4], 642 "PERF_FLAG_???"); 643 } 644 return 0; 645 } 646