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