1 /* $OpenBSD: ktrstruct.c,v 1.24 2017/12/12 01:12:34 deraadt Exp $ */ 2 3 /*- 4 * Copyright (c) 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/types.h> 33 #include <sys/resource.h> 34 #include <sys/socket.h> 35 #include <sys/select.h> 36 #include <sys/stat.h> 37 #include <sys/time.h> 38 #include <sys/event.h> 39 #include <sys/un.h> 40 #include <ufs/ufs/quota.h> 41 #include <netinet/in.h> 42 #include <arpa/inet.h> 43 44 #include <ctype.h> 45 #include <err.h> 46 #include <limits.h> 47 #include <netdb.h> 48 #include <poll.h> 49 #include <signal.h> 50 #include <stddef.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <stdint.h> 54 #include <string.h> 55 #include <grp.h> 56 #include <pwd.h> 57 #include <unistd.h> 58 #include <vis.h> 59 60 #include "kdump.h" 61 #include "kdump_subr.h" 62 63 #define TIME_FORMAT "%b %e %T %Y" 64 65 static void 66 ktrsockaddr(struct sockaddr *sa) 67 { 68 /* 69 * TODO: Support additional address families 70 * #include <netmpls/mpls.h> 71 * struct sockaddr_mpls *mpls; 72 */ 73 74 /* 75 * note: ktrstruct() has already verified that sa points to a 76 * buffer at least sizeof(struct sockaddr) bytes long and exactly 77 * sa->sa_len bytes long. 78 */ 79 printf("struct sockaddr { "); 80 sockfamilyname(sa->sa_family); 81 printf(", "); 82 83 #define check_sockaddr_len(n) \ 84 if (sa_##n->s##n##_len < sizeof(struct sockaddr_##n)) { \ 85 printf("invalid"); \ 86 break; \ 87 } 88 89 switch(sa->sa_family) { 90 case AF_INET: { 91 struct sockaddr_in *sa_in; 92 char addr[64]; 93 94 sa_in = (struct sockaddr_in *)sa; 95 check_sockaddr_len(in); 96 inet_ntop(AF_INET, &sa_in->sin_addr, addr, sizeof addr); 97 printf("%s:%u", addr, ntohs(sa_in->sin_port)); 98 break; 99 } 100 case AF_INET6: { 101 struct sockaddr_in6 *sa_in6; 102 char addr[64]; 103 104 sa_in6 = (struct sockaddr_in6 *)sa; 105 check_sockaddr_len(in6); 106 inet_ntop(AF_INET6, &sa_in6->sin6_addr, addr, sizeof addr); 107 printf("[%s]:%u", addr, htons(sa_in6->sin6_port)); 108 break; 109 } 110 case AF_UNIX: { 111 struct sockaddr_un *sa_un; 112 char path[4 * sizeof(sa_un->sun_path) + 1]; 113 size_t len; 114 115 sa_un = (struct sockaddr_un *)sa; 116 len = sa_un->sun_len; 117 if (len <= offsetof(struct sockaddr_un, sun_path)) { 118 printf("invalid"); 119 break; 120 } 121 len -= offsetof(struct sockaddr_un, sun_path); 122 if (len > sizeof(sa_un->sun_path)) { 123 printf("too long"); 124 break; 125 } 126 /* format, stopping at first NUL */ 127 len = strnlen(sa_un->sun_path, len); 128 strvisx(path, sa_un->sun_path, len, 129 VIS_CSTYLE | VIS_DQ | VIS_TAB | VIS_NL); 130 printf("\"%s\"", path); 131 break; 132 } 133 default: 134 printf("unknown address family"); 135 } 136 printf(" }\n"); 137 } 138 139 static void 140 print_time(time_t t, int relative, int have_subsec) 141 { 142 char timestr[PATH_MAX + 4]; 143 struct tm *tm; 144 145 if (t < 0 && have_subsec) { 146 /* negative times with non-zero subsecs require care */ 147 printf("-%jd", -(intmax_t)(t + 1)); 148 } else 149 printf("%jd", (intmax_t)t); 150 151 /* 1970s times are probably relative */ 152 if (!relative && t > (10 * 365 * 24 * 3600)) { 153 tm = localtime(&t); 154 if (tm != NULL) { 155 (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, 156 tm); 157 printf("<\"%s\">", timestr); 158 } 159 } 160 } 161 162 static void 163 print_timespec(const struct timespec *tsp, int relative) 164 { 165 if (tsp->tv_nsec == UTIME_NOW) 166 printf("UTIME_NOW"); 167 else if (tsp->tv_nsec == UTIME_OMIT) 168 printf("UTIME_OMIT"); 169 else { 170 print_time(tsp->tv_sec, relative, tsp->tv_nsec); 171 if (tsp->tv_nsec != 0) 172 printf(".%09ld", tsp->tv_sec >= 0 ? tsp->tv_nsec : 173 1000000000 - tsp->tv_nsec); 174 } 175 } 176 177 void 178 uidname(int uid) 179 { 180 const char *name; 181 182 if (uid == -1) 183 printf("-1"); 184 else { 185 printf("%u<", (unsigned)uid); 186 if (uid > UID_MAX || (name = user_from_uid(uid, 1)) == NULL) 187 printf("unknown>"); 188 else 189 printf("\"%s\">", name); 190 } 191 } 192 193 void 194 gidname(int gid) 195 { 196 const char *name; 197 198 if (gid == -1) 199 printf("-1"); 200 else { 201 printf("%u<", (unsigned)gid); 202 if (gid > GID_MAX || (name = group_from_gid(gid, 1)) == NULL) 203 printf("unknown>"); 204 else 205 printf("\"%s\">", name); 206 } 207 } 208 209 static void 210 ktrstat(const struct stat *statp) 211 { 212 char mode[12]; 213 214 /* 215 * note: ktrstruct() has already verified that statp points to a 216 * buffer exactly sizeof(struct stat) bytes long. 217 */ 218 printf("struct stat { "); 219 strmode(statp->st_mode, mode); 220 printf("dev=%d, ino=%llu, mode=%s, nlink=%u, uid=", 221 statp->st_dev, (unsigned long long)statp->st_ino, 222 mode, statp->st_nlink); 223 uidname(statp->st_uid); 224 printf(", gid="); 225 gidname(statp->st_gid); 226 printf(", rdev=%d, ", statp->st_rdev); 227 printf("atime="); 228 print_timespec(&statp->st_atim, 0); 229 printf(", mtime="); 230 print_timespec(&statp->st_mtim, 0); 231 printf(", ctime="); 232 print_timespec(&statp->st_ctim, 0); 233 printf(", size=%lld, blocks=%lld, blksize=%d, flags=0x%x, gen=0x%x", 234 statp->st_size, statp->st_blocks, statp->st_blksize, 235 statp->st_flags, statp->st_gen); 236 printf(" }\n"); 237 } 238 239 static void 240 ktrtimespec(const struct timespec *tsp, int relative) 241 { 242 printf("struct timespec { "); 243 print_timespec(tsp, relative); 244 printf(" }\n"); 245 } 246 247 static void 248 print_timeval(const struct timeval *tvp, int relative) 249 { 250 print_time(tvp->tv_sec, relative, tvp->tv_usec); 251 if (tvp->tv_usec != 0) 252 printf(".%06ld", tvp->tv_sec >= 0 ? tvp->tv_usec : 253 1000000 - tvp->tv_usec); 254 } 255 256 static void 257 ktrtimeval(const struct timeval *tvp, int relative) 258 { 259 printf("struct timeval { "); 260 print_timeval(tvp, relative); 261 printf(" }\n"); 262 } 263 264 static void 265 ktrsigaction(const struct sigaction *sa) 266 { 267 /* 268 * note: ktrstruct() has already verified that sa points to a 269 * buffer exactly sizeof(struct sigaction) bytes long. 270 */ 271 /* 272 * Fuck! Comparison of function pointers on hppa assumes you can 273 * dereference them if they're plabels! Cast everything to void * 274 * to suppress that extra logic; sorry folks, the address we report 275 * here might not match what you see in your executable... 276 */ 277 printf("struct sigaction { "); 278 if ((void *)sa->sa_handler == (void *)SIG_DFL) 279 printf("handler=SIG_DFL"); 280 else if ((void *)sa->sa_handler == (void *)SIG_IGN) 281 printf("handler=SIG_IGN"); 282 else if (sa->sa_flags & SA_SIGINFO) 283 printf("sigaction=%p", (void *)sa->sa_sigaction); 284 else 285 printf("handler=%p", (void *)sa->sa_handler); 286 printf(", mask="); 287 sigset(sa->sa_mask); 288 printf(", flags="); 289 sigactionflagname(sa->sa_flags); 290 printf(" }\n"); 291 } 292 293 static void 294 print_rlim(rlim_t lim) 295 { 296 if (lim == RLIM_INFINITY) 297 printf("infinite"); 298 else 299 printf("%llu", (unsigned long long)lim); 300 } 301 302 static void 303 ktrrlimit(const struct rlimit *limp) 304 { 305 printf("struct rlimit { "); 306 printf("cur="); 307 print_rlim(limp->rlim_cur); 308 printf(", max="); 309 print_rlim(limp->rlim_max); 310 printf(" }\n"); 311 } 312 313 static void 314 ktrtfork(const struct __tfork *tf) 315 { 316 printf("struct __tfork { tcb=%p, tid=%p, stack=%p }\n", 317 tf->tf_tcb, (void *)tf->tf_tid, tf->tf_stack); 318 } 319 320 static void 321 ktrfds(const char *data, size_t count) 322 { 323 size_t i; 324 int fd; 325 326 for (i = 0; i < count - 1; i++) { 327 memcpy(&fd, &data[i * sizeof(fd)], sizeof(fd)); 328 printf("fd[%zu] = %d, ", i, fd); 329 } 330 memcpy(&fd, &data[i * sizeof(fd)], sizeof(fd)); 331 printf("fd[%zu] = %d\n", i, fd); 332 } 333 334 static void 335 ktrfdset(struct fd_set *fds, int len) 336 { 337 int nfds, i, start = -1; 338 char sep = ' '; 339 340 nfds = len * NBBY; 341 printf("struct fd_set {"); 342 for (i = 0; i <= nfds; i++) 343 if (i != nfds && FD_ISSET(i, fds)) { 344 if (start == -1) 345 start = i; 346 } else if (start != -1) { 347 putchar(sep); 348 if (start == i - 1) 349 printf("%d", start); 350 else if (start == i - 2) 351 printf("%d,%d", start, i - 1); 352 else 353 printf("%d-%d", start, i - 1); 354 sep = ','; 355 start = -1; 356 } 357 358 printf(" }\n"); 359 } 360 361 static void 362 ktrrusage(const struct rusage *rup) 363 { 364 printf("struct rusage { utime="); 365 print_timeval(&rup->ru_utime, 1); 366 printf(", stime="); 367 print_timeval(&rup->ru_stime, 1); 368 printf(", maxrss=%ld, ixrss=%ld, idrss=%ld, isrss=%ld," 369 " minflt=%ld, majflt=%ld, nswap=%ld, inblock=%ld," 370 " oublock=%ld, msgsnd=%ld, msgrcv=%ld, nsignals=%ld," 371 " nvcsw=%ld, nivcsw=%ld }\n", 372 rup->ru_maxrss, rup->ru_ixrss, rup->ru_idrss, rup->ru_isrss, 373 rup->ru_minflt, rup->ru_majflt, rup->ru_nswap, rup->ru_inblock, 374 rup->ru_oublock, rup->ru_msgsnd, rup->ru_msgrcv, rup->ru_nsignals, 375 rup->ru_nvcsw, rup->ru_nivcsw); 376 } 377 378 static void 379 ktrquota(const struct dqblk *quota) 380 { 381 printf("struct dqblk { bhardlimit=%u, bsoftlimit=%u, curblocks=%u," 382 " ihardlimit=%u, isoftlimit=%u, curinodes=%u, btime=", 383 quota->dqb_bhardlimit, quota->dqb_bsoftlimit, 384 quota->dqb_curblocks, quota->dqb_ihardlimit, 385 quota->dqb_isoftlimit, quota->dqb_curinodes); 386 print_time(quota->dqb_btime, 0, 0); 387 printf(", itime="); 388 print_time(quota->dqb_itime, 0, 0); 389 printf(" }\n"); 390 } 391 392 static void 393 ktrmsghdr(const struct msghdr *msg) 394 { 395 printf("struct msghdr { name=%p, namelen=%u, iov=%p, iovlen=%u," 396 " control=%p, controllen=%u, flags=", 397 msg->msg_name, msg->msg_namelen, msg->msg_iov, msg->msg_iovlen, 398 msg->msg_control, msg->msg_controllen); 399 sendrecvflagsname(msg->msg_flags); 400 printf(" }\n"); 401 } 402 403 static void 404 ktriovec(const char *data, int count) 405 { 406 struct iovec iov; 407 int i; 408 409 printf("struct iovec"); 410 if (count > 1) 411 printf(" [%d]", count); 412 for (i = 0; i < count; i++) { 413 memcpy(&iov, data, sizeof(iov)); 414 data += sizeof(iov); 415 printf(" { base=%p, len=%lu }", iov.iov_base, iov.iov_len); 416 } 417 printf("\n"); 418 } 419 420 static void 421 ktrevent(const char *data, int count) 422 { 423 struct kevent kev; 424 int i; 425 426 printf("struct kevent"); 427 if (count > 1) 428 printf(" [%d]", count); 429 for (i = 0; i < count; i++) { 430 memcpy(&kev, data, sizeof(kev)); 431 data += sizeof(kev); 432 printf(" { ident=%lu, filter=", kev.ident); 433 evfiltername(kev.filter); 434 printf(", flags="); 435 evflagsname(kev.flags); 436 printf(", fflags="); 437 evfflagsname(kev.filter, kev.fflags); 438 printf(", data=%llu", kev.data); 439 if ((kev.flags & EV_ERROR) && fancy) { 440 printf("<\"%s\">", strerror(kev.data)); 441 } 442 printf(", udata=%p }", kev.udata); 443 } 444 printf("\n"); 445 } 446 447 static void 448 ktrpollfd(const char *data, int count) 449 { 450 struct pollfd pfd; 451 int i; 452 453 printf("struct pollfd"); 454 if (count > 1) 455 printf(" [%d]", count); 456 for (i = 0; i < count; i++) { 457 memcpy(&pfd, data, sizeof(pfd)); 458 data += sizeof(pfd); 459 printf(" { fd=%d, events=", pfd.fd); 460 pollfdeventname(pfd.events); 461 printf(", revents="); 462 pollfdeventname(pfd.revents); 463 printf(" }"); 464 } 465 printf("\n"); 466 } 467 468 static void 469 ktrcmsghdr(char *data, socklen_t len) 470 { 471 struct msghdr msg; 472 struct cmsghdr *cmsg; 473 int i, count, *fds; 474 475 msg.msg_control = data; 476 msg.msg_controllen = len; 477 478 /* count the control messages */ 479 count = 0; 480 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 481 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 482 count++; 483 } 484 485 printf("struct cmsghdr"); 486 if (count > 1) 487 printf(" [%d]", count); 488 489 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 490 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 491 printf(" { len=%u, level=", cmsg->cmsg_len); 492 if (cmsg->cmsg_level == SOL_SOCKET) { 493 printf("SOL_SOCKET, type="); 494 switch (cmsg->cmsg_type) { 495 case SCM_RIGHTS: 496 printf("SCM_RIGHTS, data="); 497 fds = (int *)CMSG_DATA(cmsg); 498 for (i = 0; 499 cmsg->cmsg_len > CMSG_LEN(sizeof(int) * i); 500 i++) { 501 printf("%s%d", i ? "," : "", fds[i]); 502 } 503 break; 504 case SCM_TIMESTAMP: 505 default: 506 printf("%d", cmsg->cmsg_type); 507 break; 508 } 509 } else { 510 struct protoent *p = getprotobynumber(cmsg->cmsg_level); 511 512 printf("%u<%s>, type=%d", cmsg->cmsg_level, 513 p != NULL ? p->p_name : "unknown", cmsg->cmsg_type); 514 } 515 printf(" }"); 516 } 517 printf("\n"); 518 } 519 520 void 521 ktrstruct(char *buf, size_t buflen) 522 { 523 char *name, *data; 524 size_t namelen, datalen; 525 int i; 526 527 for (name = buf, namelen = 0; namelen < buflen && name[namelen] != '\0'; 528 ++namelen) 529 /* nothing */; 530 if (namelen == buflen) 531 goto invalid; 532 if (name[namelen] != '\0') 533 goto invalid; 534 data = buf + namelen + 1; 535 datalen = buflen - namelen - 1; 536 if (datalen == 0) 537 goto invalid; 538 /* sanity check */ 539 for (i = 0; i < namelen; ++i) 540 if (!isalpha((unsigned char)name[i])) 541 goto invalid; 542 if (strcmp(name, "stat") == 0) { 543 struct stat sb; 544 545 if (datalen != sizeof(struct stat)) 546 goto invalid; 547 memcpy(&sb, data, datalen); 548 ktrstat(&sb); 549 } else if (strcmp(name, "sockaddr") == 0) { 550 struct sockaddr_storage ss; 551 552 if (datalen > sizeof(ss)) 553 goto invalid; 554 memcpy(&ss, data, datalen); 555 if ((ss.ss_family != AF_UNIX && 556 datalen < sizeof(struct sockaddr)) || datalen != ss.ss_len) 557 goto invalid; 558 ktrsockaddr((struct sockaddr *)&ss); 559 } else if (strcmp(name, "abstimespec") == 0 || 560 strcmp(name, "reltimespec") == 0) { 561 struct timespec ts; 562 563 if (datalen != sizeof(ts)) 564 goto invalid; 565 memcpy(&ts, data, datalen); 566 ktrtimespec(&ts, name[0] == 'r'); 567 } else if (strcmp(name, "abstimeval") == 0 || 568 strcmp(name, "reltimeval") == 0) { 569 struct timeval tv; 570 571 if (datalen != sizeof(tv)) 572 goto invalid; 573 memcpy(&tv, data, datalen); 574 ktrtimeval(&tv, name[0] == 'r'); 575 } else if (strcmp(name, "sigaction") == 0) { 576 struct sigaction sa; 577 578 if (datalen != sizeof(sa)) 579 goto invalid; 580 memcpy(&sa, data, datalen); 581 ktrsigaction(&sa); 582 } else if (strcmp(name, "rlimit") == 0) { 583 struct rlimit lim; 584 585 if (datalen != sizeof(lim)) 586 goto invalid; 587 memcpy(&lim, data, datalen); 588 ktrrlimit(&lim); 589 } else if (strcmp(name, "rusage") == 0) { 590 struct rusage ru; 591 592 if (datalen != sizeof(ru)) 593 goto invalid; 594 memcpy(&ru, data, datalen); 595 ktrrusage(&ru); 596 } else if (strcmp(name, "tfork") == 0) { 597 struct __tfork tf; 598 599 if (datalen != sizeof(tf)) 600 goto invalid; 601 memcpy(&tf, data, datalen); 602 ktrtfork(&tf); 603 } else if (strcmp(name, "fds") == 0) { 604 if (datalen % sizeof(int)) 605 goto invalid; 606 ktrfds(data, datalen / sizeof(int)); 607 } else if (strcmp(name, "fdset") == 0) { 608 struct fd_set *fds; 609 610 if ((fds = malloc(datalen)) == NULL) 611 err(1, "malloc"); 612 memcpy(fds, data, datalen); 613 ktrfdset(fds, datalen); 614 free(fds); 615 } else if (strcmp(name, "quota") == 0) { 616 struct dqblk quota; 617 618 if (datalen != sizeof(quota)) 619 goto invalid; 620 memcpy("a, data, datalen); 621 ktrquota("a); 622 } else if (strcmp(name, "msghdr") == 0) { 623 struct msghdr msg; 624 625 if (datalen != sizeof(msg)) 626 goto invalid; 627 memcpy(&msg, data, datalen); 628 ktrmsghdr(&msg); 629 } else if (strcmp(name, "iovec") == 0) { 630 if (datalen % sizeof(struct iovec)) 631 goto invalid; 632 ktriovec(data, datalen / sizeof(struct iovec)); 633 } else if (strcmp(name, "kevent") == 0) { 634 if (datalen % sizeof(struct kevent)) 635 goto invalid; 636 ktrevent(data, datalen / sizeof(struct kevent)); 637 } else if (strcmp(name, "pollfd") == 0) { 638 if (datalen % sizeof(struct pollfd)) 639 goto invalid; 640 ktrpollfd(data, datalen / sizeof(struct pollfd)); 641 } else if (strcmp(name, "cmsghdr") == 0) { 642 char *cmsg; 643 644 if ((cmsg = malloc(datalen)) == NULL) 645 err(1, "malloc"); 646 memcpy(cmsg, data, datalen); 647 ktrcmsghdr(cmsg, datalen); 648 free(cmsg); 649 } else if (strcmp(name, "pledgereq") == 0) { 650 printf("promise="); 651 showbufc(basecol + sizeof("promise=") - 1, 652 (unsigned char *)data, datalen, VIS_DQ | VIS_TAB | VIS_NL); 653 } else if (strcmp(name, "pledgeexecreq") == 0) { 654 printf("execpromise="); 655 showbufc(basecol + sizeof("execpromise=") - 1, 656 (unsigned char *)data, datalen, VIS_DQ | VIS_TAB | VIS_NL); 657 } else { 658 printf("unknown structure %s\n", name); 659 } 660 return; 661 invalid: 662 printf("invalid record\n"); 663 } 664