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