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