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