1 /* $OpenBSD: kvm_file2.c,v 1.56 2021/09/10 00:02:43 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Todd C. Miller <millert@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /*- 20 * Copyright (c) 1989, 1992, 1993 21 * The Regents of the University of California. All rights reserved. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the above copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. Neither the name of the University nor the names of its contributors 32 * may be used to endorse or promote products derived from this software 33 * without specific prior written permission. 34 * 35 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 38 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 45 * SUCH DAMAGE. 46 */ 47 48 /* 49 * Extended file list interface for kvm. pstat, fstat and netstat are 50 * users of this code, so we've factored it out into a separate module. 51 * Thus, we keep this grunge out of the other kvm applications (i.e., 52 * most other applications are interested only in open/close/read/nlist). 53 */ 54 55 #define __need_process 56 57 #include <sys/param.h> /* MAXCOMLEN */ 58 #include <sys/types.h> 59 #include <sys/signal.h> 60 #include <sys/uio.h> 61 #include <sys/ucred.h> 62 #include <sys/proc.h> 63 #define _KERNEL 64 #include <sys/file.h> 65 #include <sys/mount.h> 66 #undef _KERNEL 67 #include <sys/vnode.h> 68 #include <sys/socket.h> 69 #include <sys/socketvar.h> 70 #include <sys/domain.h> 71 #include <sys/protosw.h> 72 #include <sys/event.h> 73 #include <sys/eventvar.h> 74 #include <sys/un.h> 75 #include <sys/unpcb.h> 76 #include <sys/filedesc.h> 77 #include <sys/mbuf.h> 78 #include <sys/pipe.h> 79 #include <sys/stat.h> 80 #include <sys/sysctl.h> 81 #include <sys/specdev.h> 82 83 #define _KERNEL 84 #include <ufs/ufs/quota.h> 85 #include <ufs/ufs/inode.h> 86 #undef _KERNEL 87 88 #include <nfs/nfsproto.h> 89 #include <nfs/rpcv2.h> 90 #include <nfs/nfs.h> 91 #include <nfs/nfsnode.h> 92 93 #include <msdosfs/bpb.h> 94 #include <msdosfs/denode.h> 95 #include <msdosfs/msdosfsmount.h> 96 97 #include <net/route.h> 98 #include <netinet/in.h> 99 #include <netinet/ip.h> 100 #include <netinet/in_pcb.h> 101 #include <netinet/tcp.h> 102 #include <netinet/tcp_timer.h> 103 #include <netinet/tcp_var.h> 104 105 #ifdef INET6 106 #include <netinet/ip6.h> 107 #include <netinet6/ip6_var.h> 108 #endif 109 110 #include <fcntl.h> 111 #include <nlist.h> 112 #include <kvm.h> 113 #include <db.h> 114 #include <stddef.h> 115 #include <stdlib.h> 116 #include <string.h> 117 #include <unistd.h> 118 #include <limits.h> 119 #include <errno.h> 120 121 #include "kvm_private.h" 122 #include "kvm_file.h" 123 124 static struct kinfo_file *kvm_deadfile_byfile(kvm_t *, int, int, 125 size_t, int *); 126 static struct kinfo_file *kvm_deadfile_byid(kvm_t *, int, int, 127 size_t, int *); 128 static int fill_file(kvm_t *, struct kinfo_file *, struct file *, u_long, 129 struct vnode *, struct process *, int, pid_t); 130 static int filestat(kvm_t *, struct kinfo_file *, struct vnode *); 131 132 LIST_HEAD(processlist, process); 133 134 struct kinfo_file * 135 kvm_getfiles(kvm_t *kd, int op, int arg, size_t esize, int *cnt) 136 { 137 int mib[6], rv; 138 void *filebase; 139 size_t size; 140 141 if (ISALIVE(kd)) { 142 mib[0] = CTL_KERN; 143 mib[1] = KERN_FILE; 144 mib[2] = op; 145 mib[3] = arg; 146 mib[4] = esize; 147 148 do { 149 mib[5] = 0; 150 151 /* find size and alloc buffer */ 152 rv = sysctl(mib, 6, NULL, &size, NULL, 0); 153 if (rv == -1) { 154 if (errno != ESRCH && kd->vmfd != -1) 155 goto deadway; 156 _kvm_syserr(kd, kd->program, "kvm_getfiles"); 157 return (NULL); 158 } 159 160 size += size / 8; /* add ~10% */ 161 162 filebase = _kvm_realloc(kd, kd->filebase, size); 163 if (filebase == NULL) 164 return (NULL); 165 166 kd->filebase = filebase; 167 168 /* get actual data */ 169 mib[5] = size / esize; 170 rv = sysctl(mib, 6, kd->filebase, &size, NULL, 0); 171 if (rv == -1 && errno != ENOMEM) { 172 _kvm_syserr(kd, kd->program, 173 "kvm_getfiles"); 174 return (NULL); 175 } 176 } while (rv == -1); 177 178 *cnt = size / esize; 179 return (kd->filebase); 180 } else { 181 if (esize > sizeof(struct kinfo_file)) { 182 _kvm_syserr(kd, kd->program, 183 "kvm_getfiles: unknown fields requested: libkvm out of date?"); 184 return (NULL); 185 } 186 deadway: 187 switch (op) { 188 case KERN_FILE_BYFILE: 189 return (kvm_deadfile_byfile(kd, op, arg, esize, cnt)); 190 break; 191 case KERN_FILE_BYPID: 192 case KERN_FILE_BYUID: 193 return (kvm_deadfile_byid(kd, op, arg, esize, cnt)); 194 break; 195 default: 196 return (NULL); 197 } 198 } 199 } 200 201 static struct kinfo_file * 202 kvm_deadfile_byfile(kvm_t *kd, int op, int arg, size_t esize, int *cnt) 203 { 204 struct nlist nl[3], *p; 205 size_t buflen; 206 int n = 0; 207 char *where; 208 struct kinfo_file kf; 209 struct file *fp, file; 210 struct filelist filehead; 211 int nfiles; 212 213 nl[0].n_name = "_filehead"; 214 nl[1].n_name = "_numfiles"; 215 nl[2].n_name = 0; 216 217 if (kvm_nlist(kd, nl) != 0) { 218 for (p = nl; p->n_type != 0; ++p) 219 ; 220 _kvm_err(kd, kd->program, 221 "%s: no such symbol", p->n_name); 222 return (NULL); 223 } 224 if (KREAD(kd, nl[0].n_value, &filehead)) { 225 _kvm_err(kd, kd->program, "can't read filehead"); 226 return (NULL); 227 } 228 if (KREAD(kd, nl[1].n_value, &nfiles)) { 229 _kvm_err(kd, kd->program, "can't read nfiles"); 230 return (NULL); 231 } 232 where = _kvm_reallocarray(kd, kd->filebase, nfiles, esize); 233 if (where == NULL) 234 return (NULL); 235 236 kd->filebase = (void *)where; 237 buflen = nfiles * esize; 238 239 for (fp = LIST_FIRST(&filehead); 240 fp != NULL && esize <= buflen; 241 fp = LIST_NEXT(&file, f_list)) { 242 if (KREAD(kd, (u_long)fp, &file)) { 243 _kvm_err(kd, kd->program, "can't read kfp"); 244 return (NULL); 245 } 246 if (file.f_count == 0) 247 continue; 248 if (arg != 0 && file.f_type != arg) 249 continue; 250 if (fill_file(kd, &kf, &file, (u_long)fp, NULL, NULL, 0, 0) 251 == -1) 252 return (NULL); 253 memcpy(where, &kf, esize); 254 where += esize; 255 buflen -= esize; 256 n++; 257 } 258 if (n != nfiles) { 259 _kvm_err(kd, kd->program, "inconsistent nfiles"); 260 return (NULL); 261 } 262 *cnt = n; 263 return (kd->filebase); 264 } 265 266 static struct kinfo_file * 267 kvm_deadfile_byid(kvm_t *kd, int op, int arg, size_t esize, int *cnt) 268 { 269 size_t buflen; 270 struct nlist nl[4], *np; 271 int n = 0, matched = 0; 272 char *where; 273 struct kinfo_file kf; 274 struct file *fp, file; 275 struct filelist filehead; 276 struct filedesc0 filed0; 277 #define filed filed0.fd_fd 278 struct processlist allprocess; 279 struct process *pr, process; 280 struct ucred ucred; 281 char *filebuf = NULL; 282 int i, nfiles; 283 284 nl[0].n_name = "_filehead"; 285 nl[1].n_name = "_numfiles"; 286 nl[2].n_name = "_allprocess"; 287 nl[3].n_name = 0; 288 289 if (kvm_nlist(kd, nl) != 0) { 290 for (np = nl; np->n_type != 0; ++np) 291 ; 292 _kvm_err(kd, kd->program, 293 "%s: no such symbol", np->n_name); 294 return (NULL); 295 } 296 if (KREAD(kd, nl[0].n_value, &filehead)) { 297 _kvm_err(kd, kd->program, "can't read filehead"); 298 return (NULL); 299 } 300 if (KREAD(kd, nl[1].n_value, &nfiles)) { 301 _kvm_err(kd, kd->program, "can't read nfiles"); 302 return (NULL); 303 } 304 if (KREAD(kd, nl[2].n_value, &allprocess)) { 305 _kvm_err(kd, kd->program, "can't read allprocess"); 306 return (NULL); 307 } 308 /* this may be more room than we need but counting is expensive */ 309 where = _kvm_reallocarray(kd, kd->filebase, nfiles + 10, esize); 310 if (where == NULL) 311 return (NULL); 312 313 kd->filebase = (void *)where; 314 buflen = (nfiles + 10) * esize; 315 316 if (op != KERN_FILE_BYPID || arg <= 0) 317 matched = 1; 318 319 for (pr = LIST_FIRST(&allprocess); 320 pr != NULL; 321 pr = LIST_NEXT(&process, ps_list)) { 322 if (KREAD(kd, (u_long)pr, &process)) { 323 _kvm_err(kd, kd->program, "can't read process at %lx", 324 (u_long)pr); 325 goto cleanup; 326 } 327 328 /* skip system, exiting, embryonic and undead processes */ 329 if (process.ps_flags & (PS_SYSTEM | PS_EMBRYO | PS_EXITING)) 330 continue; 331 332 if (op == KERN_FILE_BYPID) { 333 /* check if this is the pid we are looking for */ 334 if (arg > 0 && process.ps_pid != (pid_t)arg) 335 continue; 336 matched = 1; 337 } 338 339 if (KREAD(kd, (u_long)process.ps_ucred, &ucred)) { 340 _kvm_err(kd, kd->program, "can't read ucred at %lx", 341 (u_long)process.ps_ucred); 342 goto cleanup; 343 } 344 process.ps_ucred = &ucred; 345 346 if (op == KERN_FILE_BYUID && arg >= 0 && 347 process.ps_ucred->cr_uid != (uid_t)arg) { 348 /* not the uid we are looking for */ 349 continue; 350 } 351 352 if (KREAD(kd, (u_long)process.ps_fd, &filed0)) { 353 _kvm_err(kd, kd->program, "can't read filedesc at %lx", 354 (u_long)process.ps_fd); 355 goto cleanup; 356 } 357 if ((char *)process.ps_fd + offsetof(struct filedesc0,fd_dfiles) 358 == (char *)filed.fd_ofiles) { 359 filed.fd_ofiles = filed0.fd_dfiles; 360 filed.fd_ofileflags = filed0.fd_dfileflags; 361 } else { 362 size_t fsize; 363 char *tmp = reallocarray(filebuf, 364 filed.fd_nfiles, OFILESIZE); 365 366 fsize = filed.fd_nfiles * OFILESIZE; 367 if (tmp == NULL) { 368 _kvm_syserr(kd, kd->program, "realloc ofiles"); 369 goto cleanup; 370 } 371 filebuf = tmp; 372 if (kvm_read(kd, (u_long)filed.fd_ofiles, filebuf, 373 fsize) != fsize) { 374 _kvm_err(kd, kd->program, 375 "can't read fd_ofiles"); 376 goto cleanup; 377 } 378 filed.fd_ofiles = (void *)filebuf; 379 filed.fd_ofileflags = filebuf + 380 (filed.fd_nfiles * sizeof(struct file *)); 381 } 382 process.ps_fd = &filed; 383 384 if (process.ps_textvp) { 385 if (buflen < esize) 386 goto done; 387 if (fill_file(kd, &kf, NULL, 0, process.ps_textvp, 388 &process, KERN_FILE_TEXT, process.ps_pid) == -1) 389 goto cleanup; 390 memcpy(where, &kf, esize); 391 where += esize; 392 buflen -= esize; 393 n++; 394 } 395 if (filed.fd_cdir) { 396 if (buflen < esize) 397 goto done; 398 if (fill_file(kd, &kf, NULL, 0, filed.fd_cdir, 399 &process, KERN_FILE_CDIR, process.ps_pid) == -1) 400 goto cleanup; 401 memcpy(where, &kf, esize); 402 where += esize; 403 buflen -= esize; 404 n++; 405 } 406 if (filed.fd_rdir) { 407 if (buflen < esize) 408 goto done; 409 if (fill_file(kd, &kf, NULL, 0, filed.fd_rdir, 410 &process, KERN_FILE_RDIR, process.ps_pid) == -1) 411 goto cleanup; 412 memcpy(where, &kf, esize); 413 where += esize; 414 buflen -= esize; 415 n++; 416 } 417 if (process.ps_tracevp) { 418 if (buflen < esize) 419 goto done; 420 if (fill_file(kd, &kf, NULL, 0, process.ps_tracevp, 421 &process, KERN_FILE_TRACE, process.ps_pid) == -1) 422 goto cleanup; 423 memcpy(where, &kf, esize); 424 where += esize; 425 buflen -= esize; 426 n++; 427 } 428 429 if (filed.fd_nfiles < 0 || 430 filed.fd_lastfile >= filed.fd_nfiles || 431 filed.fd_freefile > filed.fd_lastfile + 1) { 432 _kvm_err(kd, kd->program, 433 "filedesc corrupted at %lx for pid %d", 434 (u_long)process.ps_fd, process.ps_pid); 435 goto cleanup; 436 } 437 438 for (i = 0; i < filed.fd_nfiles; i++) { 439 if (buflen < esize) 440 goto done; 441 if ((fp = filed.fd_ofiles[i]) == NULL) 442 continue; 443 if (KREAD(kd, (u_long)fp, &file)) { 444 _kvm_err(kd, kd->program, "can't read file"); 445 goto cleanup; 446 } 447 if (fill_file(kd, &kf, &file, (u_long)fp, NULL, 448 &process, i, process.ps_pid) == -1) 449 goto cleanup; 450 memcpy(where, &kf, esize); 451 where += esize; 452 buflen -= esize; 453 n++; 454 } 455 } 456 if (!matched) { 457 errno = ESRCH; 458 goto cleanup; 459 } 460 done: 461 *cnt = n; 462 free(filebuf); 463 return (kd->filebase); 464 cleanup: 465 free(filebuf); 466 return (NULL); 467 } 468 469 static int 470 fill_file(kvm_t *kd, struct kinfo_file *kf, struct file *fp, u_long fpaddr, 471 struct vnode *vp, struct process *pr, int fd, pid_t pid) 472 { 473 struct ucred f_cred; 474 475 memset(kf, 0, sizeof(*kf)); 476 477 kf->fd_fd = fd; /* might not really be an fd */ 478 479 if (fp != NULL) { 480 /* Fill in f_cred */ 481 if (KREAD(kd, (u_long)fp->f_cred, &f_cred)) { 482 _kvm_err(kd, kd->program, "can't read f_cred"); 483 return (-1); 484 } 485 486 kf->f_fileaddr = PTRTOINT64(fpaddr); 487 kf->f_flag = fp->f_flag; 488 kf->f_iflags = fp->f_iflags; 489 kf->f_type = fp->f_type; 490 kf->f_count = fp->f_count; 491 kf->f_ucred = PTRTOINT64(fp->f_cred); 492 kf->f_uid = f_cred.cr_uid; 493 kf->f_gid = f_cred.cr_gid; 494 kf->f_ops = PTRTOINT64(fp->f_ops); 495 kf->f_offset = fp->f_offset; 496 kf->f_data = PTRTOINT64(fp->f_data); 497 kf->f_usecount = 0; 498 499 kf->f_rxfer = fp->f_rxfer; 500 kf->f_rwfer = fp->f_wxfer; 501 kf->f_seek = fp->f_seek; 502 kf->f_rbytes = fp->f_rbytes; 503 kf->f_wbytes = fp->f_wbytes; 504 } else if (vp != NULL) { 505 /* fake it */ 506 kf->f_type = DTYPE_VNODE; 507 kf->f_flag = FREAD; 508 if (fd == KERN_FILE_TRACE) 509 kf->f_flag |= FWRITE; 510 kf->f_data = PTRTOINT64(vp); 511 } 512 513 /* information about the object associated with this file */ 514 switch (kf->f_type) { 515 case DTYPE_VNODE: { 516 struct vnode vbuf; 517 518 if (KREAD(kd, (u_long)(fp ? fp->f_data : vp), &vbuf)) { 519 _kvm_err(kd, kd->program, "can't read vnode"); 520 return (-1); 521 } 522 vp = &vbuf; 523 524 kf->v_un = PTRTOINT64(vp->v_un.vu_socket); 525 kf->v_type = vp->v_type; 526 kf->v_tag = vp->v_tag; 527 kf->v_flag = vp->v_flag; 528 kf->v_data = PTRTOINT64(vp->v_data); 529 kf->v_mount = PTRTOINT64(vp->v_mount); 530 531 if (vp->v_mount != NULL) { 532 struct mount mount; 533 534 if (KREAD(kd, (u_long)vp->v_mount, &mount)) { 535 _kvm_err(kd, kd->program, "can't read v_mount"); 536 return (-1); 537 } 538 539 strlcpy(kf->f_mntonname, mount.mnt_stat.f_mntonname, 540 sizeof(kf->f_mntonname)); 541 } 542 543 /* Fill in va_fsid, va_fileid, va_mode, va_size, va_rdev */ 544 filestat(kd, kf, vp); 545 break; 546 } 547 548 case DTYPE_SOCKET: { 549 struct socket sock; 550 struct sosplice ssp; 551 struct protosw protosw; 552 struct domain domain; 553 554 if (KREAD(kd, (u_long)fp->f_data, &sock)) { 555 _kvm_err(kd, kd->program, "can't read socket"); 556 return (-1); 557 } 558 559 kf->so_type = sock.so_type; 560 kf->so_state = sock.so_state; 561 kf->so_pcb = PTRTOINT64(sock.so_pcb); 562 if (KREAD(kd, (u_long)sock.so_proto, &protosw)) { 563 _kvm_err(kd, kd->program, "can't read protosw"); 564 return (-1); 565 } 566 kf->so_protocol = protosw.pr_protocol; 567 if (KREAD(kd, (u_long)protosw.pr_domain, &domain)) { 568 _kvm_err(kd, kd->program, "can't read domain"); 569 return (-1); 570 } 571 kf->so_family = domain.dom_family; 572 kf->so_rcv_cc = sock.so_rcv.sb_cc; 573 kf->so_snd_cc = sock.so_snd.sb_cc; 574 if (sock.so_sp) { 575 if (KREAD(kd, (u_long)sock.so_sp, &ssp)) { 576 _kvm_err(kd, kd->program, "can't read splice"); 577 return (-1); 578 } 579 if (ssp.ssp_socket) { 580 kf->so_splice = PTRTOINT64(ssp.ssp_socket); 581 kf->so_splicelen = ssp.ssp_len; 582 } else if (ssp.ssp_soback) { 583 kf->so_splicelen = -1; 584 } 585 } 586 if (!sock.so_pcb) 587 break; 588 switch (kf->so_family) { 589 case AF_INET: { 590 struct inpcb inpcb; 591 592 if (KREAD(kd, (u_long)sock.so_pcb, &inpcb)) { 593 _kvm_err(kd, kd->program, "can't read inpcb"); 594 return (-1); 595 } 596 kf->inp_ppcb = PTRTOINT64(inpcb.inp_ppcb); 597 kf->inp_lport = inpcb.inp_lport; 598 kf->inp_laddru[0] = inpcb.inp_laddr.s_addr; 599 kf->inp_fport = inpcb.inp_fport; 600 kf->inp_faddru[0] = inpcb.inp_faddr.s_addr; 601 kf->inp_rtableid = inpcb.inp_rtableid; 602 if (sock.so_type == SOCK_RAW) 603 kf->inp_proto = inpcb.inp_ip.ip_p; 604 if (protosw.pr_protocol == IPPROTO_TCP) { 605 struct tcpcb tcpcb; 606 if (KREAD(kd, (u_long)inpcb.inp_ppcb, &tcpcb)) { 607 _kvm_err(kd, kd->program, 608 "can't read tcpcb"); 609 return (-1); 610 } 611 kf->t_rcv_wnd = tcpcb.rcv_wnd; 612 kf->t_snd_wnd = tcpcb.snd_wnd; 613 kf->t_snd_cwnd = tcpcb.snd_cwnd; 614 kf->t_state = tcpcb.t_state; 615 } 616 break; 617 } 618 case AF_INET6: { 619 struct inpcb inpcb; 620 #define s6_addr32 __u6_addr.__u6_addr32 621 622 if (KREAD(kd, (u_long)sock.so_pcb, &inpcb)) { 623 _kvm_err(kd, kd->program, "can't read inpcb"); 624 return (-1); 625 } 626 kf->inp_ppcb = PTRTOINT64(inpcb.inp_ppcb); 627 kf->inp_lport = inpcb.inp_lport; 628 kf->inp_laddru[0] = inpcb.inp_laddr6.s6_addr32[0]; 629 kf->inp_laddru[1] = inpcb.inp_laddr6.s6_addr32[1]; 630 kf->inp_laddru[2] = inpcb.inp_laddr6.s6_addr32[2]; 631 kf->inp_laddru[3] = inpcb.inp_laddr6.s6_addr32[3]; 632 kf->inp_fport = inpcb.inp_fport; 633 kf->inp_faddru[0] = inpcb.inp_laddr6.s6_addr32[0]; 634 kf->inp_faddru[1] = inpcb.inp_faddr6.s6_addr32[1]; 635 kf->inp_faddru[2] = inpcb.inp_faddr6.s6_addr32[2]; 636 kf->inp_faddru[3] = inpcb.inp_faddr6.s6_addr32[3]; 637 kf->inp_rtableid = inpcb.inp_rtableid; 638 if (sock.so_type == SOCK_RAW) 639 kf->inp_proto = inpcb.inp_ipv6.ip6_nxt; 640 if (protosw.pr_protocol == IPPROTO_TCP) { 641 struct tcpcb tcpcb; 642 if (KREAD(kd, (u_long)inpcb.inp_ppcb, &tcpcb)) { 643 _kvm_err(kd, kd->program, 644 "can't read tcpcb"); 645 return (-1); 646 } 647 kf->t_rcv_wnd = tcpcb.rcv_wnd; 648 kf->t_snd_wnd = tcpcb.snd_wnd; 649 kf->t_snd_cwnd = tcpcb.snd_cwnd; 650 kf->t_state = tcpcb.t_state; 651 } 652 break; 653 } 654 case AF_UNIX: { 655 struct unpcb unpcb; 656 657 if (KREAD(kd, (u_long)sock.so_pcb, &unpcb)) { 658 _kvm_err(kd, kd->program, "can't read unpcb"); 659 return (-1); 660 } 661 kf->f_msgcount = unpcb.unp_msgcount; 662 kf->unp_conn = PTRTOINT64(unpcb.unp_conn); 663 kf->unp_refs = PTRTOINT64( 664 SLIST_FIRST(&unpcb.unp_refs)); 665 kf->unp_nextref = PTRTOINT64( 666 SLIST_NEXT(&unpcb, unp_nextref)); 667 kf->v_un = PTRTOINT64(unpcb.unp_vnode); 668 if (unpcb.unp_addr != NULL) { 669 struct mbuf mb; 670 struct sockaddr_un un; 671 672 if (KREAD(kd, (u_long)unpcb.unp_addr, &mb)) { 673 _kvm_err(kd, kd->program, 674 "can't read sockaddr_un mbuf"); 675 return (-1); 676 } 677 if (KREAD(kd, (u_long)mb.m_data, &un)) { 678 _kvm_err(kd, kd->program, 679 "can't read sockaddr_un"); 680 return (-1); 681 } 682 683 kf->unp_addr = PTRTOINT64(unpcb.unp_addr); 684 memcpy(kf->unp_path, un.sun_path, un.sun_len 685 - offsetof(struct sockaddr_un,sun_path)); 686 } 687 688 break; 689 } 690 } 691 break; 692 } 693 694 case DTYPE_PIPE: { 695 struct pipe pipe; 696 697 if (KREAD(kd, (u_long)fp->f_data, &pipe)) { 698 _kvm_err(kd, kd->program, "can't read pipe"); 699 return (-1); 700 } 701 kf->pipe_peer = PTRTOINT64(pipe.pipe_peer); 702 kf->pipe_state = pipe.pipe_state; 703 break; 704 } 705 706 case DTYPE_KQUEUE: { 707 struct kqueue kqi; 708 709 if (KREAD(kd, (u_long)fp->f_data, &kqi)) { 710 _kvm_err(kd, kd->program, "can't read kqi"); 711 return (-1); 712 } 713 kf->kq_count = kqi.kq_count; 714 kf->kq_state = kqi.kq_state; 715 break; 716 } 717 } 718 719 /* per-process information for KERN_FILE_BY[PU]ID */ 720 if (pr != NULL) { 721 kf->p_pid = pid; 722 kf->p_uid = pr->ps_ucred->cr_uid; 723 kf->p_gid = pr->ps_ucred->cr_gid; 724 kf->p_tid = -1; 725 strlcpy(kf->p_comm, pr->ps_comm, sizeof(kf->p_comm)); 726 if (pr->ps_fd != NULL) 727 kf->fd_ofileflags = pr->ps_fd->fd_ofileflags[fd]; 728 } 729 730 return (0); 731 } 732 733 mode_t 734 _kvm_getftype(enum vtype v_type) 735 { 736 mode_t ftype = 0; 737 738 switch (v_type) { 739 case VREG: 740 ftype = S_IFREG; 741 break; 742 case VDIR: 743 ftype = S_IFDIR; 744 break; 745 case VBLK: 746 ftype = S_IFBLK; 747 break; 748 case VCHR: 749 ftype = S_IFCHR; 750 break; 751 case VLNK: 752 ftype = S_IFLNK; 753 break; 754 case VSOCK: 755 ftype = S_IFSOCK; 756 break; 757 case VFIFO: 758 ftype = S_IFIFO; 759 break; 760 case VNON: 761 case VBAD: 762 break; 763 } 764 765 return (ftype); 766 } 767 768 static int 769 ufs_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp) 770 { 771 struct inode inode; 772 struct ufs1_dinode di1; 773 774 if (KREAD(kd, (u_long)VTOI(vp), &inode)) { 775 _kvm_err(kd, kd->program, "can't read inode at %p", VTOI(vp)); 776 return (-1); 777 } 778 779 if (KREAD(kd, (u_long)inode.i_din1, &di1)) { 780 _kvm_err(kd, kd->program, "can't read dinode at %p", 781 inode.i_din1); 782 return (-1); 783 } 784 785 inode.i_din1 = &di1; 786 787 kf->va_fsid = inode.i_dev & 0xffff; 788 kf->va_fileid = (long)inode.i_number; 789 kf->va_mode = inode.i_ffs1_mode; 790 kf->va_size = inode.i_ffs1_size; 791 kf->va_rdev = inode.i_ffs1_rdev; 792 kf->va_nlink = inode.i_ffs1_nlink; 793 794 return (0); 795 } 796 797 static int 798 ext2fs_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp) 799 { 800 struct inode inode; 801 struct ext2fs_dinode e2di; 802 803 if (KREAD(kd, (u_long)VTOI(vp), &inode)) { 804 _kvm_err(kd, kd->program, "can't read inode at %p", VTOI(vp)); 805 return (-1); 806 } 807 808 if (KREAD(kd, (u_long)inode.i_e2din, &e2di)) { 809 _kvm_err(kd, kd->program, "can't read dinode at %p", 810 inode.i_e2din); 811 return (-1); 812 } 813 814 inode.i_e2din = &e2di; 815 816 kf->va_fsid = inode.i_dev & 0xffff; 817 kf->va_fileid = (long)inode.i_number; 818 kf->va_mode = inode.i_e2fs_mode; 819 kf->va_size = inode.i_e2fs_size; 820 kf->va_rdev = 0; /* XXX */ 821 kf->va_nlink = inode.i_e2fs_nlink; 822 823 return (0); 824 } 825 826 static int 827 msdos_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp) 828 { 829 struct denode de; 830 struct msdosfsmount mp; 831 832 if (KREAD(kd, (u_long)VTODE(vp), &de)) { 833 _kvm_err(kd, kd->program, "can't read denode at %p", VTODE(vp)); 834 return (-1); 835 } 836 if (KREAD(kd, (u_long)de.de_pmp, &mp)) { 837 _kvm_err(kd, kd->program, "can't read mount struct at %p", 838 de.de_pmp); 839 return (-1); 840 } 841 842 kf->va_fsid = de.de_dev & 0xffff; 843 kf->va_fileid = 0; /* XXX see msdosfs_vptofh() for more info */ 844 kf->va_mode = (mp.pm_mask & 0777) | _kvm_getftype(vp->v_type); 845 kf->va_size = de.de_FileSize; 846 kf->va_rdev = 0; /* msdosfs doesn't support device files */ 847 kf->va_nlink = 1; 848 849 return (0); 850 } 851 852 static int 853 nfs_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp) 854 { 855 struct nfsnode nfsnode; 856 857 if (KREAD(kd, (u_long)VTONFS(vp), &nfsnode)) { 858 _kvm_err(kd, kd->program, "can't read nfsnode at %p", 859 VTONFS(vp)); 860 return (-1); 861 } 862 kf->va_fsid = nfsnode.n_vattr.va_fsid; 863 kf->va_fileid = nfsnode.n_vattr.va_fileid; 864 kf->va_size = nfsnode.n_size; 865 kf->va_rdev = nfsnode.n_vattr.va_rdev; 866 kf->va_mode = (mode_t)nfsnode.n_vattr.va_mode | _kvm_getftype(vp->v_type); 867 kf->va_nlink = nfsnode.n_vattr.va_nlink; 868 869 return (0); 870 } 871 872 static int 873 spec_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp) 874 { 875 struct specinfo specinfo; 876 struct vnode parent; 877 878 if (KREAD(kd, (u_long)vp->v_specinfo, &specinfo)) { 879 _kvm_err(kd, kd->program, "can't read specinfo at %p", 880 vp->v_specinfo); 881 return (-1); 882 } 883 884 vp->v_specinfo = &specinfo; 885 886 if (KREAD(kd, (u_long)vp->v_specparent, &parent)) { 887 _kvm_err(kd, kd->program, "can't read parent vnode at %p", 888 vp->v_specparent); 889 return (-1); 890 } 891 892 if (ufs_filestat(kd, kf, vp)) 893 return (-1); 894 895 return (0); 896 } 897 898 static int 899 filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp) 900 { 901 int ret = 0; 902 903 if (vp->v_type != VNON && vp->v_type != VBAD) { 904 switch (vp->v_tag) { 905 case VT_UFS: 906 case VT_MFS: 907 ret = ufs_filestat(kd, kf, vp); 908 break; 909 case VT_NFS: 910 ret = nfs_filestat(kd, kf, vp); 911 break; 912 case VT_EXT2FS: 913 ret = ext2fs_filestat(kd, kf, vp); 914 break; 915 case VT_ISOFS: 916 ret = _kvm_stat_cd9660(kd, kf, vp); 917 break; 918 case VT_MSDOSFS: 919 ret = msdos_filestat(kd, kf, vp); 920 break; 921 case VT_UDF: 922 ret = _kvm_stat_udf(kd, kf, vp); 923 break; 924 case VT_NTFS: 925 ret = _kvm_stat_ntfs(kd, kf, vp); 926 break; 927 case VT_NON: 928 if (vp->v_flag & VCLONE) 929 ret = spec_filestat(kd, kf, vp); 930 break; 931 default: 932 ret = -1; 933 break; 934 } 935 } 936 return (ret); 937 } 938