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