1 2 #include "inc.h" 3 4 #include <fcntl.h> 5 #include <unistd.h> 6 #include <dirent.h> 7 #include <sys/mount.h> 8 #include <sys/resource.h> 9 #include <sys/socket.h> 10 #include <sys/un.h> 11 #include <netinet/in.h> 12 #if 0 /* not yet, header is missing */ 13 #include <netbt/bluetooth.h> 14 #endif 15 #include <arpa/inet.h> 16 17 /* 18 * This function should always be used when printing a file descriptor. It 19 * currently offers no benefit, but will in the future allow for features such 20 * as color highlighting and tracking of specific open files (TODO). 21 */ 22 void 23 put_fd(struct trace_proc * proc, const char * name, int fd) 24 { 25 26 put_value(proc, name, "%d", fd); 27 } 28 29 static int 30 vfs_read_out(struct trace_proc * proc, const message * m_out) 31 { 32 33 put_fd(proc, "fd", m_out->m_lc_vfs_readwrite.fd); 34 35 return CT_NOTDONE; 36 } 37 38 static void 39 vfs_read_in(struct trace_proc * proc, const message * m_out, 40 const message * m_in, int failed) 41 { 42 43 put_buf(proc, "buf", failed, m_out->m_lc_vfs_readwrite.buf, 44 m_in->m_type); 45 put_value(proc, "len", "%zu", m_out->m_lc_vfs_readwrite.len); 46 put_equals(proc); 47 put_result(proc); 48 } 49 50 static int 51 vfs_write_out(struct trace_proc * proc, const message * m_out) 52 { 53 54 put_fd(proc, "fd", m_out->m_lc_vfs_readwrite.fd); 55 put_buf(proc, "buf", 0, m_out->m_lc_vfs_readwrite.buf, 56 m_out->m_lc_vfs_readwrite.len); 57 put_value(proc, "len", "%zu", m_out->m_lc_vfs_readwrite.len); 58 59 return CT_DONE; 60 } 61 62 static void 63 put_lseek_whence(struct trace_proc * proc, const char * name, int whence) 64 { 65 const char *text = NULL; 66 67 if (!valuesonly) { 68 switch (whence) { 69 TEXT(SEEK_SET); 70 TEXT(SEEK_CUR); 71 TEXT(SEEK_END); 72 } 73 } 74 75 if (text != NULL) 76 put_field(proc, name, text); 77 else 78 put_value(proc, name, "%d", whence); 79 } 80 81 static int 82 vfs_lseek_out(struct trace_proc * proc, const message * m_out) 83 { 84 85 put_fd(proc, "fd", m_out->m_lc_vfs_lseek.fd); 86 put_value(proc, "offset", "%"PRId64, m_out->m_lc_vfs_lseek.offset); 87 put_lseek_whence(proc, "whence", m_out->m_lc_vfs_lseek.whence); 88 89 return CT_DONE; 90 } 91 92 static void 93 vfs_lseek_in(struct trace_proc * proc, const message * __unused m_out, 94 const message * m_in, int failed) 95 { 96 97 if (!failed) 98 put_value(proc, NULL, "%"PRId64, m_in->m_vfs_lc_lseek.offset); 99 else 100 put_result(proc); 101 } 102 103 static const struct flags open_flags[] = { 104 FLAG_MASK(O_ACCMODE, O_RDONLY), 105 FLAG_MASK(O_ACCMODE, O_WRONLY), 106 FLAG_MASK(O_ACCMODE, O_RDWR), 107 #define ACCMODE_ENTRIES 3 /* the first N entries are for O_ACCMODE */ 108 FLAG(O_NONBLOCK), 109 FLAG(O_APPEND), 110 FLAG(O_SHLOCK), 111 FLAG(O_EXLOCK), 112 FLAG(O_ASYNC), 113 FLAG(O_SYNC), 114 FLAG(O_NOFOLLOW), 115 FLAG(O_CREAT), 116 FLAG(O_TRUNC), 117 FLAG(O_EXCL), 118 FLAG(O_NOCTTY), 119 FLAG(O_DSYNC), 120 FLAG(O_RSYNC), 121 FLAG(O_ALT_IO), 122 FLAG(O_DIRECT), 123 FLAG(O_DIRECTORY), 124 FLAG(O_CLOEXEC), 125 FLAG(O_SEARCH), 126 FLAG(O_NOSIGPIPE), 127 }; 128 129 static void 130 put_open_flags(struct trace_proc * proc, const char * name, int value, 131 int full) 132 { 133 const struct flags *fp; 134 unsigned int num; 135 136 fp = open_flags; 137 num = COUNT(open_flags); 138 139 /* 140 * If we're not printing a full open()-style set of flags, but instead 141 * just a loose set of flags, then skip the access mode altogether, 142 * otherwise we'd be printing O_RDONLY when no access mode is given. 143 */ 144 if (!full) { 145 fp += ACCMODE_ENTRIES; 146 num -= ACCMODE_ENTRIES; 147 } 148 149 put_flags(proc, name, fp, num, "0x%x", value); 150 } 151 152 static const struct flags mode_flags[] = { 153 FLAG_MASK(S_IFMT, S_IFIFO), 154 FLAG_MASK(S_IFMT, S_IFCHR), 155 FLAG_MASK(S_IFMT, S_IFDIR), 156 FLAG_MASK(S_IFMT, S_IFBLK), 157 FLAG_MASK(S_IFMT, S_IFREG), 158 FLAG_MASK(S_IFMT, S_IFLNK), 159 FLAG_MASK(S_IFMT, S_IFSOCK), 160 FLAG_MASK(S_IFMT, S_IFWHT), 161 FLAG(S_ARCH1), 162 FLAG(S_ARCH2), 163 FLAG(S_ISUID), 164 FLAG(S_ISGID), 165 FLAG(S_ISTXT), 166 }; 167 168 /* Do not use %04o instead of 0%03o; it is octal even if greater than 0777. */ 169 #define put_mode(p, n, v) \ 170 put_flags(p, n, mode_flags, COUNT(mode_flags), "0%03o", v) 171 172 static void 173 put_path(struct trace_proc * proc, const message * m_out) 174 { 175 size_t len; 176 177 if ((len = m_out->m_lc_vfs_path.len) <= M_PATH_STRING_MAX) 178 put_buf(proc, "path", PF_LOCADDR | PF_PATH, 179 (vir_bytes)m_out->m_lc_vfs_path.buf, len); 180 else 181 put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_path.name, len); 182 } 183 184 static int 185 vfs_open_out(struct trace_proc * proc, const message * m_out) 186 { 187 188 put_path(proc, m_out); 189 put_open_flags(proc, "flags", m_out->m_lc_vfs_path.flags, 190 TRUE /*full*/); 191 192 return CT_DONE; 193 } 194 195 /* This function is shared between creat and open. */ 196 static void 197 vfs_open_in(struct trace_proc * proc, const message * __unused m_out, 198 const message * m_in, int failed) 199 { 200 201 if (!failed) 202 put_fd(proc, NULL, m_in->m_type); 203 else 204 put_result(proc); 205 } 206 207 static int 208 vfs_creat_out(struct trace_proc * proc, const message * m_out) 209 { 210 211 put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_creat.name, 212 m_out->m_lc_vfs_creat.len); 213 put_open_flags(proc, "flags", m_out->m_lc_vfs_creat.flags, 214 TRUE /*full*/); 215 put_mode(proc, "mode", m_out->m_lc_vfs_creat.mode); 216 217 return CT_DONE; 218 } 219 220 static int 221 vfs_close_out(struct trace_proc * proc, const message * m_out) 222 { 223 224 put_fd(proc, "fd", m_out->m_lc_vfs_close.fd); 225 226 return CT_DONE; 227 } 228 229 /* This function is used for link, rename, and symlink. */ 230 static int 231 vfs_link_out(struct trace_proc * proc, const message * m_out) 232 { 233 234 put_buf(proc, "path1", PF_PATH, m_out->m_lc_vfs_link.name1, 235 m_out->m_lc_vfs_link.len1); 236 put_buf(proc, "path2", PF_PATH, m_out->m_lc_vfs_link.name2, 237 m_out->m_lc_vfs_link.len2); 238 239 return CT_DONE; 240 } 241 242 static int 243 vfs_path_out(struct trace_proc * proc, const message * m_out) 244 { 245 246 put_path(proc, m_out); 247 248 return CT_DONE; 249 } 250 251 static int 252 vfs_path_mode_out(struct trace_proc * proc, const message * m_out) 253 { 254 255 put_path(proc, m_out); 256 put_mode(proc, "mode", m_out->m_lc_vfs_path.mode); 257 258 return CT_DONE; 259 } 260 261 void 262 put_dev(struct trace_proc * proc, const char * name, dev_t dev) 263 { 264 devmajor_t major; 265 devminor_t minor; 266 267 major = major(dev); 268 minor = minor(dev); 269 270 /* The value 0 ("no device") should print as "0". */ 271 if (dev != 0 && makedev(major, minor) == dev && !valuesonly) 272 put_value(proc, name, "<%d,%d>", major, minor); 273 else 274 put_value(proc, name, "%"PRIu64, dev); 275 } 276 277 static int 278 vfs_mknod_out(struct trace_proc * proc, const message * m_out) 279 { 280 281 put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_mknod.name, 282 m_out->m_lc_vfs_mknod.len); 283 put_mode(proc, "mode", m_out->m_lc_vfs_mknod.mode); 284 put_dev(proc, "dev", m_out->m_lc_vfs_mknod.device); 285 286 return CT_DONE; 287 } 288 289 static int 290 vfs_chown_out(struct trace_proc * proc, const message * m_out) 291 { 292 293 put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_chown.name, 294 m_out->m_lc_vfs_chown.len); 295 /* -1 means "keep the current value" so print as signed */ 296 put_value(proc, "owner", "%d", m_out->m_lc_vfs_chown.owner); 297 put_value(proc, "group", "%d", m_out->m_lc_vfs_chown.group); 298 299 return CT_DONE; 300 } 301 302 /* TODO: expand this to the full ST_ set. */ 303 static const struct flags mount_flags[] = { 304 FLAG(MNT_RDONLY), 305 }; 306 307 static int 308 vfs_mount_out(struct trace_proc * proc, const message * m_out) 309 { 310 311 put_buf(proc, "special", PF_PATH, m_out->m_lc_vfs_mount.dev, 312 m_out->m_lc_vfs_mount.devlen); 313 put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_mount.path, 314 m_out->m_lc_vfs_mount.pathlen); 315 put_flags(proc, "flags", mount_flags, COUNT(mount_flags), "0x%x", 316 m_out->m_lc_vfs_mount.flags); 317 put_buf(proc, "type", PF_STRING, m_out->m_lc_vfs_mount.type, 318 m_out->m_lc_vfs_mount.typelen); 319 put_buf(proc, "label", PF_STRING, m_out->m_lc_vfs_mount.label, 320 m_out->m_lc_vfs_mount.labellen); 321 322 return CT_DONE; 323 } 324 325 static int 326 vfs_umount_out(struct trace_proc * proc, const message * m_out) 327 { 328 329 put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_umount.name, 330 m_out->m_lc_vfs_umount.namelen); 331 332 return CT_DONE; 333 } 334 335 static void 336 vfs_umount_in(struct trace_proc * proc, const message * m_out, 337 const message * __unused m_in, int failed) 338 { 339 340 put_result(proc); 341 342 if (!failed) { 343 put_open(proc, NULL, 0, "(", ", "); 344 put_buf(proc, "label", PF_STRING, m_out->m_lc_vfs_umount.label, 345 m_out->m_lc_vfs_umount.labellen); 346 347 put_close(proc, ")"); 348 } 349 } 350 351 352 static const struct flags access_flags[] = { 353 FLAG_ZERO(F_OK), 354 FLAG(R_OK), 355 FLAG(W_OK), 356 FLAG(X_OK), 357 }; 358 359 static int 360 vfs_access_out(struct trace_proc * proc, const message * m_out) 361 { 362 363 put_path(proc, m_out); 364 put_flags(proc, "mode", access_flags, COUNT(access_flags), "0x%x", 365 m_out->m_lc_vfs_path.mode); 366 367 return CT_DONE; 368 } 369 370 static int 371 vfs_readlink_out(struct trace_proc * proc, const message * m_out) 372 { 373 374 put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_readlink.name, 375 m_out->m_lc_vfs_readlink.namelen); 376 377 return CT_NOTDONE; 378 } 379 380 static void 381 vfs_readlink_in(struct trace_proc * proc, const message * m_out, 382 const message * m_in, int failed) 383 { 384 385 /* The call does not return a string, so do not use PF_STRING here. */ 386 put_buf(proc, "buf", failed, m_out->m_lc_vfs_readlink.buf, 387 m_in->m_type); 388 put_value(proc, "bufsize", "%zd", m_out->m_lc_vfs_readlink.bufsize); 389 put_equals(proc); 390 put_result(proc); 391 } 392 393 static void 394 put_struct_stat(struct trace_proc * proc, const char * name, int flags, 395 vir_bytes addr) 396 { 397 struct stat buf; 398 int is_special; 399 400 if (!put_open_struct(proc, name, flags, addr, &buf, sizeof(buf))) 401 return; 402 403 /* 404 * The combination of struct stat's frequent usage and large number of 405 * fields makes this structure a pain to print. For now, the idea is 406 * that for verbosity level 0, we print the mode, and the target device 407 * for block/char special files or the file size for all other files. 408 * For higher verbosity levels, largely maintain the structure's own 409 * order of fields. Violate this general structure printing rule for 410 * some fields though, because the actual field order in struct stat is 411 * downright ridiculous. Like elsewhere, for verbosity level 1 print 412 * all fields with meaningful values, and for verbosity level 2 just 413 * print everything, including fields that are known to be not yet 414 * supported and fields that contain known values. 415 */ 416 is_special = (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode)); 417 418 if (verbose > 0) { 419 put_dev(proc, "st_dev", buf.st_dev); 420 put_value(proc, "st_ino", "%"PRId64, buf.st_ino); 421 } 422 put_mode(proc, "st_mode", buf.st_mode); 423 if (verbose > 0) { 424 put_value(proc, "st_nlink", "%u", buf.st_nlink); 425 put_value(proc, "st_uid", "%u", buf.st_uid); 426 put_value(proc, "st_gid", "%u", buf.st_gid); 427 } 428 if (is_special || verbose > 1) 429 put_dev(proc, "st_rdev", buf.st_rdev); 430 if (verbose > 0) { 431 /* 432 * TODO: print the nanosecond part, but possibly only if we are 433 * not actually interpreting the time as a date (another TODO), 434 * and/or possibly only with verbose > 1 (largely unsupported). 435 */ 436 put_time(proc, "st_atime", buf.st_atime); 437 put_time(proc, "st_mtime", buf.st_mtime); 438 put_time(proc, "st_ctime", buf.st_ctime); 439 } 440 if (verbose > 1) /* not yet supported on MINIX3 */ 441 put_time(proc, "st_birthtime", buf.st_birthtime); 442 if (!is_special || verbose > 1) 443 put_value(proc, "st_size", "%"PRId64, buf.st_size); 444 if (verbose > 0) { 445 put_value(proc, "st_blocks", "%"PRId64, buf.st_blocks); 446 put_value(proc, "st_blksize", "%"PRId32, buf.st_blksize); 447 } 448 if (verbose > 1) { 449 put_value(proc, "st_flags", "%"PRIu32, buf.st_flags); 450 put_value(proc, "st_gen", "%"PRIu32, buf.st_gen); 451 } 452 453 put_close_struct(proc, verbose > 1); 454 } 455 456 static int 457 vfs_stat_out(struct trace_proc * proc, const message * m_out) 458 { 459 460 put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_stat.name, 461 m_out->m_lc_vfs_stat.len); 462 463 return CT_NOTDONE; 464 } 465 466 static void 467 vfs_stat_in(struct trace_proc * proc, const message * m_out, 468 const message * __unused m_in, int failed) 469 { 470 471 put_struct_stat(proc, "buf", failed, m_out->m_lc_vfs_stat.buf); 472 put_equals(proc); 473 put_result(proc); 474 } 475 476 static int 477 vfs_fstat_out(struct trace_proc * proc, const message * m_out) 478 { 479 480 put_fd(proc, "fd", m_out->m_lc_vfs_fstat.fd); 481 482 return CT_NOTDONE; 483 } 484 485 static void 486 vfs_fstat_in(struct trace_proc * proc, const message * m_out, 487 const message * __unused m_in, int failed) 488 { 489 490 put_struct_stat(proc, "buf", failed, m_out->m_lc_vfs_fstat.buf); 491 put_equals(proc); 492 put_result(proc); 493 } 494 495 static int 496 vfs_ioctl_out(struct trace_proc * proc, const message * m_out) 497 { 498 499 put_fd(proc, "fd", m_out->m_lc_vfs_ioctl.fd); 500 put_ioctl_req(proc, "req", m_out->m_lc_vfs_ioctl.req, 501 FALSE /*is_svrctl*/); 502 return put_ioctl_arg_out(proc, "arg", m_out->m_lc_vfs_ioctl.req, 503 (vir_bytes)m_out->m_lc_vfs_ioctl.arg, FALSE /*is_svrctl*/); 504 } 505 506 static void 507 vfs_ioctl_in(struct trace_proc * proc, const message * m_out, 508 const message * __unused m_in, int failed) 509 { 510 511 put_ioctl_arg_in(proc, "arg", failed, m_out->m_lc_vfs_ioctl.req, 512 (vir_bytes)m_out->m_lc_vfs_ioctl.arg, FALSE /*is_svrctl*/); 513 } 514 515 static void 516 put_fcntl_cmd(struct trace_proc * proc, const char * name, int cmd) 517 { 518 const char *text = NULL; 519 520 if (!valuesonly) { 521 switch (cmd) { 522 TEXT(F_DUPFD); 523 TEXT(F_GETFD); 524 TEXT(F_SETFD); 525 TEXT(F_GETFL); 526 TEXT(F_SETFL); 527 TEXT(F_GETOWN); 528 TEXT(F_SETOWN); 529 TEXT(F_GETLK); 530 TEXT(F_SETLK); 531 TEXT(F_SETLKW); 532 TEXT(F_CLOSEM); 533 TEXT(F_MAXFD); 534 TEXT(F_DUPFD_CLOEXEC); 535 TEXT(F_GETNOSIGPIPE); 536 TEXT(F_SETNOSIGPIPE); 537 TEXT(F_FREESP); 538 TEXT(F_FLUSH_FS_CACHE); 539 } 540 } 541 542 if (text != NULL) 543 put_field(proc, name, text); 544 else 545 put_value(proc, name, "%d", cmd); 546 } 547 548 static const struct flags fd_flags[] = { 549 FLAG(FD_CLOEXEC), 550 }; 551 552 #define put_fd_flags(p, n, v) \ 553 put_flags(p, n, fd_flags, COUNT(fd_flags), "0x%x", v) 554 555 static void 556 put_flock_type(struct trace_proc * proc, const char * name, int type) 557 { 558 const char *text = NULL; 559 560 if (!valuesonly) { 561 switch (type) { 562 TEXT(F_RDLCK); 563 TEXT(F_UNLCK); 564 TEXT(F_WRLCK); 565 } 566 } 567 568 if (text != NULL) 569 put_field(proc, name, text); 570 else 571 put_value(proc, name, "%d", type); 572 } 573 574 /* 575 * With PF_FULL, also print l_pid, unless l_type is F_UNLCK in which case 576 * only that type is printed. With PF_ALT, print only l_whence/l_start/l_len. 577 */ 578 static void 579 put_struct_flock(struct trace_proc * proc, const char * name, int flags, 580 vir_bytes addr) 581 { 582 struct flock flock; 583 int limited; 584 585 if (!put_open_struct(proc, name, flags, addr, &flock, sizeof(flock))) 586 return; 587 588 limited = ((flags & PF_FULL) && flock.l_type == F_UNLCK); 589 590 if (!(flags & PF_ALT)) 591 put_flock_type(proc, "l_type", flock.l_type); 592 if (!limited) { 593 put_lseek_whence(proc, "l_whence", flock.l_whence); 594 put_value(proc, "l_start", "%"PRId64, flock.l_start); 595 put_value(proc, "l_len", "%"PRId64, flock.l_len); 596 if (flags & PF_FULL) 597 put_value(proc, "l_pid", "%d", flock.l_pid); 598 } 599 600 put_close_struct(proc, TRUE /*all*/); 601 } 602 603 static int 604 vfs_fcntl_out(struct trace_proc * proc, const message * m_out) 605 { 606 607 put_fd(proc, "fd", m_out->m_lc_vfs_fcntl.fd); 608 put_fcntl_cmd(proc, "cmd", m_out->m_lc_vfs_fcntl.cmd); 609 610 switch (m_out->m_lc_vfs_fcntl.cmd) { 611 case F_DUPFD: 612 case F_DUPFD_CLOEXEC: 613 put_fd(proc, "fd2", m_out->m_lc_vfs_fcntl.arg_int); 614 break; 615 case F_SETFD: 616 put_fd_flags(proc, "flags", m_out->m_lc_vfs_fcntl.arg_int); 617 break; 618 case F_SETFL: 619 /* 620 * One of those difficult cases: the access mode is ignored, so 621 * we don't want to print O_RDONLY if it is not given. On the 622 * other hand, fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_..) is 623 * a fairly common construction, in which case we don't want to 624 * print eg O_..|0x2 if the access mode is O_RDWR. Thus, we 625 * compromise: show the access mode if any of its bits are set. 626 */ 627 put_open_flags(proc, "flags", m_out->m_lc_vfs_fcntl.arg_int, 628 m_out->m_lc_vfs_fcntl.arg_int & O_ACCMODE /*full*/); 629 break; 630 case F_SETLK: 631 case F_SETLKW: 632 put_struct_flock(proc, "lkp", 0, 633 m_out->m_lc_vfs_fcntl.arg_ptr); 634 break; 635 case F_FREESP: 636 put_struct_flock(proc, "lkp", PF_ALT, 637 m_out->m_lc_vfs_fcntl.arg_ptr); 638 break; 639 case F_SETNOSIGPIPE: 640 put_value(proc, "arg", "%d", m_out->m_lc_vfs_fcntl.arg_int); 641 break; 642 } 643 644 return (m_out->m_lc_vfs_fcntl.cmd != F_GETLK) ? CT_DONE : CT_NOTDONE; 645 } 646 647 static void 648 vfs_fcntl_in(struct trace_proc * proc, const message * m_out, 649 const message * m_in, int failed) 650 { 651 652 switch (m_out->m_lc_vfs_fcntl.cmd) { 653 case F_GETFD: 654 if (failed) 655 break; 656 put_fd_flags(proc, NULL, m_in->m_type); 657 return; 658 case F_GETFL: 659 if (failed) 660 break; 661 put_open_flags(proc, NULL, m_in->m_type, TRUE /*full*/); 662 return; 663 case F_GETLK: 664 put_struct_flock(proc, "lkp", failed | PF_FULL, 665 m_out->m_lc_vfs_fcntl.arg_ptr); 666 put_equals(proc); 667 break; 668 } 669 670 put_result(proc); 671 } 672 673 static int 674 vfs_pipe2_out(struct trace_proc * __unused proc, 675 const message * __unused m_out) 676 { 677 678 return CT_NOTDONE; 679 } 680 681 static void 682 vfs_pipe2_in(struct trace_proc * proc, const message * m_out, 683 const message * m_in, int failed) 684 { 685 686 if (!failed) { 687 put_open(proc, "fd", PF_NONAME, "[", ", "); 688 put_fd(proc, "rfd", m_in->m_vfs_lc_fdpair.fd0); 689 put_fd(proc, "wfd", m_in->m_vfs_lc_fdpair.fd1); 690 put_close(proc, "]"); 691 } else 692 put_field(proc, "fd", "&.."); 693 put_open_flags(proc, "flags", m_out->m_lc_vfs_pipe2.flags, 694 FALSE /*full*/); 695 put_equals(proc); 696 put_result(proc); 697 } 698 699 static int 700 vfs_umask_out(struct trace_proc * proc, const message * m_out) 701 { 702 703 put_mode(proc, NULL, m_out->m_lc_vfs_umask.mask); 704 705 return CT_DONE; 706 } 707 708 static void 709 vfs_umask_in(struct trace_proc * proc, const message * __unused m_out, 710 const message * m_in, int failed) 711 { 712 713 if (!failed) 714 put_mode(proc, NULL, m_in->m_type); 715 else 716 put_result(proc); 717 718 } 719 720 static void 721 put_dirent_type(struct trace_proc * proc, const char * name, unsigned int type) 722 { 723 const char *text = NULL; 724 725 if (!valuesonly) { 726 switch (type) { 727 TEXT(DT_UNKNOWN); 728 TEXT(DT_FIFO); 729 TEXT(DT_CHR); 730 TEXT(DT_DIR); 731 TEXT(DT_BLK); 732 TEXT(DT_REG); 733 TEXT(DT_LNK); 734 TEXT(DT_SOCK); 735 TEXT(DT_WHT); 736 } 737 } 738 739 if (text != NULL) 740 put_field(proc, name, text); 741 else 742 put_value(proc, name, "%u", type); 743 } 744 745 static void 746 put_struct_dirent(struct trace_proc * proc, const char *name, int flags, 747 vir_bytes addr) 748 { 749 struct dirent dirent; 750 751 if (!put_open_struct(proc, name, flags, addr, &dirent, sizeof(dirent))) 752 return; 753 754 if (verbose > 0) 755 put_value(proc, "d_fileno", "%"PRIu64, dirent.d_fileno); 756 if (verbose > 1) { 757 put_value(proc, "d_reclen", "%u", dirent.d_reclen); 758 put_value(proc, "d_namlen", "%u", dirent.d_namlen); 759 } 760 if (verbose >= 1 + (dirent.d_type == DT_UNKNOWN)) 761 put_dirent_type(proc, "d_type", dirent.d_type); 762 put_buf(proc, "d_name", PF_LOCADDR, (vir_bytes)dirent.d_name, 763 MIN(dirent.d_namlen, sizeof(dirent.d_name))); 764 765 put_close_struct(proc, verbose > 1); 766 } 767 768 static void 769 put_dirent_array(struct trace_proc * proc, const char * name, int flags, 770 vir_bytes addr, ssize_t size) 771 { 772 struct dirent dirent; 773 unsigned count, max; 774 ssize_t off, chunk; 775 776 if ((flags & PF_FAILED) || valuesonly > 1 || size < 0) { 777 put_ptr(proc, name, addr); 778 779 return; 780 } 781 782 if (size == 0) { 783 put_field(proc, name, "[]"); 784 785 return; 786 } 787 788 if (verbose == 0) 789 max = 0; /* TODO: should we set this to 1 instead? */ 790 else if (verbose == 1) 791 max = 3; /* low; just to give an indication where we are */ 792 else 793 max = INT_MAX; 794 795 /* 796 * TODO: as is, this is highly inefficient, as we are typically copying 797 * in the same pieces of memory in repeatedly.. 798 */ 799 count = 0; 800 for (off = 0; off < size; off += chunk) { 801 chunk = size - off; 802 if ((size_t)chunk > sizeof(dirent)) 803 chunk = (ssize_t)sizeof(dirent); 804 if ((size_t)chunk < _DIRENT_MINSIZE(&dirent)) 805 break; 806 807 if (mem_get_data(proc->pid, addr + off, &dirent, chunk) < 0) { 808 if (off == 0) { 809 put_ptr(proc, name, addr); 810 811 return; 812 } 813 814 break; 815 } 816 817 if (off == 0) 818 put_open(proc, name, PF_NONAME, "[", ", "); 819 820 if (count < max) 821 put_struct_dirent(proc, NULL, PF_LOCADDR, 822 (vir_bytes)&dirent); 823 824 if (chunk > dirent.d_reclen) 825 chunk = dirent.d_reclen; 826 count++; 827 } 828 829 if (off < size) 830 put_tail(proc, 0, 0); 831 else if (count > max) 832 put_tail(proc, count, max); 833 put_close(proc, "]"); 834 } 835 836 static int 837 vfs_getdents_out(struct trace_proc * proc, const message * m_out) 838 { 839 840 put_fd(proc, "fd", m_out->m_lc_vfs_readwrite.fd); 841 842 return CT_NOTDONE; 843 } 844 845 static void 846 vfs_getdents_in(struct trace_proc * proc, const message * m_out, 847 const message * m_in, int failed) 848 { 849 850 put_dirent_array(proc, "buf", failed, m_out->m_lc_vfs_readwrite.buf, 851 m_in->m_type); 852 put_value(proc, "len", "%zu", m_out->m_lc_vfs_readwrite.len); 853 put_equals(proc); 854 put_result(proc); 855 } 856 857 static void 858 put_fd_set(struct trace_proc * proc, const char * name, vir_bytes addr, 859 int nfds) 860 { 861 fd_set set; 862 size_t off; 863 unsigned int i, j, words, count, max; 864 865 if (addr == 0 || nfds < 0) { 866 put_ptr(proc, name, addr); 867 868 return; 869 } 870 871 /* 872 * Each process may define its own FD_SETSIZE, so our fd_set may be of 873 * a different size than theirs. Thus, we copy at a granularity known 874 * to be valid in any case: a single word of bits. We make the 875 * assumption that fd_set consists purely of bits, so that we can use 876 * the second (and so on) bit word as an fd_set by itself. 877 */ 878 words = (nfds + NFDBITS - 1) / NFDBITS; 879 880 count = 0; 881 882 if (verbose == 0) 883 max = 16; 884 else if (verbose == 1) 885 max = FD_SETSIZE; 886 else 887 max = INT_MAX; 888 889 /* TODO: copy in more at once, but stick to fd_mask boundaries. */ 890 for (off = 0, i = 0; i < words; i++, off += sizeof(fd_mask)) { 891 if (mem_get_data(proc->pid, addr + off, &set, 892 sizeof(fd_mask)) != 0) { 893 if (count == 0) { 894 put_ptr(proc, name, addr); 895 896 return; 897 } 898 899 break; 900 } 901 902 for (j = 0; j < NFDBITS; j++) { 903 if (FD_ISSET(j, &set)) { 904 if (count == 0) 905 put_open(proc, name, PF_NONAME, "[", 906 " "); 907 908 if (count < max) 909 put_fd(proc, NULL, i * NFDBITS + j); 910 911 count++; 912 } 913 } 914 } 915 916 /* 917 * The empty set should print as "[]". If copying any part failed, it 918 * should print as "[x, ..(?)]" where x is the set printed so far, if 919 * any. If copying never failed, and we did not print all fds in the 920 * set, print the remaining count n as "[x, ..(+n)]" at the end. 921 */ 922 if (count == 0) 923 put_open(proc, name, PF_NONAME, "[", " "); 924 925 if (i < words) 926 put_tail(proc, 0, 0); 927 else if (count > max) 928 put_tail(proc, count, max); 929 930 put_close(proc, "]"); 931 } 932 933 static int 934 vfs_select_out(struct trace_proc * proc, const message * m_out) 935 { 936 int nfds; 937 938 nfds = m_out->m_lc_vfs_select.nfds; 939 940 put_fd(proc, "nfds", nfds); /* not really a file descriptor.. */ 941 put_fd_set(proc, "readfds", 942 (vir_bytes)m_out->m_lc_vfs_select.readfds, nfds); 943 put_fd_set(proc, "writefds", 944 (vir_bytes)m_out->m_lc_vfs_select.writefds, nfds); 945 put_fd_set(proc, "errorfds", 946 (vir_bytes)m_out->m_lc_vfs_select.errorfds, nfds); 947 put_struct_timeval(proc, "timeout", 0, m_out->m_lc_vfs_select.timeout); 948 949 return CT_DONE; 950 } 951 952 static void 953 vfs_select_in(struct trace_proc * proc, const message * m_out, 954 const message * __unused m_in, int failed) 955 { 956 vir_bytes readfds, writefds, errorfds; 957 int nfds; 958 959 put_result(proc); 960 if (failed) 961 return; 962 963 nfds = m_out->m_lc_vfs_select.nfds; 964 965 readfds = (vir_bytes)m_out->m_lc_vfs_select.readfds; 966 writefds = (vir_bytes)m_out->m_lc_vfs_select.writefds; 967 errorfds = (vir_bytes)m_out->m_lc_vfs_select.errorfds; 968 969 if (readfds == 0 && writefds == 0 && errorfds == 0) 970 return; 971 972 /* Omit names, because it looks weird. */ 973 put_open(proc, NULL, PF_NONAME, "(", ", "); 974 if (readfds != 0) 975 put_fd_set(proc, "readfds", readfds, nfds); 976 if (writefds != 0) 977 put_fd_set(proc, "writefds", writefds, nfds); 978 if (errorfds != 0) 979 put_fd_set(proc, "errorfds", errorfds, nfds); 980 put_close(proc, ")"); 981 } 982 983 static int 984 vfs_fchdir_out(struct trace_proc * proc, const message * m_out) 985 { 986 987 put_fd(proc, "fd", m_out->m_lc_vfs_fchdir.fd); 988 989 return CT_DONE; 990 } 991 992 static int 993 vfs_fsync_out(struct trace_proc * proc, const message * m_out) 994 { 995 996 put_fd(proc, "fd", m_out->m_lc_vfs_fsync.fd); 997 998 return CT_DONE; 999 } 1000 1001 static int 1002 vfs_truncate_out(struct trace_proc * proc, const message * m_out) 1003 { 1004 1005 put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_truncate.name, 1006 m_out->m_lc_vfs_truncate.len); 1007 put_value(proc, "length", "%"PRId64, m_out->m_lc_vfs_truncate.offset); 1008 1009 return CT_DONE; 1010 } 1011 1012 static int 1013 vfs_ftruncate_out(struct trace_proc * proc, const message * m_out) 1014 { 1015 1016 put_fd(proc, "fd", m_out->m_lc_vfs_truncate.fd); 1017 put_value(proc, "length", "%"PRId64, m_out->m_lc_vfs_truncate.offset); 1018 1019 return CT_DONE; 1020 } 1021 1022 static int 1023 vfs_fchmod_out(struct trace_proc * proc, const message * m_out) 1024 { 1025 1026 put_fd(proc, "fd", m_out->m_lc_vfs_fchmod.fd); 1027 put_mode(proc, "mode", m_out->m_lc_vfs_fchmod.mode); 1028 1029 return CT_DONE; 1030 } 1031 1032 static int 1033 vfs_fchown_out(struct trace_proc * proc, const message * m_out) 1034 { 1035 1036 put_fd(proc, "fd", m_out->m_lc_vfs_chown.fd); 1037 /* -1 means "keep the current value" so print as signed */ 1038 put_value(proc, "owner", "%d", m_out->m_lc_vfs_chown.owner); 1039 put_value(proc, "group", "%d", m_out->m_lc_vfs_chown.group); 1040 1041 return CT_DONE; 1042 } 1043 1044 static const char * 1045 vfs_utimens_name(const message * m_out) 1046 { 1047 int has_path, has_flags; 1048 1049 has_path = (m_out->m_vfs_utimens.name != NULL); 1050 has_flags = (m_out->m_vfs_utimens.flags != 0); 1051 1052 if (has_path && m_out->m_vfs_utimens.flags == AT_SYMLINK_NOFOLLOW) 1053 return "lutimens"; 1054 if (has_path && !has_flags) 1055 return "utimens"; 1056 else if (!has_path && !has_flags) 1057 return "futimens"; 1058 else 1059 return "utimensat"; 1060 } 1061 1062 static const struct flags at_flags[] = { 1063 FLAG(AT_EACCESS), 1064 FLAG(AT_SYMLINK_NOFOLLOW), 1065 FLAG(AT_SYMLINK_FOLLOW), 1066 FLAG(AT_REMOVEDIR), 1067 }; 1068 1069 static void 1070 put_utimens_timespec(struct trace_proc * proc, const char * name, 1071 time_t sec, long nsec) 1072 { 1073 1074 /* No field names. */ 1075 put_open(proc, name, PF_NONAME, "{", ", "); 1076 1077 put_time(proc, "tv_sec", sec); 1078 1079 if (!valuesonly && nsec == UTIME_NOW) 1080 put_field(proc, "tv_nsec", "UTIME_NOW"); 1081 else if (!valuesonly && nsec == UTIME_OMIT) 1082 put_field(proc, "tv_nsec", "UTIME_OMIT"); 1083 else 1084 put_value(proc, "tv_nsec", "%ld", nsec); 1085 1086 put_close(proc, "}"); 1087 } 1088 1089 static int 1090 vfs_utimens_out(struct trace_proc * proc, const message * m_out) 1091 { 1092 int has_path, has_flags; 1093 1094 /* Here we do not care about the utimens/lutimens distinction. */ 1095 has_path = (m_out->m_vfs_utimens.name != NULL); 1096 has_flags = !!(m_out->m_vfs_utimens.flags & ~AT_SYMLINK_NOFOLLOW); 1097 1098 if (has_path && has_flags) 1099 put_field(proc, "fd", "AT_CWD"); /* utimensat */ 1100 else if (!has_path) 1101 put_fd(proc, "fd", m_out->m_vfs_utimens.fd); /* futimes */ 1102 if (has_path || has_flags) /* lutimes, utimes, utimensat */ 1103 put_buf(proc, "path", PF_PATH, 1104 (vir_bytes)m_out->m_vfs_utimens.name, 1105 m_out->m_vfs_utimens.len); 1106 1107 put_open(proc, "times", 0, "[", ", "); 1108 put_utimens_timespec(proc, "atime", m_out->m_vfs_utimens.atime, 1109 m_out->m_vfs_utimens.ansec); 1110 put_utimens_timespec(proc, "mtime", m_out->m_vfs_utimens.mtime, 1111 m_out->m_vfs_utimens.mnsec); 1112 put_close(proc, "]"); 1113 1114 if (has_flags) 1115 put_flags(proc, "flag", at_flags, COUNT(at_flags), "0x%x", 1116 m_out->m_vfs_utimens.flags); 1117 1118 return CT_DONE; 1119 } 1120 1121 static const struct flags statvfs_flags[] = { 1122 FLAG(ST_WAIT), 1123 FLAG(ST_NOWAIT), 1124 }; 1125 1126 static const struct flags st_flags[] = { 1127 FLAG(ST_RDONLY), 1128 FLAG(ST_SYNCHRONOUS), 1129 FLAG(ST_NOEXEC), 1130 FLAG(ST_NOSUID), 1131 FLAG(ST_NODEV), 1132 FLAG(ST_UNION), 1133 FLAG(ST_ASYNC), 1134 FLAG(ST_NOCOREDUMP), 1135 FLAG(ST_RELATIME), 1136 FLAG(ST_IGNORE), 1137 FLAG(ST_NOATIME), 1138 FLAG(ST_SYMPERM), 1139 FLAG(ST_NODEVMTIME), 1140 FLAG(ST_SOFTDEP), 1141 FLAG(ST_LOG), 1142 FLAG(ST_EXTATTR), 1143 FLAG(ST_EXRDONLY), 1144 FLAG(ST_EXPORTED), 1145 FLAG(ST_DEFEXPORTED), 1146 FLAG(ST_EXPORTANON), 1147 FLAG(ST_EXKERB), 1148 FLAG(ST_EXNORESPORT), 1149 FLAG(ST_EXPUBLIC), 1150 FLAG(ST_LOCAL), 1151 FLAG(ST_QUOTA), 1152 FLAG(ST_ROOTFS), 1153 FLAG(ST_NOTRUNC), 1154 }; 1155 1156 static void 1157 put_struct_statvfs(struct trace_proc * proc, const char * name, int flags, 1158 vir_bytes addr) 1159 { 1160 struct statvfs buf; 1161 1162 if (!put_open_struct(proc, name, flags, addr, &buf, sizeof(buf))) 1163 return; 1164 1165 put_flags(proc, "f_flag", st_flags, COUNT(st_flags), "0x%x", 1166 buf.f_flag); 1167 put_value(proc, "f_bsize", "%lu", buf.f_bsize); 1168 if (verbose > 0 || buf.f_bsize != buf.f_frsize) 1169 put_value(proc, "f_frsize", "%lu", buf.f_frsize); 1170 if (verbose > 1) 1171 put_value(proc, "f_iosize", "%lu", buf.f_iosize); 1172 1173 put_value(proc, "f_blocks", "%"PRIu64, buf.f_blocks); 1174 put_value(proc, "f_bfree", "%"PRIu64, buf.f_bfree); 1175 if (verbose > 1) { 1176 put_value(proc, "f_bavail", "%"PRIu64, buf.f_bavail); 1177 put_value(proc, "f_bresvd", "%"PRIu64, buf.f_bresvd); 1178 } 1179 1180 if (verbose > 0) { 1181 put_value(proc, "f_files", "%"PRIu64, buf.f_files); 1182 put_value(proc, "f_ffree", "%"PRIu64, buf.f_ffree); 1183 } 1184 if (verbose > 1) { 1185 put_value(proc, "f_favail", "%"PRIu64, buf.f_favail); 1186 put_value(proc, "f_fresvd", "%"PRIu64, buf.f_fresvd); 1187 } 1188 1189 if (verbose > 1) { 1190 put_value(proc, "f_syncreads", "%"PRIu64, buf.f_syncreads); 1191 put_value(proc, "f_syncwrites", "%"PRIu64, buf.f_syncwrites); 1192 put_value(proc, "f_asyncreads", "%"PRIu64, buf.f_asyncreads); 1193 put_value(proc, "f_asyncwrites", "%"PRIu64, buf.f_asyncwrites); 1194 1195 put_value(proc, "f_fsidx", "<%"PRId32",%"PRId32">", 1196 buf.f_fsidx.__fsid_val[0], buf.f_fsidx.__fsid_val[1]); 1197 } 1198 put_dev(proc, "f_fsid", buf.f_fsid); /* MINIX3 interpretation! */ 1199 1200 if (verbose > 0) 1201 put_value(proc, "f_namemax", "%lu", buf.f_namemax); 1202 if (verbose > 1) 1203 put_value(proc, "f_owner", "%u", buf.f_owner); 1204 1205 put_buf(proc, "f_fstypename", PF_STRING | PF_LOCADDR, 1206 (vir_bytes)&buf.f_fstypename, sizeof(buf.f_fstypename)); 1207 if (verbose > 0) 1208 put_buf(proc, "f_mntfromname", PF_STRING | PF_LOCADDR, 1209 (vir_bytes)&buf.f_mntfromname, sizeof(buf.f_mntfromname)); 1210 put_buf(proc, "f_mntonname", PF_STRING | PF_LOCADDR, 1211 (vir_bytes)&buf.f_mntonname, sizeof(buf.f_mntonname)); 1212 1213 put_close_struct(proc, verbose > 1); 1214 } 1215 1216 static void 1217 put_statvfs_array(struct trace_proc * proc, const char * name, int flags, 1218 vir_bytes addr, int count) 1219 { 1220 struct statvfs buf; 1221 int i, max; 1222 1223 if ((flags & PF_FAILED) || valuesonly > 1 || count < 0) { 1224 put_ptr(proc, name, addr); 1225 1226 return; 1227 } 1228 1229 if (count == 0) { 1230 put_field(proc, name, "[]"); 1231 1232 return; 1233 } 1234 1235 if (verbose == 0) 1236 max = 0; 1237 else if (verbose == 1) 1238 max = 1; /* TODO: is this reasonable? */ 1239 else 1240 max = INT_MAX; 1241 1242 if (max > count) 1243 max = count; 1244 1245 for (i = 0; i < max; i++) { 1246 if (mem_get_data(proc->pid, addr + i * sizeof(buf), &buf, 1247 sizeof(buf)) < 0) { 1248 if (i == 0) { 1249 put_ptr(proc, name, addr); 1250 1251 return; 1252 } 1253 1254 break; 1255 } 1256 1257 if (i == 0) 1258 put_open(proc, name, PF_NONAME, "[", ", "); 1259 1260 put_struct_statvfs(proc, NULL, PF_LOCADDR, (vir_bytes)&buf); 1261 } 1262 1263 if (i == 0) 1264 put_open(proc, name, PF_NONAME, "[", ", "); 1265 if (i < max) 1266 put_tail(proc, 0, 0); 1267 else if (count > i) 1268 put_tail(proc, count, i); 1269 put_close(proc, "]"); 1270 } 1271 1272 static int 1273 vfs_getvfsstat_out(struct trace_proc * proc, const message * m_out) 1274 { 1275 1276 if (m_out->m_lc_vfs_getvfsstat.buf == 0) { 1277 put_ptr(proc, "buf", m_out->m_lc_vfs_getvfsstat.buf); 1278 put_value(proc, "bufsize", "%zu", 1279 m_out->m_lc_vfs_getvfsstat.len); 1280 put_flags(proc, "flags", statvfs_flags, COUNT(statvfs_flags), 1281 "%d", m_out->m_lc_vfs_getvfsstat.flags); 1282 return CT_DONE; 1283 } else 1284 return CT_NOTDONE; 1285 } 1286 1287 static void 1288 vfs_getvfsstat_in(struct trace_proc * proc, const message * m_out, 1289 const message * m_in, int failed) 1290 { 1291 1292 if (m_out->m_lc_vfs_getvfsstat.buf != 0) { 1293 put_statvfs_array(proc, "buf", failed, 1294 m_out->m_lc_vfs_getvfsstat.buf, m_in->m_type); 1295 put_value(proc, "bufsize", "%zu", 1296 m_out->m_lc_vfs_getvfsstat.len); 1297 put_flags(proc, "flags", statvfs_flags, COUNT(statvfs_flags), 1298 "%d", m_out->m_lc_vfs_getvfsstat.flags); 1299 put_equals(proc); 1300 } 1301 put_result(proc); 1302 } 1303 1304 static int 1305 vfs_statvfs1_out(struct trace_proc * proc, const message * m_out) 1306 { 1307 1308 put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_statvfs1.name, 1309 m_out->m_lc_vfs_statvfs1.len); 1310 1311 return CT_NOTDONE; 1312 } 1313 1314 static void 1315 vfs_statvfs1_in(struct trace_proc * proc, const message * m_out, 1316 const message * __unused m_in, int failed) 1317 { 1318 1319 put_struct_statvfs(proc, "buf", failed, m_out->m_lc_vfs_statvfs1.buf); 1320 put_flags(proc, "flags", statvfs_flags, COUNT(statvfs_flags), "%d", 1321 m_out->m_lc_vfs_statvfs1.flags); 1322 put_equals(proc); 1323 put_result(proc); 1324 } 1325 1326 /* This function is shared between statvfs1 and fstatvfs1. */ 1327 static int 1328 vfs_fstatvfs1_out(struct trace_proc * proc, const message * m_out) 1329 { 1330 1331 put_fd(proc, "fd", m_out->m_lc_vfs_statvfs1.fd); 1332 1333 return CT_NOTDONE; 1334 } 1335 1336 static int 1337 vfs_svrctl_out(struct trace_proc * proc, const message * m_out) 1338 { 1339 1340 put_ioctl_req(proc, "request", m_out->m_lc_svrctl.request, 1341 TRUE /*is_svrctl*/); 1342 return put_ioctl_arg_out(proc, "arg", m_out->m_lc_svrctl.request, 1343 m_out->m_lc_svrctl.arg, TRUE /*is_svrctl*/); 1344 } 1345 1346 static void 1347 vfs_svrctl_in(struct trace_proc * proc, const message * m_out, 1348 const message * __unused m_in, int failed) 1349 { 1350 1351 put_ioctl_arg_in(proc, "arg", failed, m_out->m_lc_svrctl.request, 1352 m_out->m_lc_svrctl.arg, TRUE /*is_svrctl*/); 1353 } 1354 1355 static int 1356 vfs_gcov_flush_out(struct trace_proc * proc, const message * m_out) 1357 { 1358 1359 put_buf(proc, "label", PF_STRING, m_out->m_lc_vfs_gcov.label, 1360 m_out->m_lc_vfs_gcov.labellen); 1361 put_ptr(proc, "buff", m_out->m_lc_vfs_gcov.buf); 1362 put_value(proc, "buff_sz", "%zu", m_out->m_lc_vfs_gcov.buflen); 1363 1364 return CT_DONE; 1365 } 1366 1367 void 1368 put_socket_family(struct trace_proc * proc, const char * name, int family) 1369 { 1370 const char *text = NULL; 1371 1372 if (!valuesonly) { 1373 /* 1374 * For socket(2) and socketpair(2) this should really be using 1375 * the prefix "PF_" since those functions take a protocol 1376 * family rather than an address family. This rule is applied 1377 * fairly consistently within the system. Here I caved because 1378 * I don't want to duplicate this entire function just for the 1379 * one letter. There are exceptions however; some names only 1380 * exist as "PF_". 1381 */ 1382 switch (family) { 1383 TEXT(AF_UNSPEC); 1384 TEXT(AF_LOCAL); 1385 TEXT(AF_INET); 1386 TEXT(AF_IMPLINK); 1387 TEXT(AF_PUP); 1388 TEXT(AF_CHAOS); 1389 TEXT(AF_NS); 1390 TEXT(AF_ISO); 1391 TEXT(AF_ECMA); 1392 TEXT(AF_DATAKIT); 1393 TEXT(AF_CCITT); 1394 TEXT(AF_SNA); 1395 TEXT(AF_DECnet); 1396 TEXT(AF_DLI); 1397 TEXT(AF_LAT); 1398 TEXT(AF_HYLINK); 1399 TEXT(AF_APPLETALK); 1400 TEXT(AF_OROUTE); 1401 TEXT(AF_LINK); 1402 TEXT(PF_XTP); 1403 TEXT(AF_COIP); 1404 TEXT(AF_CNT); 1405 TEXT(PF_RTIP); 1406 TEXT(AF_IPX); 1407 TEXT(AF_INET6); 1408 TEXT(PF_PIP); 1409 TEXT(AF_ISDN); 1410 TEXT(AF_NATM); 1411 TEXT(AF_ARP); 1412 TEXT(PF_KEY); 1413 TEXT(AF_BLUETOOTH); 1414 TEXT(AF_IEEE80211); 1415 TEXT(AF_MPLS); 1416 TEXT(AF_ROUTE); 1417 } 1418 } 1419 1420 if (text != NULL) 1421 put_field(proc, name, text); 1422 else 1423 put_value(proc, name, "%d", family); 1424 } 1425 1426 static const struct flags socket_types[] = { 1427 FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_STREAM), 1428 FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_DGRAM), 1429 FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_RAW), 1430 FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_RDM), 1431 FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_SEQPACKET), 1432 FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_CONN_DGRAM), 1433 FLAG(SOCK_CLOEXEC), 1434 FLAG(SOCK_NONBLOCK), 1435 FLAG(SOCK_NOSIGPIPE), 1436 }; 1437 1438 void 1439 put_socket_type(struct trace_proc * proc, const char * name, int type) 1440 { 1441 1442 put_flags(proc, name, socket_types, COUNT(socket_types), "%d", type); 1443 } 1444 1445 static void 1446 put_socket_protocol(struct trace_proc * proc, const char * name, int family, 1447 int type, int protocol) 1448 { 1449 const char *text = NULL; 1450 1451 if (!valuesonly && (type == SOCK_RAW || protocol != 0)) { 1452 switch (family) { 1453 case PF_INET: 1454 case PF_INET6: 1455 /* TODO: is this all that is used in socket(2)? */ 1456 switch (protocol) { 1457 TEXT(IPPROTO_IP); 1458 TEXT(IPPROTO_ICMP); 1459 TEXT(IPPROTO_IGMP); 1460 TEXT(IPPROTO_TCP); 1461 TEXT(IPPROTO_UDP); 1462 TEXT(IPPROTO_ICMPV6); 1463 TEXT(IPPROTO_RAW); 1464 } 1465 break; 1466 #if 0 /* not yet */ 1467 case PF_BLUETOOTH: 1468 switch (protocol) { 1469 TEXT(BTPROTO_HCI); 1470 TEXT(BTPROTO_L2CAP); 1471 TEXT(BTPROTO_RFCOMM); 1472 TEXT(BTPROTO_SCO); 1473 } 1474 break; 1475 #endif 1476 } 1477 } 1478 1479 if (text != NULL) 1480 put_field(proc, name, text); 1481 else 1482 put_value(proc, name, "%d", protocol); 1483 } 1484 1485 static int 1486 vfs_socket_out(struct trace_proc * proc, const message * m_out) 1487 { 1488 1489 put_socket_family(proc, "domain", m_out->m_lc_vfs_socket.domain); 1490 put_socket_type(proc, "type", m_out->m_lc_vfs_socket.type); 1491 put_socket_protocol(proc, "protocol", m_out->m_lc_vfs_socket.domain, 1492 m_out->m_lc_vfs_socket.type & ~SOCK_FLAGS_MASK, 1493 m_out->m_lc_vfs_socket.protocol); 1494 1495 return CT_DONE; 1496 } 1497 1498 static int 1499 vfs_socketpair_out(struct trace_proc * proc, const message * m_out) 1500 { 1501 1502 put_socket_family(proc, "domain", m_out->m_lc_vfs_socket.domain); 1503 put_socket_type(proc, "type", m_out->m_lc_vfs_socket.type); 1504 put_socket_protocol(proc, "protocol", m_out->m_lc_vfs_socket.domain, 1505 m_out->m_lc_vfs_socket.type & ~SOCK_FLAGS_MASK, 1506 m_out->m_lc_vfs_socket.protocol); 1507 1508 return CT_NOTDONE; 1509 } 1510 1511 static void 1512 vfs_socketpair_in(struct trace_proc * proc, const message * m_out, 1513 const message * m_in, int failed) 1514 { 1515 1516 if (!failed) { 1517 put_open(proc, "fd", PF_NONAME, "[", ", "); 1518 put_fd(proc, "fd0", m_in->m_vfs_lc_fdpair.fd0); 1519 put_fd(proc, "fd1", m_in->m_vfs_lc_fdpair.fd1); 1520 put_close(proc, "]"); 1521 } else 1522 put_field(proc, "fd", "&.."); 1523 put_equals(proc); 1524 put_result(proc); 1525 } 1526 1527 void 1528 put_in_addr(struct trace_proc * proc, const char * name, struct in_addr in) 1529 { 1530 1531 if (!valuesonly) { 1532 /* Is this an acceptable encapsulation? */ 1533 put_value(proc, name, "[%s]", inet_ntoa(in)); 1534 } else 1535 put_value(proc, name, "0x%08x", ntohl(in.s_addr)); 1536 } 1537 1538 static void 1539 put_in6_addr(struct trace_proc * proc, const char * name, struct in6_addr * in) 1540 { 1541 char buf[INET6_ADDRSTRLEN]; 1542 const char *ptr; 1543 unsigned int i, n; 1544 1545 if (!valuesonly && 1546 (ptr = inet_ntop(AF_INET6, in, buf, sizeof(buf))) != NULL) { 1547 put_value(proc, name, "[%s]", ptr); 1548 } else { 1549 for (i = n = 0; i < 16; i++) 1550 n += snprintf(buf + n, sizeof(buf) - n, "%02x", 1551 ((unsigned char *)in)[i]); 1552 put_value(proc, name, "0x%s", buf); 1553 } 1554 } 1555 1556 static void 1557 put_struct_sockaddr(struct trace_proc * proc, const char * name, int flags, 1558 vir_bytes addr, socklen_t addr_len) 1559 { 1560 char buf[UCHAR_MAX + 1]; 1561 uint8_t len; 1562 sa_family_t family; 1563 struct sockaddr sa; 1564 struct sockaddr_in sin; 1565 struct sockaddr_in6 sin6; 1566 int all, off, left; 1567 1568 /* 1569 * For UNIX domain sockets, make sure there's always room to add a 1570 * trailing NULL byte, because UDS paths are not necessarily null 1571 * terminated. 1572 */ 1573 if (addr_len < offsetof(struct sockaddr, sa_data) || 1574 addr_len >= sizeof(buf)) { 1575 put_ptr(proc, name, addr); 1576 1577 return; 1578 } 1579 1580 if (!put_open_struct(proc, name, flags, addr, buf, addr_len)) 1581 return; 1582 1583 memcpy(&sa, buf, sizeof(sa)); 1584 len = sa.sa_len; 1585 family = sa.sa_family; 1586 all = (verbose > 1); 1587 1588 switch (family) { 1589 case AF_LOCAL: 1590 if (verbose > 1) 1591 put_value(proc, "sun_len", "%u", len); 1592 if (verbose > 0) 1593 put_socket_family(proc, "sun_family", family); 1594 off = (int)offsetof(struct sockaddr_un, sun_path); 1595 left = addr_len - off; 1596 if (left > 0) { 1597 buf[addr_len] = 0; /* force null termination */ 1598 put_buf(proc, "sun_path", PF_LOCADDR | PF_PATH, 1599 (vir_bytes)&buf[off], 1600 left + 1 /* include null byte */); 1601 } 1602 break; 1603 case AF_INET: 1604 if (verbose > 1) 1605 put_value(proc, "sin_len", "%u", len); 1606 if (verbose > 0) 1607 put_socket_family(proc, "sin_family", family); 1608 if (addr_len == sizeof(sin)) { 1609 memcpy(&sin, buf, sizeof(sin)); 1610 put_value(proc, "sin_port", "%u", ntohs(sin.sin_port)); 1611 put_in_addr(proc, "sin_addr", sin.sin_addr); 1612 } else 1613 all = FALSE; 1614 break; 1615 case AF_INET6: 1616 if (verbose > 1) 1617 put_value(proc, "sin6_len", "%u", len); 1618 if (verbose > 0) 1619 put_socket_family(proc, "sin6_family", family); 1620 if (addr_len == sizeof(sin6)) { 1621 memcpy(&sin6, buf, sizeof(sin6)); 1622 put_value(proc, "sin6_port", "%u", 1623 ntohs(sin6.sin6_port)); 1624 if (verbose > 1) 1625 put_value(proc, "sin6_flowinfo", "%"PRIu32, 1626 sin6.sin6_flowinfo); 1627 put_in6_addr(proc, "sin6_addr", &sin6.sin6_addr); 1628 if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) || 1629 IN6_IS_ADDR_MC_NODELOCAL(&sin6.sin6_addr) || 1630 IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr) || 1631 verbose > 0) 1632 put_value(proc, "sin6_scope_id", "%"PRIu32, 1633 sin6.sin6_scope_id); 1634 } else 1635 all = FALSE; 1636 break; 1637 /* TODO: support for other address families */ 1638 default: 1639 if (verbose > 1) 1640 put_value(proc, "sa_len", "%u", len); 1641 put_socket_family(proc, "sa_family", family); 1642 all = (verbose > 1 && family == AF_UNSPEC); 1643 } 1644 1645 put_close_struct(proc, all); 1646 } 1647 1648 /* This function is shared between bind and connect. */ 1649 static int 1650 vfs_bind_out(struct trace_proc * proc, const message * m_out) 1651 { 1652 1653 put_fd(proc, "fd", m_out->m_lc_vfs_sockaddr.fd); 1654 put_struct_sockaddr(proc, "addr", 0, m_out->m_lc_vfs_sockaddr.addr, 1655 m_out->m_lc_vfs_sockaddr.addr_len); 1656 put_value(proc, "addr_len", "%u", m_out->m_lc_vfs_sockaddr.addr_len); 1657 1658 return CT_DONE; 1659 } 1660 1661 static int 1662 vfs_listen_out(struct trace_proc * proc, const message * m_out) 1663 { 1664 1665 put_fd(proc, "fd", m_out->m_lc_vfs_listen.fd); 1666 put_value(proc, "backlog", "%d", m_out->m_lc_vfs_listen.backlog); 1667 1668 return CT_DONE; 1669 } 1670 1671 static int 1672 vfs_accept_out(struct trace_proc * proc, const message * m_out) 1673 { 1674 1675 put_fd(proc, "fd", m_out->m_lc_vfs_sockaddr.fd); 1676 1677 return CT_NOTDONE; 1678 } 1679 1680 static void 1681 vfs_accept_in(struct trace_proc * proc, const message * m_out, 1682 const message * m_in, int failed) 1683 { 1684 1685 put_struct_sockaddr(proc, "addr", failed, 1686 m_out->m_lc_vfs_sockaddr.addr, m_in->m_vfs_lc_socklen.len); 1687 /* 1688 * We print the resulting address length rather than the given buffer 1689 * size here, as we do in recvfrom, getsockname, getpeername, and (less 1690 * explicitly) recvmsg. We could also print both, by adding the 1691 * resulting length after the call result. 1692 */ 1693 if (m_out->m_lc_vfs_sockaddr.addr == 0) 1694 put_field(proc, "addr_len", "NULL"); 1695 else if (!failed) 1696 put_value(proc, "addr_len", "{%u}", 1697 m_in->m_vfs_lc_socklen.len); 1698 else 1699 put_field(proc, "addr_len", "&.."); 1700 1701 put_equals(proc); 1702 put_result(proc); 1703 } 1704 1705 static const struct flags msg_flags[] = { 1706 FLAG(MSG_OOB), 1707 FLAG(MSG_PEEK), 1708 FLAG(MSG_DONTROUTE), 1709 FLAG(MSG_EOR), 1710 FLAG(MSG_TRUNC), 1711 FLAG(MSG_CTRUNC), 1712 FLAG(MSG_WAITALL), 1713 FLAG(MSG_DONTWAIT), 1714 FLAG(MSG_BCAST), 1715 FLAG(MSG_MCAST), 1716 #ifdef MSG_NOSIGNAL 1717 FLAG(MSG_NOSIGNAL), 1718 #endif 1719 FLAG(MSG_CMSG_CLOEXEC), 1720 FLAG(MSG_NBIO), 1721 FLAG(MSG_WAITFORONE), 1722 }; 1723 1724 static int 1725 vfs_sendto_out(struct trace_proc * proc, const message * m_out) 1726 { 1727 1728 put_fd(proc, "fd", m_out->m_lc_vfs_sendrecv.fd); 1729 put_buf(proc, "buf", 0, m_out->m_lc_vfs_sendrecv.buf, 1730 m_out->m_lc_vfs_readwrite.len); 1731 put_value(proc, "len", "%zu", m_out->m_lc_vfs_sendrecv.len); 1732 put_flags(proc, "flags", msg_flags, COUNT(msg_flags), "0x%x", 1733 m_out->m_lc_vfs_sendrecv.flags); 1734 put_struct_sockaddr(proc, "addr", 0, m_out->m_lc_vfs_sendrecv.addr, 1735 m_out->m_lc_vfs_sendrecv.addr_len); 1736 put_value(proc, "addr_len", "%u", m_out->m_lc_vfs_sendrecv.addr_len); 1737 1738 return CT_DONE; 1739 } 1740 1741 static void 1742 put_struct_iovec(struct trace_proc * proc, const char * name, int flags, 1743 vir_bytes addr, int len, ssize_t bmax) 1744 { 1745 struct iovec iov; 1746 size_t bytes; 1747 int i, imax; 1748 1749 /* 1750 * For simplicity and clarity reasons, we currently print the I/O 1751 * vector as an array of data elements rather than an array of 1752 * structures. We also copy in each element separately, because as of 1753 * writing there is no system support for more than one element anyway. 1754 * All of this may be changed later. 1755 */ 1756 if ((flags & PF_FAILED) || valuesonly > 1 || addr == 0 || len < 0) { 1757 put_ptr(proc, name, addr); 1758 1759 return; 1760 } 1761 1762 if (len == 0 || bmax == 0) { 1763 put_field(proc, name, "[]"); 1764 1765 return; 1766 } 1767 1768 /* As per logic below, 'imax' must be set to a nonzero value here. */ 1769 if (verbose == 0) 1770 imax = 4; 1771 else if (verbose == 1) 1772 imax = 16; 1773 else 1774 imax = INT_MAX; 1775 1776 for (i = 0; i < len && bmax > 0; i++) { 1777 if (mem_get_data(proc->pid, addr, &iov, sizeof(iov)) < 0) { 1778 if (i == 0) { 1779 put_ptr(proc, name, addr); 1780 1781 return; 1782 } 1783 1784 len = imax = 0; /* make put_tail() print an error */ 1785 break; 1786 } 1787 1788 if (i == 0) 1789 put_open(proc, name, 0, "[", ", "); 1790 1791 bytes = MIN(iov.iov_len, (size_t)bmax); 1792 1793 if (len < imax) 1794 put_buf(proc, NULL, 0, (vir_bytes)iov.iov_base, bytes); 1795 1796 addr += sizeof(struct iovec); 1797 bmax -= bytes; 1798 } 1799 1800 if (imax == 0 || imax < len) 1801 put_tail(proc, len, imax); 1802 put_close(proc, "]"); 1803 } 1804 1805 static void 1806 put_struct_sockcred(struct trace_proc * proc, const char * name, int flags, 1807 vir_bytes addr, size_t left) 1808 { 1809 struct sockcred sc; 1810 1811 if (!put_open_struct(proc, name, flags, addr, &sc, sizeof(sc))) 1812 return; 1813 1814 put_value(proc, "sc_uid", "%u", sc.sc_uid); 1815 if (verbose > 0) 1816 put_value(proc, "sc_euid", "%u", sc.sc_euid); 1817 put_value(proc, "sc_gid", "%u", sc.sc_gid); 1818 if (verbose > 0) { 1819 put_value(proc, "sc_egid", "%u", sc.sc_egid); 1820 if (verbose > 1) 1821 put_value(proc, "sc_ngroups", "%d", sc.sc_ngroups); 1822 if (left >= sizeof(sc.sc_groups[0]) * (sc.sc_ngroups - 1)) { 1823 put_groups(proc, "sc_groups", flags, 1824 addr + offsetof(struct sockcred, sc_groups), 1825 sc.sc_ngroups); 1826 } else 1827 put_field(proc, "sc_groups", ".."); 1828 } 1829 1830 put_close_struct(proc, verbose > 1); 1831 } 1832 1833 static void 1834 put_socket_level(struct trace_proc * proc, const char * name, int level) 1835 { 1836 1837 /* 1838 * Unfortunately, the level is a domain-specific protocol number. That 1839 * means that without knowing how the socket was created, we cannot 1840 * tell what it means. The only thing we can print is SOL_SOCKET, 1841 * which is the same across all domains. 1842 */ 1843 if (!valuesonly && level == SOL_SOCKET) 1844 put_field(proc, name, "SOL_SOCKET"); 1845 else 1846 put_value(proc, name, "%d", level); 1847 } 1848 1849 void 1850 put_cmsg_type(struct trace_proc * proc, const char * name, int type) 1851 { 1852 const char *text = NULL; 1853 1854 if (!valuesonly) { 1855 switch (type) { 1856 TEXT(SCM_RIGHTS); 1857 TEXT(SCM_CREDS); 1858 TEXT(SCM_TIMESTAMP); 1859 } 1860 } 1861 1862 if (text != NULL) 1863 put_field(proc, name, text); 1864 else 1865 put_value(proc, name, "%d", type); 1866 } 1867 1868 static void 1869 put_cmsg_rights(struct trace_proc * proc, const char * name, char * buf, 1870 size_t size, char * cptr, size_t chunk, vir_bytes addr, size_t len) 1871 { 1872 unsigned int i, nfds; 1873 int *ptr; 1874 1875 put_open(proc, name, PF_NONAME, "[", ", "); 1876 1877 /* 1878 * Since file descriptors are important, we print them all, regardless 1879 * of the current verbosity level. Start with the file descriptors 1880 * that are already copied into the local buffer. 1881 */ 1882 ptr = (int *)cptr; 1883 chunk = MIN(chunk, len); 1884 1885 nfds = chunk / sizeof(int); 1886 for (i = 0; i < nfds; i++) 1887 put_fd(proc, NULL, ptr[i]); 1888 1889 /* Then do the remaining file descriptors, in chunks. */ 1890 size -= size % sizeof(int); 1891 1892 for (len -= chunk; len >= sizeof(int); len -= chunk) { 1893 chunk = MIN(len, size); 1894 1895 if (mem_get_data(proc->pid, addr, buf, chunk) < 0) { 1896 put_field(proc, NULL, ".."); 1897 1898 break; 1899 } 1900 1901 ptr = (int *)buf; 1902 nfds = chunk / sizeof(int); 1903 for (i = 0; i < nfds; i++) 1904 put_fd(proc, NULL, ptr[i]); 1905 1906 addr += chunk; 1907 } 1908 1909 put_close(proc, "]"); 1910 } 1911 1912 static void 1913 put_cmsg(struct trace_proc * proc, const char * name, vir_bytes addr, 1914 size_t len) 1915 { 1916 struct cmsghdr cmsg; 1917 char buf[CMSG_SPACE(sizeof(struct sockcred))]; 1918 size_t off, chunk, datalen; 1919 1920 if (valuesonly > 1 || addr == 0 || len < CMSG_LEN(0)) { 1921 put_ptr(proc, name, addr); 1922 1923 return; 1924 } 1925 1926 for (off = 0; off < len; off += CMSG_SPACE(datalen)) { 1927 chunk = MIN(len - off, sizeof(buf)); 1928 1929 if (chunk < CMSG_LEN(0)) 1930 break; 1931 1932 if (mem_get_data(proc->pid, addr + off, buf, chunk) < 0) { 1933 if (off == 0) { 1934 put_ptr(proc, name, addr); 1935 1936 return; 1937 } 1938 break; 1939 } 1940 1941 if (off == 0) 1942 put_open(proc, name, 0, "[", ", "); 1943 1944 memcpy(&cmsg, buf, sizeof(cmsg)); 1945 1946 put_open(proc, NULL, 0, "{", ", "); 1947 if (verbose > 0) 1948 put_value(proc, "cmsg_len", "%u", cmsg.cmsg_len); 1949 put_socket_level(proc, "cmsg_level", cmsg.cmsg_level); 1950 if (cmsg.cmsg_level == SOL_SOCKET) 1951 put_cmsg_type(proc, "cmsg_type", cmsg.cmsg_type); 1952 else 1953 put_value(proc, "cmsg_type", "%d", cmsg.cmsg_type); 1954 1955 if (cmsg.cmsg_len < CMSG_LEN(0) || off + cmsg.cmsg_len > len) { 1956 put_tail(proc, 0, 0); 1957 put_close(proc, "}"); 1958 break; 1959 } 1960 1961 datalen = cmsg.cmsg_len - CMSG_LEN(0); 1962 1963 if (cmsg.cmsg_level == SOL_SOCKET && 1964 cmsg.cmsg_type == SCM_RIGHTS) { 1965 put_cmsg_rights(proc, "cmsg_data", buf, sizeof(buf), 1966 &buf[CMSG_LEN(0)], chunk - CMSG_LEN(0), 1967 addr + off + chunk, datalen); 1968 } else if (cmsg.cmsg_level == SOL_SOCKET && 1969 cmsg.cmsg_type == SCM_CREDS && 1970 datalen >= sizeof(struct sockcred) && 1971 chunk >= CMSG_LEN(datalen)) { 1972 put_struct_sockcred(proc, "cmsg_data", PF_LOCADDR, 1973 (vir_bytes)&buf[CMSG_LEN(0)], 1974 datalen - sizeof(struct sockcred)); 1975 } else if (datalen > 0) 1976 put_field(proc, "cmsg_data", ".."); 1977 1978 if (verbose == 0) 1979 put_field(proc, NULL, ".."); 1980 put_close(proc, "}"); 1981 } 1982 1983 if (off < len) 1984 put_field(proc, NULL, ".."); 1985 put_close(proc, "]"); 1986 } 1987 1988 static void 1989 put_struct_msghdr(struct trace_proc * proc, const char * name, int flags, 1990 vir_bytes addr, ssize_t max) 1991 { 1992 struct msghdr msg; 1993 int all; 1994 1995 if (!put_open_struct(proc, name, flags, addr, &msg, sizeof(msg))) 1996 return; 1997 1998 all = TRUE; 1999 2000 if (msg.msg_name != NULL || verbose > 1) { 2001 put_struct_sockaddr(proc, "msg_name", 0, 2002 (vir_bytes)msg.msg_name, msg.msg_namelen); 2003 if (verbose > 0) 2004 put_value(proc, "msg_namelen", "%u", msg.msg_namelen); 2005 else 2006 all = FALSE; 2007 } else 2008 all = FALSE; 2009 2010 put_struct_iovec(proc, "msg_iov", 0, (vir_bytes)msg.msg_iov, 2011 msg.msg_iovlen, max); 2012 if (verbose > 0) 2013 put_value(proc, "msg_iovlen", "%d", msg.msg_iovlen); 2014 else 2015 all = FALSE; 2016 2017 if (msg.msg_control != NULL || verbose > 1) { 2018 put_cmsg(proc, "msg_control", (vir_bytes)msg.msg_control, 2019 msg.msg_controllen); 2020 2021 if (verbose > 0) 2022 put_value(proc, "msg_controllen", "%u", 2023 msg.msg_controllen); 2024 else 2025 all = FALSE; 2026 } else 2027 all = FALSE; 2028 2029 /* When receiving, print the flags field as well. */ 2030 if (flags & PF_ALT) 2031 put_flags(proc, "msg_flags", msg_flags, COUNT(msg_flags), 2032 "0x%x", msg.msg_flags); 2033 2034 put_close_struct(proc, all); 2035 } 2036 2037 static int 2038 vfs_sendmsg_out(struct trace_proc * proc, const message * m_out) 2039 { 2040 2041 put_fd(proc, "fd", m_out->m_lc_vfs_sockmsg.fd); 2042 put_struct_msghdr(proc, "msg", 0, m_out->m_lc_vfs_sockmsg.msgbuf, 2043 SSIZE_MAX); 2044 put_flags(proc, "flags", msg_flags, COUNT(msg_flags), "0x%x", 2045 m_out->m_lc_vfs_sockmsg.flags); 2046 2047 return CT_DONE; 2048 } 2049 2050 static int 2051 vfs_recvfrom_out(struct trace_proc * proc, const message * m_out) 2052 { 2053 2054 put_fd(proc, "fd", m_out->m_lc_vfs_sendrecv.fd); 2055 2056 return CT_NOTDONE; 2057 } 2058 2059 static void 2060 vfs_recvfrom_in(struct trace_proc * proc, const message * m_out, 2061 const message * m_in, int failed) 2062 { 2063 2064 put_buf(proc, "buf", failed, m_out->m_lc_vfs_sendrecv.buf, 2065 m_in->m_type); 2066 put_value(proc, "len", "%zu", m_out->m_lc_vfs_sendrecv.len); 2067 put_flags(proc, "flags", msg_flags, COUNT(msg_flags), "0x%x", 2068 m_out->m_lc_vfs_sendrecv.flags); 2069 put_struct_sockaddr(proc, "addr", failed, 2070 m_out->m_lc_vfs_sendrecv.addr, m_in->m_vfs_lc_socklen.len); 2071 if (m_out->m_lc_vfs_sendrecv.addr == 0) 2072 put_field(proc, "addr_len", "NULL"); 2073 else if (!failed) 2074 put_value(proc, "addr_len", "{%u}", 2075 m_in->m_vfs_lc_socklen.len); 2076 else 2077 put_field(proc, "addr_len", "&.."); 2078 2079 put_equals(proc); 2080 put_result(proc); 2081 } 2082 2083 static int 2084 vfs_recvmsg_out(struct trace_proc * proc, const message * m_out) 2085 { 2086 2087 put_fd(proc, "fd", m_out->m_lc_vfs_sockmsg.fd); 2088 2089 return CT_NOTDONE; 2090 } 2091 2092 static void 2093 vfs_recvmsg_in(struct trace_proc * proc, const message * m_out, 2094 const message * m_in, int failed) 2095 { 2096 2097 /* 2098 * We choose to print only the resulting structure in this case. Doing 2099 * so is easier and less messy than printing both the original and the 2100 * result for the fields that are updated by the system (msg_namelen 2101 * and msg_controllen); also, this approach is stateless. Admittedly 2102 * it is not entirely consistent with many other parts of the trace 2103 * output, though. 2104 */ 2105 put_struct_msghdr(proc, "msg", PF_ALT | failed, 2106 m_out->m_lc_vfs_sockmsg.msgbuf, m_in->m_type); 2107 put_flags(proc, "flags", msg_flags, COUNT(msg_flags), "0x%x", 2108 m_out->m_lc_vfs_sockmsg.flags); 2109 2110 put_equals(proc); 2111 put_result(proc); 2112 } 2113 2114 static void 2115 put_sockopt_name(struct trace_proc * proc, const char * name, int level, 2116 int optname) 2117 { 2118 const char *text = NULL; 2119 2120 /* 2121 * The only level for which we can know names is SOL_SOCKET. See also 2122 * put_socket_level(). Of course we could guess, but then we need a 2123 * proper guessing system, which should probably also take into account 2124 * the [gs]etsockopt option length. TODO. 2125 */ 2126 if (!valuesonly && level == SOL_SOCKET) { 2127 switch (optname) { 2128 TEXT(SO_DEBUG); 2129 TEXT(SO_ACCEPTCONN); 2130 TEXT(SO_REUSEADDR); 2131 TEXT(SO_KEEPALIVE); 2132 TEXT(SO_DONTROUTE); 2133 TEXT(SO_BROADCAST); 2134 TEXT(SO_USELOOPBACK); 2135 TEXT(SO_LINGER); 2136 TEXT(SO_OOBINLINE); 2137 TEXT(SO_REUSEPORT); 2138 TEXT(SO_NOSIGPIPE); 2139 TEXT(SO_TIMESTAMP); 2140 TEXT(SO_SNDBUF); 2141 TEXT(SO_RCVBUF); 2142 TEXT(SO_SNDLOWAT); 2143 TEXT(SO_RCVLOWAT); 2144 TEXT(SO_ERROR); 2145 TEXT(SO_TYPE); 2146 TEXT(SO_OVERFLOWED); 2147 TEXT(SO_NOHEADER); 2148 TEXT(SO_SNDTIMEO); 2149 TEXT(SO_RCVTIMEO); 2150 } 2151 } 2152 2153 if (text != NULL) 2154 put_field(proc, name, text); 2155 else 2156 put_value(proc, name, "0x%x", optname); 2157 } 2158 2159 static void 2160 put_sockopt_data(struct trace_proc * proc, const char * name, int flags, 2161 int level, int optname, vir_bytes addr, socklen_t len) 2162 { 2163 const char *text; 2164 int i; 2165 struct linger l; 2166 struct timeval tv; 2167 void *ptr; 2168 size_t size; 2169 2170 /* See above regarding ambiguity for levels other than SOL_SOCKET. */ 2171 if ((flags & PF_FAILED) || valuesonly > 1 || len == 0 || 2172 level != SOL_SOCKET) { 2173 put_ptr(proc, name, addr); 2174 2175 return; 2176 } 2177 2178 /* Determine how much data to get, and where to put it. */ 2179 switch (optname) { 2180 case SO_DEBUG: 2181 case SO_ACCEPTCONN: 2182 case SO_REUSEADDR: 2183 case SO_KEEPALIVE: 2184 case SO_DONTROUTE: 2185 case SO_BROADCAST: 2186 case SO_USELOOPBACK: 2187 case SO_OOBINLINE: 2188 case SO_REUSEPORT: 2189 case SO_NOSIGPIPE: 2190 case SO_TIMESTAMP: 2191 case SO_SNDBUF: 2192 case SO_RCVBUF: 2193 case SO_SNDLOWAT: 2194 case SO_RCVLOWAT: 2195 case SO_ERROR: 2196 case SO_TYPE: 2197 case SO_OVERFLOWED: 2198 case SO_NOHEADER: 2199 ptr = &i; 2200 size = sizeof(i); 2201 break; 2202 case SO_LINGER: 2203 ptr = &l; 2204 size = sizeof(l); 2205 break; 2206 case SO_SNDTIMEO: 2207 case SO_RCVTIMEO: 2208 ptr = &tv; 2209 size = sizeof(tv); 2210 break; 2211 default: 2212 put_ptr(proc, name, addr); 2213 return; 2214 } 2215 2216 /* Get the data. Do not bother with truncated values. */ 2217 if (len < size || mem_get_data(proc->pid, addr, ptr, size) < 0) { 2218 put_ptr(proc, name, addr); 2219 2220 return; 2221 } 2222 2223 /* Print the data according to the option name. */ 2224 switch (optname) { 2225 case SO_LINGER: 2226 /* This isn't going to appear anywhere else; do it inline. */ 2227 put_open(proc, name, 0, "{", ", "); 2228 put_value(proc, "l_onoff", "%d", l.l_onoff); 2229 put_value(proc, "l_linger", "%d", l.l_linger); 2230 put_close(proc, "}"); 2231 break; 2232 case SO_ERROR: 2233 put_open(proc, name, 0, "{", ", "); 2234 if (!valuesonly && (text = get_error_name(i)) != NULL) 2235 put_field(proc, NULL, text); 2236 else 2237 put_value(proc, NULL, "%d", i); 2238 put_close(proc, "}"); 2239 break; 2240 case SO_TYPE: 2241 put_open(proc, name, 0, "{", ", "); 2242 put_socket_type(proc, NULL, i); 2243 put_close(proc, "}"); 2244 break; 2245 case SO_SNDTIMEO: 2246 case SO_RCVTIMEO: 2247 put_struct_timeval(proc, name, PF_LOCADDR, (vir_bytes)&tv); 2248 break; 2249 default: 2250 /* All other options are integer values. */ 2251 put_value(proc, name, "{%d}", i); 2252 } 2253 } 2254 2255 static int 2256 vfs_setsockopt_out(struct trace_proc * proc, const message * m_out) 2257 { 2258 int level, name; 2259 2260 level = m_out->m_lc_vfs_sockopt.level; 2261 name = m_out->m_lc_vfs_sockopt.name; 2262 2263 put_fd(proc, "fd", m_out->m_lc_vfs_sockopt.fd); 2264 put_socket_level(proc, "level", level); 2265 put_sockopt_name(proc, "name", level, name); 2266 put_sockopt_data(proc, "buf", 0, level, name, 2267 m_out->m_lc_vfs_sockopt.buf, m_out->m_lc_vfs_sockopt.len); 2268 put_value(proc, "len", "%u", m_out->m_lc_vfs_sockopt.len); 2269 2270 return CT_DONE; 2271 } 2272 2273 static int 2274 vfs_getsockopt_out(struct trace_proc * proc, const message * m_out) 2275 { 2276 int level; 2277 2278 level = m_out->m_lc_vfs_sockopt.level; 2279 2280 put_fd(proc, "fd", m_out->m_lc_vfs_sockopt.fd); 2281 put_socket_level(proc, "level", level); 2282 put_sockopt_name(proc, "name", level, m_out->m_lc_vfs_sockopt.name); 2283 2284 return CT_NOTDONE; 2285 } 2286 2287 static void 2288 vfs_getsockopt_in(struct trace_proc * proc, const message * m_out, 2289 const message * m_in, int failed) 2290 { 2291 2292 put_sockopt_data(proc, "buf", failed, m_out->m_lc_vfs_sockopt.level, 2293 m_out->m_lc_vfs_sockopt.name, m_out->m_lc_vfs_sockopt.buf, 2294 m_in->m_vfs_lc_socklen.len); 2295 /* 2296 * For the length, we follow the same scheme as for addr_len pointers 2297 * in accept() et al., in that we print the result only. We need not 2298 * take into account that the given buffer is NULL as it must not be. 2299 */ 2300 if (!failed) 2301 put_value(proc, "len", "%u", m_out->m_lc_vfs_sockopt.len); 2302 else 2303 put_field(proc, "len", "&.."); 2304 2305 put_equals(proc); 2306 put_result(proc); 2307 } 2308 2309 /* This function is shared between getsockname and getpeername. */ 2310 static int 2311 vfs_getsockname_out(struct trace_proc * proc, const message * m_out) 2312 { 2313 2314 put_fd(proc, "fd", m_out->m_lc_vfs_sockaddr.fd); 2315 2316 return CT_NOTDONE; 2317 } 2318 2319 static void 2320 vfs_getsockname_in(struct trace_proc * proc, const message * m_out, 2321 const message * m_in, int failed) 2322 { 2323 2324 put_struct_sockaddr(proc, "addr", failed, 2325 m_out->m_lc_vfs_sockaddr.addr, m_in->m_vfs_lc_socklen.len); 2326 if (m_out->m_lc_vfs_sockaddr.addr == 0) 2327 put_field(proc, "addr_len", "NULL"); 2328 else if (!failed) 2329 put_value(proc, "addr_len", "{%u}", 2330 m_in->m_vfs_lc_socklen.len); 2331 else 2332 put_field(proc, "addr_len", "&.."); 2333 2334 put_equals(proc); 2335 put_result(proc); 2336 } 2337 2338 void 2339 put_shutdown_how(struct trace_proc * proc, const char * name, int how) 2340 { 2341 const char *text = NULL; 2342 2343 if (!valuesonly) { 2344 switch (how) { 2345 TEXT(SHUT_RD); 2346 TEXT(SHUT_WR); 2347 TEXT(SHUT_RDWR); 2348 } 2349 } 2350 2351 if (text != NULL) 2352 put_field(proc, name, text); 2353 else 2354 put_value(proc, name, "%d", how); 2355 } 2356 2357 static int 2358 vfs_shutdown_out(struct trace_proc * proc, const message * m_out) 2359 { 2360 2361 put_fd(proc, "fd", m_out->m_lc_vfs_shutdown.fd); 2362 put_shutdown_how(proc, "how", m_out->m_lc_vfs_shutdown.how); 2363 2364 return CT_DONE; 2365 } 2366 2367 #define VFS_CALL(c) [((VFS_ ## c) - VFS_BASE)] 2368 2369 static const struct call_handler vfs_map[] = { 2370 VFS_CALL(READ) = HANDLER("read", vfs_read_out, vfs_read_in), 2371 VFS_CALL(WRITE) = HANDLER("write", vfs_write_out, default_in), 2372 VFS_CALL(LSEEK) = HANDLER("lseek", vfs_lseek_out, vfs_lseek_in), 2373 VFS_CALL(OPEN) = HANDLER("open", vfs_open_out, vfs_open_in), 2374 VFS_CALL(CREAT) = HANDLER("open", vfs_creat_out, vfs_open_in), 2375 VFS_CALL(CLOSE) = HANDLER("close", vfs_close_out, default_in), 2376 VFS_CALL(LINK) = HANDLER("link", vfs_link_out, default_in), 2377 VFS_CALL(UNLINK) = HANDLER("unlink", vfs_path_out, default_in), 2378 VFS_CALL(CHDIR) = HANDLER("chdir", vfs_path_out, default_in), 2379 VFS_CALL(MKDIR) = HANDLER("mkdir", vfs_path_mode_out, default_in), 2380 VFS_CALL(MKNOD) = HANDLER("mknod", vfs_mknod_out, default_in), 2381 VFS_CALL(CHMOD) = HANDLER("chmod", vfs_path_mode_out, default_in), 2382 VFS_CALL(CHOWN) = HANDLER("chown", vfs_chown_out, default_in), 2383 VFS_CALL(MOUNT) = HANDLER("mount", vfs_mount_out, default_in), 2384 VFS_CALL(UMOUNT) = HANDLER("umount", vfs_umount_out, vfs_umount_in), 2385 VFS_CALL(ACCESS) = HANDLER("access", vfs_access_out, default_in), 2386 VFS_CALL(SYNC) = HANDLER("sync", default_out, default_in), 2387 VFS_CALL(RENAME) = HANDLER("rename", vfs_link_out, default_in), 2388 VFS_CALL(RMDIR) = HANDLER("rmdir", vfs_path_out, default_in), 2389 VFS_CALL(SYMLINK) = HANDLER("symlink", vfs_link_out, default_in), 2390 VFS_CALL(READLINK) = HANDLER("readlink", vfs_readlink_out, 2391 vfs_readlink_in), 2392 VFS_CALL(STAT) = HANDLER("stat", vfs_stat_out, vfs_stat_in), 2393 VFS_CALL(FSTAT) = HANDLER("fstat", vfs_fstat_out, vfs_fstat_in), 2394 VFS_CALL(LSTAT) = HANDLER("lstat", vfs_stat_out, vfs_stat_in), 2395 VFS_CALL(IOCTL) = HANDLER("ioctl", vfs_ioctl_out, vfs_ioctl_in), 2396 VFS_CALL(FCNTL) = HANDLER("fcntl", vfs_fcntl_out, vfs_fcntl_in), 2397 VFS_CALL(PIPE2) = HANDLER("pipe2", vfs_pipe2_out, vfs_pipe2_in), 2398 VFS_CALL(UMASK) = HANDLER("umask", vfs_umask_out, vfs_umask_in), 2399 VFS_CALL(CHROOT) = HANDLER("chroot", vfs_path_out, default_in), 2400 VFS_CALL(GETDENTS) = HANDLER("getdents", vfs_getdents_out, 2401 vfs_getdents_in), 2402 VFS_CALL(SELECT) = HANDLER("select", vfs_select_out, vfs_select_in), 2403 VFS_CALL(FCHDIR) = HANDLER("fchdir", vfs_fchdir_out, default_in), 2404 VFS_CALL(FSYNC) = HANDLER("fsync", vfs_fsync_out, default_in), 2405 VFS_CALL(TRUNCATE) = HANDLER("truncate", vfs_truncate_out, default_in), 2406 VFS_CALL(FTRUNCATE) = HANDLER("ftruncate", vfs_ftruncate_out, 2407 default_in), 2408 VFS_CALL(FCHMOD) = HANDLER("fchmod", vfs_fchmod_out, default_in), 2409 VFS_CALL(FCHOWN) = HANDLER("fchown", vfs_fchown_out, default_in), 2410 VFS_CALL(UTIMENS) = HANDLER_NAME(vfs_utimens_name, vfs_utimens_out, 2411 default_in), 2412 VFS_CALL(GETVFSSTAT) = HANDLER("getvfsstat", vfs_getvfsstat_out, 2413 vfs_getvfsstat_in), 2414 VFS_CALL(STATVFS1) = HANDLER("statvfs1", vfs_statvfs1_out, 2415 vfs_statvfs1_in), 2416 VFS_CALL(FSTATVFS1) = HANDLER("fstatvfs1", vfs_fstatvfs1_out, 2417 vfs_statvfs1_in), 2418 VFS_CALL(SVRCTL) = HANDLER("vfs_svrctl", vfs_svrctl_out, 2419 vfs_svrctl_in), 2420 VFS_CALL(GCOV_FLUSH) = HANDLER("gcov_flush", vfs_gcov_flush_out, 2421 default_in), 2422 VFS_CALL(SOCKET) = HANDLER("socket", vfs_socket_out, default_in), 2423 VFS_CALL(SOCKETPAIR) = HANDLER("socketpair", vfs_socketpair_out, 2424 vfs_socketpair_in), 2425 VFS_CALL(BIND) = HANDLER("bind", vfs_bind_out, default_in), 2426 VFS_CALL(CONNECT) = HANDLER("connect", vfs_bind_out, default_in), 2427 VFS_CALL(LISTEN) = HANDLER("listen", vfs_listen_out, default_in), 2428 VFS_CALL(ACCEPT) = HANDLER("accept", vfs_accept_out, vfs_accept_in), 2429 VFS_CALL(SENDTO) = HANDLER("sendto", vfs_sendto_out, default_in), 2430 VFS_CALL(SENDMSG) = HANDLER("sendmsg", vfs_sendmsg_out, default_in), 2431 VFS_CALL(RECVFROM) = HANDLER("recvfrom", vfs_recvfrom_out, 2432 vfs_recvfrom_in), 2433 VFS_CALL(RECVMSG) = HANDLER("recvmsg", vfs_recvmsg_out, 2434 vfs_recvmsg_in), 2435 VFS_CALL(SETSOCKOPT) = HANDLER("setsockopt", vfs_setsockopt_out, 2436 default_in), 2437 VFS_CALL(GETSOCKOPT) = HANDLER("getsockopt", vfs_getsockopt_out, 2438 vfs_getsockopt_in), 2439 VFS_CALL(GETSOCKNAME) = HANDLER("getsockname", vfs_getsockname_out, 2440 vfs_getsockname_in), 2441 VFS_CALL(GETPEERNAME) = HANDLER("getpeername", vfs_getsockname_out, 2442 vfs_getsockname_in), 2443 VFS_CALL(SHUTDOWN) = HANDLER("shutdown", vfs_shutdown_out, default_in), 2444 }; 2445 2446 const struct calls vfs_calls = { 2447 .endpt = VFS_PROC_NR, 2448 .base = VFS_BASE, 2449 .map = vfs_map, 2450 .count = COUNT(vfs_map) 2451 }; 2452