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