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