desc.c revision 6522f132ba865f90ba3bb3a740eff191911e4dba
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 = NULL; 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 328 /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */ 329 if (nfds > 1024*1024) 330 nfds = 1024*1024; 331 332 /* 333 * We had bugs a-la "while (j < args[0])" and "umoven(args[0])" below. 334 * Instead of args[0], use nfds for fd count, fdsize for array lengths. 335 */ 336 fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize; 337 338 if (entering(tcp)) { 339 tprintf("%d", (int) args[0]); 340 341 if (fdsize > 0) { 342 fds = malloc(fdsize); 343 if (!fds) 344 die_out_of_memory(); 345 } 346 for (i = 0; i < 3; i++) { 347 arg = args[i+1]; 348 if (arg == 0) { 349 tprints(", NULL"); 350 continue; 351 } 352 if (!verbose(tcp) || !fds) { 353 tprintf(", %#lx", arg); 354 continue; 355 } 356 if (umoven(tcp, arg, fdsize, (char *) fds) < 0) { 357 tprints(", [?]"); 358 continue; 359 } 360 tprints(", ["); 361 for (j = 0, sep = "";; j++) { 362 j = next_set_bit(fds, j, nfds); 363 if (j < 0) 364 break; 365 tprints(sep); 366 printfd(tcp, j); 367 sep = " "; 368 } 369 tprints("]"); 370 } 371 free(fds); 372 tprints(", "); 373 printtv_bitness(tcp, args[4], bitness, 0); 374 } 375 else { 376 static char outstr[1024]; 377 char *outptr; 378#define end_outstr (outstr + sizeof(outstr)) 379 int ready_fds; 380 381 if (syserror(tcp)) 382 return 0; 383 384 ready_fds = tcp->u_rval; 385 if (ready_fds == 0) { 386 tcp->auxstr = "Timeout"; 387 return RVAL_STR; 388 } 389 390 fds = malloc(fdsize); 391 if (!fds) 392 die_out_of_memory(); 393 394 outptr = outstr; 395 sep = ""; 396 for (i = 0; i < 3 && ready_fds > 0; i++) { 397 int first = 1; 398 399 arg = args[i+1]; 400 if (!arg || umoven(tcp, arg, fdsize, (char *) fds) < 0) 401 continue; 402 for (j = 0;; j++) { 403 j = next_set_bit(fds, j, nfds); 404 if (j < 0) 405 break; 406 /* +2 chars needed at the end: ']',NUL */ 407 if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) { 408 if (first) { 409 outptr += sprintf(outptr, "%s%s [%u", 410 sep, 411 i == 0 ? "in" : i == 1 ? "out" : "except", 412 j 413 ); 414 first = 0; 415 sep = ", "; 416 } 417 else { 418 outptr += sprintf(outptr, " %u", j); 419 } 420 } 421 if (--ready_fds == 0) 422 break; 423 } 424 if (outptr != outstr) 425 *outptr++ = ']'; 426 } 427 free(fds); 428 /* This contains no useful information on SunOS. */ 429 if (args[4]) { 430 if (outptr < end_outstr - (10 + TIMEVAL_TEXT_BUFSIZE)) { 431 outptr += sprintf(outptr, "%sleft ", sep); 432 outptr = sprinttv(outptr, tcp, args[4], bitness, /*special:*/ 0); 433 } 434 } 435 *outptr = '\0'; 436 tcp->auxstr = outstr; 437 return RVAL_STR; 438#undef end_outstr 439 } 440 return 0; 441} 442 443int 444sys_oldselect(struct tcb *tcp) 445{ 446 long args[5]; 447 448 if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) { 449 tprints("[...]"); 450 return 0; 451 } 452 return decode_select(tcp, args, BITNESS_CURRENT); 453} 454 455#ifdef ALPHA 456int 457sys_osf_select(struct tcb *tcp) 458{ 459 long *args = tcp->u_arg; 460 return decode_select(tcp, args, BITNESS_32); 461} 462#endif 463 464#include "xlat/epollctls.h" 465#include "xlat/epollevents.h" 466#include "xlat/epollflags.h" 467 468/* Not aliased to printargs_ld: we want it to have a distinct address */ 469int 470sys_epoll_create(struct tcb *tcp) 471{ 472 return printargs_ld(tcp); 473} 474 475int 476sys_epoll_create1(struct tcb *tcp) 477{ 478 if (entering(tcp)) 479 printflags(epollflags, tcp->u_arg[0], "EPOLL_???"); 480 return 0; 481} 482 483#ifdef HAVE_SYS_EPOLL_H 484static void 485print_epoll_event(struct epoll_event *ev) 486{ 487 tprints("{"); 488 printflags(epollevents, ev->events, "EPOLL???"); 489 /* We cannot know what format the program uses, so print u32 and u64 490 which will cover every value. */ 491 tprintf(", {u32=%" PRIu32 ", u64=%" PRIu64 "}}", 492 ev->data.u32, ev->data.u64); 493} 494#endif 495 496int 497sys_epoll_ctl(struct tcb *tcp) 498{ 499 if (entering(tcp)) { 500 printfd(tcp, tcp->u_arg[0]); 501 tprints(", "); 502 printxval(epollctls, tcp->u_arg[1], "EPOLL_CTL_???"); 503 tprints(", "); 504 printfd(tcp, tcp->u_arg[2]); 505 tprints(", "); 506 if (tcp->u_arg[3] == 0) 507 tprints("NULL"); 508 else { 509#ifdef HAVE_SYS_EPOLL_H 510 struct epoll_event ev; 511 if ( 512#ifdef EPOLL_CTL_DEL 513 (tcp->u_arg[1] != EPOLL_CTL_DEL) && 514#endif 515 umove(tcp, tcp->u_arg[3], &ev) == 0) 516 print_epoll_event(&ev); 517 else 518#endif 519 tprintf("%lx", tcp->u_arg[3]); 520 } 521 } 522 return 0; 523} 524 525static void 526epoll_wait_common(struct tcb *tcp) 527{ 528 if (entering(tcp)) { 529 printfd(tcp, tcp->u_arg[0]); 530 tprints(", "); 531 } else { 532 if (syserror(tcp)) 533 tprintf("%lx", tcp->u_arg[1]); 534 else if (tcp->u_rval == 0) 535 tprints("{}"); 536 else { 537#ifdef HAVE_SYS_EPOLL_H 538 struct epoll_event ev, *start, *cur, *end; 539 int failed = 0; 540 541 tprints("{"); 542 start = (struct epoll_event *) tcp->u_arg[1]; 543 end = start + tcp->u_rval; 544 for (cur = start; cur < end; ++cur) { 545 if (cur > start) 546 tprints(", "); 547 if (umove(tcp, (long) cur, &ev) == 0) 548 print_epoll_event(&ev); 549 else { 550 tprints("?"); 551 failed = 1; 552 break; 553 } 554 } 555 tprints("}"); 556 if (failed) 557 tprintf(" %#lx", (long) start); 558#else 559 tprints("{...}"); 560#endif 561 } 562 tprintf(", %d, %d", (int) tcp->u_arg[2], (int) tcp->u_arg[3]); 563 } 564} 565 566int 567sys_epoll_wait(struct tcb *tcp) 568{ 569 epoll_wait_common(tcp); 570 return 0; 571} 572 573int 574sys_epoll_pwait(struct tcb *tcp) 575{ 576 epoll_wait_common(tcp); 577 if (exiting(tcp)) { 578 tprints(", "); 579 /* NB: kernel requires arg[5] == NSIG / 8 */ 580 print_sigset_addr_len(tcp, tcp->u_arg[4], tcp->u_arg[5]); 581 tprintf(", %lu", tcp->u_arg[5]); 582 } 583 return 0; 584} 585 586int 587sys_select(struct tcb *tcp) 588{ 589 return decode_select(tcp, tcp->u_arg, BITNESS_CURRENT); 590} 591 592int 593sys_pselect6(struct tcb *tcp) 594{ 595 int rc = decode_select(tcp, tcp->u_arg, BITNESS_CURRENT); 596 if (entering(tcp)) { 597 long r; 598 struct { 599 unsigned long ptr; 600 unsigned long len; 601 } data; 602#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 603 if (current_wordsize == 4) { 604 struct { 605 uint32_t ptr; 606 uint32_t len; 607 } data32; 608 r = umove(tcp, tcp->u_arg[5], &data32); 609 data.ptr = data32.ptr; 610 data.len = data32.len; 611 } else 612#endif 613 r = umove(tcp, tcp->u_arg[5], &data); 614 if (r < 0) 615 tprintf(", %#lx", tcp->u_arg[5]); 616 else { 617 tprints(", {"); 618 /* NB: kernel requires data.len == NSIG / 8 */ 619 print_sigset_addr_len(tcp, data.ptr, data.len); 620 tprintf(", %lu}", data.len); 621 } 622 } 623 return rc; 624} 625 626static int 627do_eventfd(struct tcb *tcp, int flags_arg) 628{ 629 if (entering(tcp)) { 630 tprintf("%lu", tcp->u_arg[0]); 631 if (flags_arg >= 0) { 632 tprints(", "); 633 printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???"); 634 } 635 } 636 return 0; 637} 638 639int 640sys_eventfd(struct tcb *tcp) 641{ 642 return do_eventfd(tcp, -1); 643} 644 645int 646sys_eventfd2(struct tcb *tcp) 647{ 648 return do_eventfd(tcp, 1); 649} 650 651int 652sys_perf_event_open(struct tcb *tcp) 653{ 654 if (entering(tcp)) { 655 tprintf("%#lx, %d, %d, %d, ", 656 tcp->u_arg[0], 657 (int) tcp->u_arg[1], 658 (int) tcp->u_arg[2], 659 (int) tcp->u_arg[3]); 660 printflags(perf_event_open_flags, tcp->u_arg[4], 661 "PERF_FLAG_???"); 662 } 663 return 0; 664} 665