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