Bug Summary

File:src/lib/libkvm/kvm_file2.c
Warning:line 888, column 3
Address of stack memory associated with local variable 'specinfo' is still referred to by the stack variable 'vbuf' upon returning to the caller. This will be a dangling reference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name kvm_file2.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/lib/libkvm/obj -resource-dir /usr/local/llvm16/lib/clang/16 -D _LIBKVM -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libkvm/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/lib/libkvm/kvm_file2.c
1/* $OpenBSD: kvm_file2.c,v 1.57 2022/02/22 17:35:01 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2009 Todd C. Miller <millert@openbsd.org>
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/types.h>
58#include <sys/signal.h>
59#include <sys/uio.h>
60#include <sys/ucred.h>
61#include <sys/proc.h>
62#define _KERNEL
63#include <sys/file.h>
64#include <sys/mount.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/un.h>
74#include <sys/unpcb.h>
75#include <sys/filedesc.h>
76#include <sys/mbuf.h>
77#include <sys/pipe.h>
78#include <sys/stat.h>
79#include <sys/sysctl.h>
80#include <sys/specdev.h>
81
82#define _KERNEL
83#include <ufs/ufs/quota.h>
84#include <ufs/ufs/inode.h>
85#undef _KERNEL
86
87#include <nfs/nfsproto.h>
88#include <nfs/rpcv2.h>
89#include <nfs/nfs.h>
90#include <nfs/nfsnode.h>
91
92#include <msdosfs/bpb.h>
93#include <msdosfs/denode.h>
94#include <msdosfs/msdosfsmount.h>
95
96#include <net/route.h>
97#include <netinet/in.h>
98#include <netinet/ip.h>
99#include <netinet/in_pcb.h>
100#include <netinet/tcp.h>
101#include <netinet/tcp_timer.h>
102#include <netinet/tcp_var.h>
103
104#ifdef INET6
105#include <netinet/ip6.h>
106#include <netinet6/ip6_var.h>
107#endif
108
109#include <fcntl.h>
110#include <nlist.h>
111#include <kvm.h>
112#include <db.h>
113#include <stddef.h>
114#include <stdlib.h>
115#include <string.h>
116#include <unistd.h>
117#include <limits.h>
118#include <errno(*__errno()).h>
119
120#include "kvm_private.h"
121#include "kvm_file.h"
122
123static struct kinfo_file *kvm_deadfile_byfile(kvm_t *, int, int,
124 size_t, int *);
125static struct kinfo_file *kvm_deadfile_byid(kvm_t *, int, int,
126 size_t, int *);
127static int fill_file(kvm_t *, struct kinfo_file *, struct file *, u_long,
128 struct vnode *, struct process *, int, pid_t);
129static int filestat(kvm_t *, struct kinfo_file *, struct vnode *);
130
131LIST_HEAD(processlist, process)struct processlist { struct process *lh_first; };
132
133struct kinfo_file *
134kvm_getfiles(kvm_t *kd, int op, int arg, size_t esize, int *cnt)
135{
136 int mib[6], rv;
137 void *filebase;
138 size_t size;
139
140 if (ISALIVE(kd)((kd)->alive)) {
1
Assuming field 'alive' is 0
2
Taking false branch
141 mib[0] = CTL_KERN1;
142 mib[1] = KERN_FILE73;
143 mib[2] = op;
144 mib[3] = arg;
145 mib[4] = esize;
146
147 do {
148 mib[5] = 0;
149
150 /* find size and alloc buffer */
151 rv = sysctl(mib, 6, NULL((void *)0), &size, NULL((void *)0), 0);
152 if (rv == -1) {
153 if (errno(*__errno()) != ESRCH3 && kd->vmfd != -1)
154 goto deadway;
155 _kvm_syserr(kd, kd->program, "kvm_getfiles");
156 return (NULL((void *)0));
157 }
158
159 size += size / 8; /* add ~10% */
160
161 filebase = _kvm_realloc(kd, kd->filebase, size);
162 if (filebase == NULL((void *)0))
163 return (NULL((void *)0));
164
165 kd->filebase = filebase;
166
167 /* get actual data */
168 mib[5] = size / esize;
169 rv = sysctl(mib, 6, kd->filebase, &size, NULL((void *)0), 0);
170 if (rv == -1 && errno(*__errno()) != ENOMEM12) {
171 _kvm_syserr(kd, kd->program,
172 "kvm_getfiles");
173 return (NULL((void *)0));
174 }
175 } while (rv == -1);
176
177 *cnt = size / esize;
178 return (kd->filebase);
179 } else {
180 if (esize > sizeof(struct kinfo_file)) {
3
Assuming the condition is false
4
Taking false branch
181 _kvm_syserr(kd, kd->program,
182 "kvm_getfiles: unknown fields requested: libkvm out of date?");
183 return (NULL((void *)0));
184 }
185 deadway:
186 switch (op) {
5
Control jumps to 'case 1:' at line 187
187 case KERN_FILE_BYFILE1:
188 return (kvm_deadfile_byfile(kd, op, arg, esize, cnt));
6
Calling 'kvm_deadfile_byfile'
189 break;
190 case KERN_FILE_BYPID2:
191 case KERN_FILE_BYUID3:
192 return (kvm_deadfile_byid(kd, op, arg, esize, cnt));
193 break;
194 default:
195 return (NULL((void *)0));
196 }
197 }
198}
199
200static struct kinfo_file *
201kvm_deadfile_byfile(kvm_t *kd, int op, int arg, size_t esize, int *cnt)
202{
203 struct nlist nl[3], *p;
204 size_t buflen;
205 int n = 0;
206 char *where;
207 struct kinfo_file kf;
208 struct file *fp, file;
209 struct filelist filehead;
210 int nfiles;
211
212 nl[0].n_name = "_filehead";
213 nl[1].n_name = "_numfiles";
214 nl[2].n_name = 0;
215
216 if (kvm_nlist(kd, nl) != 0) {
7
Assuming the condition is false
8
Taking false branch
217 for (p = nl; p->n_type != 0; ++p)
218 ;
219 _kvm_err(kd, kd->program,
220 "%s: no such symbol", p->n_name);
221 return (NULL((void *)0));
222 }
223 if (KREAD(kd, nl[0].n_value, &filehead)(kvm_read(kd, nl[0].n_value, (void *)(&filehead), sizeof(
*&filehead)) != sizeof(*&filehead))
) {
9
Assuming the condition is false
10
Taking false branch
224 _kvm_err(kd, kd->program, "can't read filehead");
225 return (NULL((void *)0));
226 }
227 if (KREAD(kd, nl[1].n_value, &nfiles)(kvm_read(kd, nl[1].n_value, (void *)(&nfiles), sizeof(*&
nfiles)) != sizeof(*&nfiles))
) {
11
Assuming the condition is false
12
Taking false branch
228 _kvm_err(kd, kd->program, "can't read nfiles");
229 return (NULL((void *)0));
230 }
231 where = _kvm_reallocarray(kd, kd->filebase, nfiles, esize);
232 if (where == NULL((void *)0))
13
Assuming 'where' is not equal to NULL
14
Taking false branch
233 return (NULL((void *)0));
234
235 kd->filebase = (void *)where;
236 buflen = nfiles * esize;
237
238 for (fp = LIST_FIRST(&filehead)((&filehead)->lh_first);
17
Loop condition is true. Entering loop body
239 fp != NULL((void *)0) && esize <= buflen;
15
Assuming 'fp' is not equal to NULL
16
Assuming 'esize' is <= 'buflen'
240 fp = LIST_NEXT(&file, f_list)((&file)->f_list.le_next)) {
241 if (KREAD(kd, (u_long)fp, &file)(kvm_read(kd, (u_long)fp, (void *)(&file), sizeof(*&file
)) != sizeof(*&file))
) {
18
Assuming the condition is false
19
Taking false branch
242 _kvm_err(kd, kd->program, "can't read kfp");
243 return (NULL((void *)0));
244 }
245 if (file.f_count == 0)
20
Assuming field 'f_count' is not equal to 0
246 continue;
247 if (arg != 0 && file.f_type != arg)
21
Assuming 'arg' is equal to 0
248 continue;
249 if (fill_file(kd, &kf, &file, (u_long)fp, NULL((void *)0), NULL((void *)0), 0, 0)
22
Calling 'fill_file'
250 == -1)
251 return (NULL((void *)0));
252 memcpy(where, &kf, esize);
253 where += esize;
254 buflen -= esize;
255 n++;
256 }
257 if (n != nfiles) {
258 _kvm_err(kd, kd->program, "inconsistent nfiles");
259 return (NULL((void *)0));
260 }
261 *cnt = n;
262 return (kd->filebase);
263}
264
265static struct kinfo_file *
266kvm_deadfile_byid(kvm_t *kd, int op, int arg, size_t esize, int *cnt)
267{
268 size_t buflen;
269 struct nlist nl[4], *np;
270 int n = 0, matched = 0;
271 char *where;
272 struct kinfo_file kf;
273 struct file *fp, file;
274 struct filelist filehead;
275 struct filedesc0 filed0;
276#define filedfiled0.fd_fd filed0.fd_fd
277 struct processlist allprocess;
278 struct process *pr, process;
279 struct ucred ucred;
280 char *filebuf = NULL((void *)0);
281 int i, nfiles;
282
283 nl[0].n_name = "_filehead";
284 nl[1].n_name = "_numfiles";
285 nl[2].n_name = "_allprocess";
286 nl[3].n_name = 0;
287
288 if (kvm_nlist(kd, nl) != 0) {
289 for (np = nl; np->n_type != 0; ++np)
290 ;
291 _kvm_err(kd, kd->program,
292 "%s: no such symbol", np->n_name);
293 return (NULL((void *)0));
294 }
295 if (KREAD(kd, nl[0].n_value, &filehead)(kvm_read(kd, nl[0].n_value, (void *)(&filehead), sizeof(
*&filehead)) != sizeof(*&filehead))
) {
296 _kvm_err(kd, kd->program, "can't read filehead");
297 return (NULL((void *)0));
298 }
299 if (KREAD(kd, nl[1].n_value, &nfiles)(kvm_read(kd, nl[1].n_value, (void *)(&nfiles), sizeof(*&
nfiles)) != sizeof(*&nfiles))
) {
300 _kvm_err(kd, kd->program, "can't read nfiles");
301 return (NULL((void *)0));
302 }
303 if (KREAD(kd, nl[2].n_value, &allprocess)(kvm_read(kd, nl[2].n_value, (void *)(&allprocess), sizeof
(*&allprocess)) != sizeof(*&allprocess))
) {
304 _kvm_err(kd, kd->program, "can't read allprocess");
305 return (NULL((void *)0));
306 }
307 /* this may be more room than we need but counting is expensive */
308 where = _kvm_reallocarray(kd, kd->filebase, nfiles + 10, esize);
309 if (where == NULL((void *)0))
310 return (NULL((void *)0));
311
312 kd->filebase = (void *)where;
313 buflen = (nfiles + 10) * esize;
314
315 if (op != KERN_FILE_BYPID2 || arg <= 0)
316 matched = 1;
317
318 for (pr = LIST_FIRST(&allprocess)((&allprocess)->lh_first);
319 pr != NULL((void *)0);
320 pr = LIST_NEXT(&process, ps_list)((&process)->ps_list.le_next)) {
321 if (KREAD(kd, (u_long)pr, &process)(kvm_read(kd, (u_long)pr, (void *)(&process), sizeof(*&
process)) != sizeof(*&process))
) {
322 _kvm_err(kd, kd->program, "can't read process at %lx",
323 (u_long)pr);
324 goto cleanup;
325 }
326
327 /* skip system, exiting, embryonic and undead processes */
328 if (process.ps_flags & (PS_SYSTEM0x00010000 | PS_EMBRYO0x00020000 | PS_EXITING0x00000008))
329 continue;
330
331 if (op == KERN_FILE_BYPID2) {
332 /* check if this is the pid we are looking for */
333 if (arg > 0 && process.ps_pid != (pid_t)arg)
334 continue;
335 matched = 1;
336 }
337
338 if (KREAD(kd, (u_long)process.ps_ucred, &ucred)(kvm_read(kd, (u_long)process.ps_ucred, (void *)(&ucred),
sizeof(*&ucred)) != sizeof(*&ucred))
) {
339 _kvm_err(kd, kd->program, "can't read ucred at %lx",
340 (u_long)process.ps_ucred);
341 goto cleanup;
342 }
343 process.ps_ucred = &ucred;
344
345 if (op == KERN_FILE_BYUID3 && arg >= 0 &&
346 process.ps_ucred->cr_uid != (uid_t)arg) {
347 /* not the uid we are looking for */
348 continue;
349 }
350
351 if (KREAD(kd, (u_long)process.ps_fd, &filed0)(kvm_read(kd, (u_long)process.ps_fd, (void *)(&filed0), sizeof
(*&filed0)) != sizeof(*&filed0))
) {
352 _kvm_err(kd, kd->program, "can't read filedesc at %lx",
353 (u_long)process.ps_fd);
354 goto cleanup;
355 }
356 if ((char *)process.ps_fd + offsetof(struct filedesc0,fd_dfiles)__builtin_offsetof(struct filedesc0, fd_dfiles)
357 == (char *)filedfiled0.fd_fd.fd_ofiles) {
358 filedfiled0.fd_fd.fd_ofiles = filed0.fd_dfiles;
359 filedfiled0.fd_fd.fd_ofileflags = filed0.fd_dfileflags;
360 } else {
361 size_t fsize;
362 char *tmp = reallocarray(filebuf,
363 filedfiled0.fd_fd.fd_nfiles, OFILESIZE(sizeof(struct file *) + sizeof(char)));
364
365 fsize = filedfiled0.fd_fd.fd_nfiles * OFILESIZE(sizeof(struct file *) + sizeof(char));
366 if (tmp == NULL((void *)0)) {
367 _kvm_syserr(kd, kd->program, "realloc ofiles");
368 goto cleanup;
369 }
370 filebuf = tmp;
371 if (kvm_read(kd, (u_long)filedfiled0.fd_fd.fd_ofiles, filebuf,
372 fsize) != fsize) {
373 _kvm_err(kd, kd->program,
374 "can't read fd_ofiles");
375 goto cleanup;
376 }
377 filedfiled0.fd_fd.fd_ofiles = (void *)filebuf;
378 filedfiled0.fd_fd.fd_ofileflags = filebuf +
379 (filedfiled0.fd_fd.fd_nfiles * sizeof(struct file *));
380 }
381 process.ps_fd = &filedfiled0.fd_fd;
382
383 if (process.ps_textvp) {
384 if (buflen < esize)
385 goto done;
386 if (fill_file(kd, &kf, NULL((void *)0), 0, process.ps_textvp,
387 &process, KERN_FILE_TEXT-1, process.ps_pid) == -1)
388 goto cleanup;
389 memcpy(where, &kf, esize);
390 where += esize;
391 buflen -= esize;
392 n++;
393 }
394 if (filedfiled0.fd_fd.fd_cdir) {
395 if (buflen < esize)
396 goto done;
397 if (fill_file(kd, &kf, NULL((void *)0), 0, filedfiled0.fd_fd.fd_cdir,
398 &process, KERN_FILE_CDIR-2, process.ps_pid) == -1)
399 goto cleanup;
400 memcpy(where, &kf, esize);
401 where += esize;
402 buflen -= esize;
403 n++;
404 }
405 if (filedfiled0.fd_fd.fd_rdir) {
406 if (buflen < esize)
407 goto done;
408 if (fill_file(kd, &kf, NULL((void *)0), 0, filedfiled0.fd_fd.fd_rdir,
409 &process, KERN_FILE_RDIR-3, process.ps_pid) == -1)
410 goto cleanup;
411 memcpy(where, &kf, esize);
412 where += esize;
413 buflen -= esize;
414 n++;
415 }
416 if (process.ps_tracevp) {
417 if (buflen < esize)
418 goto done;
419 if (fill_file(kd, &kf, NULL((void *)0), 0, process.ps_tracevp,
420 &process, KERN_FILE_TRACE-4, process.ps_pid) == -1)
421 goto cleanup;
422 memcpy(where, &kf, esize);
423 where += esize;
424 buflen -= esize;
425 n++;
426 }
427
428 if (filedfiled0.fd_fd.fd_nfiles < 0 ||
429 filedfiled0.fd_fd.fd_lastfile >= filedfiled0.fd_fd.fd_nfiles ||
430 filedfiled0.fd_fd.fd_freefile > filedfiled0.fd_fd.fd_lastfile + 1) {
431 _kvm_err(kd, kd->program,
432 "filedesc corrupted at %lx for pid %d",
433 (u_long)process.ps_fd, process.ps_pid);
434 goto cleanup;
435 }
436
437 for (i = 0; i < filedfiled0.fd_fd.fd_nfiles; i++) {
438 if (buflen < esize)
439 goto done;
440 if ((fp = filedfiled0.fd_fd.fd_ofiles[i]) == NULL((void *)0))
441 continue;
442 if (KREAD(kd, (u_long)fp, &file)(kvm_read(kd, (u_long)fp, (void *)(&file), sizeof(*&file
)) != sizeof(*&file))
) {
443 _kvm_err(kd, kd->program, "can't read file");
444 goto cleanup;
445 }
446 if (fill_file(kd, &kf, &file, (u_long)fp, NULL((void *)0),
447 &process, i, process.ps_pid) == -1)
448 goto cleanup;
449 memcpy(where, &kf, esize);
450 where += esize;
451 buflen -= esize;
452 n++;
453 }
454 }
455 if (!matched) {
456 errno(*__errno()) = ESRCH3;
457 goto cleanup;
458 }
459done:
460 *cnt = n;
461 free(filebuf);
462 return (kd->filebase);
463cleanup:
464 free(filebuf);
465 return (NULL((void *)0));
466}
467
468static int
469fill_file(kvm_t *kd, struct kinfo_file *kf, struct file *fp, u_long fpaddr,
470 struct vnode *vp, struct process *pr, int fd, pid_t pid)
471{
472 struct ucred f_cred;
473
474 memset(kf, 0, sizeof(*kf));
475
476 kf->fd_fd = fd; /* might not really be an fd */
477
478 if (fp
22.1
'fp' is not equal to NULL
!= NULL((void *)0)) {
23
Taking true branch
479 /* Fill in f_cred */
480 if (KREAD(kd, (u_long)fp->f_cred, &f_cred)(kvm_read(kd, (u_long)fp->f_cred, (void *)(&f_cred), sizeof
(*&f_cred)) != sizeof(*&f_cred))
) {
24
Assuming the condition is false
25
Taking false branch
481 _kvm_err(kd, kd->program, "can't read f_cred");
482 return (-1);
483 }
484
485 kf->f_fileaddr = PTRTOINT64(fpaddr)((u_int64_t)(u_long)(fpaddr));
486 kf->f_flag = fp->f_flag;
487 kf->f_iflags = fp->f_iflags;
488 kf->f_type = fp->f_type;
489 kf->f_count = fp->f_count;
490 kf->f_ucred = PTRTOINT64(fp->f_cred)((u_int64_t)(u_long)(fp->f_cred));
491 kf->f_uid = f_cred.cr_uid;
492 kf->f_gid = f_cred.cr_gid;
493 kf->f_ops = PTRTOINT64(fp->f_ops)((u_int64_t)(u_long)(fp->f_ops));
494 kf->f_offset = fp->f_offset;
495 kf->f_data = PTRTOINT64(fp->f_data)((u_int64_t)(u_long)(fp->f_data));
496 kf->f_usecount = 0;
497
498 kf->f_rxfer = fp->f_rxfer;
499 kf->f_rwfer = fp->f_wxfer;
500 kf->f_seek = fp->f_seek;
501 kf->f_rbytes = fp->f_rbytes;
502 kf->f_wbytes = fp->f_wbytes;
503 } else if (vp != NULL((void *)0)) {
504 /* fake it */
505 kf->f_type = DTYPE_VNODE1;
506 kf->f_flag = FREAD0x0001;
507 if (fd == KERN_FILE_TRACE-4)
508 kf->f_flag |= FWRITE0x0002;
509 kf->f_data = PTRTOINT64(vp)((u_int64_t)(u_long)(vp));
510 }
511
512 /* information about the object associated with this file */
513 switch (kf->f_type) {
26
Control jumps to 'case 1:' at line 514
514 case DTYPE_VNODE1: {
515 struct vnode vbuf;
516
517 if (KREAD(kd, (u_long)(fp ? fp->f_data : vp), &vbuf)(kvm_read(kd, (u_long)(fp ? fp->f_data : vp), (void *)(&
vbuf), sizeof(*&vbuf)) != sizeof(*&vbuf))
) {
27
'?' condition is true
28
Assuming the condition is false
29
Taking false branch
518 _kvm_err(kd, kd->program, "can't read vnode");
519 return (-1);
520 }
521 vp = &vbuf;
522
523 kf->v_un = PTRTOINT64(vp->v_un.vu_socket)((u_int64_t)(u_long)(vp->v_un.vu_socket));
524 kf->v_type = vp->v_type;
525 kf->v_tag = vp->v_tag;
526 kf->v_flag = vp->v_flag;
527 kf->v_data = PTRTOINT64(vp->v_data)((u_int64_t)(u_long)(vp->v_data));
528 kf->v_mount = PTRTOINT64(vp->v_mount)((u_int64_t)(u_long)(vp->v_mount));
529
530 if (vp->v_mount != NULL((void *)0)) {
30
Assuming field 'v_mount' is equal to NULL
31
Taking false branch
531 struct mount mount;
532
533 if (KREAD(kd, (u_long)vp->v_mount, &mount)(kvm_read(kd, (u_long)vp->v_mount, (void *)(&mount), sizeof
(*&mount)) != sizeof(*&mount))
) {
534 _kvm_err(kd, kd->program, "can't read v_mount");
535 return (-1);
536 }
537
538 strlcpy(kf->f_mntonname, mount.mnt_stat.f_mntonname,
539 sizeof(kf->f_mntonname));
540 }
541
542 /* Fill in va_fsid, va_fileid, va_mode, va_size, va_rdev */
543 filestat(kd, kf, vp);
32
Calling 'filestat'
544 break;
545 }
546
547 case DTYPE_SOCKET2: {
548 struct socket sock;
549 struct sosplice ssp;
550 struct protosw protosw;
551 struct domain domain;
552
553 if (KREAD(kd, (u_long)fp->f_data, &sock)(kvm_read(kd, (u_long)fp->f_data, (void *)(&sock), sizeof
(*&sock)) != sizeof(*&sock))
) {
554 _kvm_err(kd, kd->program, "can't read socket");
555 return (-1);
556 }
557
558 kf->so_type = sock.so_type;
559 kf->so_state = sock.so_state;
560 kf->so_pcb = PTRTOINT64(sock.so_pcb)((u_int64_t)(u_long)(sock.so_pcb));
561 if (KREAD(kd, (u_long)sock.so_proto, &protosw)(kvm_read(kd, (u_long)sock.so_proto, (void *)(&protosw), sizeof
(*&protosw)) != sizeof(*&protosw))
) {
562 _kvm_err(kd, kd->program, "can't read protosw");
563 return (-1);
564 }
565 kf->so_protocol = protosw.pr_protocol;
566 if (KREAD(kd, (u_long)protosw.pr_domain, &domain)(kvm_read(kd, (u_long)protosw.pr_domain, (void *)(&domain
), sizeof(*&domain)) != sizeof(*&domain))
) {
567 _kvm_err(kd, kd->program, "can't read domain");
568 return (-1);
569 }
570 kf->so_family = domain.dom_family;
571 kf->so_rcv_cc = sock.so_rcv.sb_cc;
572 kf->so_snd_cc = sock.so_snd.sb_cc;
573 if (sock.so_sp) {
574 if (KREAD(kd, (u_long)sock.so_sp, &ssp)(kvm_read(kd, (u_long)sock.so_sp, (void *)(&ssp), sizeof(
*&ssp)) != sizeof(*&ssp))
) {
575 _kvm_err(kd, kd->program, "can't read splice");
576 return (-1);
577 }
578 if (ssp.ssp_socket) {
579 kf->so_splice = PTRTOINT64(ssp.ssp_socket)((u_int64_t)(u_long)(ssp.ssp_socket));
580 kf->so_splicelen = ssp.ssp_len;
581 } else if (ssp.ssp_soback) {
582 kf->so_splicelen = -1;
583 }
584 }
585 if (!sock.so_pcb)
586 break;
587 switch (kf->so_family) {
588 case AF_INET2: {
589 struct inpcb inpcb;
590
591 if (KREAD(kd, (u_long)sock.so_pcb, &inpcb)(kvm_read(kd, (u_long)sock.so_pcb, (void *)(&inpcb), sizeof
(*&inpcb)) != sizeof(*&inpcb))
) {
592 _kvm_err(kd, kd->program, "can't read inpcb");
593 return (-1);
594 }
595 kf->inp_ppcb = PTRTOINT64(inpcb.inp_ppcb)((u_int64_t)(u_long)(inpcb.inp_ppcb));
596 kf->inp_lport = inpcb.inp_lport;
597 kf->inp_laddru[0] = inpcb.inp_laddrinp_laddru.iau_a4u.inaddr.s_addr;
598 kf->inp_fport = inpcb.inp_fport;
599 kf->inp_faddru[0] = inpcb.inp_faddrinp_faddru.iau_a4u.inaddr.s_addr;
600 kf->inp_rtableid = inpcb.inp_rtableid;
601 if (sock.so_type == SOCK_RAW3)
602 kf->inp_proto = inpcb.inp_ipinp_hu.hu_ip.ip_p;
603 if (protosw.pr_protocol == IPPROTO_TCP6) {
604 struct tcpcb tcpcb;
605 if (KREAD(kd, (u_long)inpcb.inp_ppcb, &tcpcb)(kvm_read(kd, (u_long)inpcb.inp_ppcb, (void *)(&tcpcb), sizeof
(*&tcpcb)) != sizeof(*&tcpcb))
) {
606 _kvm_err(kd, kd->program,
607 "can't read tcpcb");
608 return (-1);
609 }
610 kf->t_rcv_wnd = tcpcb.rcv_wnd;
611 kf->t_snd_wnd = tcpcb.snd_wnd;
612 kf->t_snd_cwnd = tcpcb.snd_cwnd;
613 kf->t_state = tcpcb.t_state;
614 }
615 break;
616 }
617 case AF_INET624: {
618 struct inpcb inpcb;
619#define s6_addr32__u6_addr.__u6_addr32 __u6_addr.__u6_addr32
620
621 if (KREAD(kd, (u_long)sock.so_pcb, &inpcb)(kvm_read(kd, (u_long)sock.so_pcb, (void *)(&inpcb), sizeof
(*&inpcb)) != sizeof(*&inpcb))
) {
622 _kvm_err(kd, kd->program, "can't read inpcb");
623 return (-1);
624 }
625 kf->inp_ppcb = PTRTOINT64(inpcb.inp_ppcb)((u_int64_t)(u_long)(inpcb.inp_ppcb));
626 kf->inp_lport = inpcb.inp_lport;
627 kf->inp_laddru[0] = inpcb.inp_laddr6inp_laddru.iau_addr6.s6_addr32__u6_addr.__u6_addr32[0];
628 kf->inp_laddru[1] = inpcb.inp_laddr6inp_laddru.iau_addr6.s6_addr32__u6_addr.__u6_addr32[1];
629 kf->inp_laddru[2] = inpcb.inp_laddr6inp_laddru.iau_addr6.s6_addr32__u6_addr.__u6_addr32[2];
630 kf->inp_laddru[3] = inpcb.inp_laddr6inp_laddru.iau_addr6.s6_addr32__u6_addr.__u6_addr32[3];
631 kf->inp_fport = inpcb.inp_fport;
632 kf->inp_faddru[0] = inpcb.inp_laddr6inp_laddru.iau_addr6.s6_addr32__u6_addr.__u6_addr32[0];
633 kf->inp_faddru[1] = inpcb.inp_faddr6inp_faddru.iau_addr6.s6_addr32__u6_addr.__u6_addr32[1];
634 kf->inp_faddru[2] = inpcb.inp_faddr6inp_faddru.iau_addr6.s6_addr32__u6_addr.__u6_addr32[2];
635 kf->inp_faddru[3] = inpcb.inp_faddr6inp_faddru.iau_addr6.s6_addr32__u6_addr.__u6_addr32[3];
636 kf->inp_rtableid = inpcb.inp_rtableid;
637 if (sock.so_type == SOCK_RAW3)
638 kf->inp_proto = inpcb.inp_ipv6inp_hu.hu_ipv6.ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt;
639 if (protosw.pr_protocol == IPPROTO_TCP6) {
640 struct tcpcb tcpcb;
641 if (KREAD(kd, (u_long)inpcb.inp_ppcb, &tcpcb)(kvm_read(kd, (u_long)inpcb.inp_ppcb, (void *)(&tcpcb), sizeof
(*&tcpcb)) != sizeof(*&tcpcb))
) {
642 _kvm_err(kd, kd->program,
643 "can't read tcpcb");
644 return (-1);
645 }
646 kf->t_rcv_wnd = tcpcb.rcv_wnd;
647 kf->t_snd_wnd = tcpcb.snd_wnd;
648 kf->t_snd_cwnd = tcpcb.snd_cwnd;
649 kf->t_state = tcpcb.t_state;
650 }
651 break;
652 }
653 case AF_UNIX1: {
654 struct unpcb unpcb;
655
656 if (KREAD(kd, (u_long)sock.so_pcb, &unpcb)(kvm_read(kd, (u_long)sock.so_pcb, (void *)(&unpcb), sizeof
(*&unpcb)) != sizeof(*&unpcb))
) {
657 _kvm_err(kd, kd->program, "can't read unpcb");
658 return (-1);
659 }
660 kf->f_msgcount = unpcb.unp_msgcount;
661 kf->unp_conn = PTRTOINT64(unpcb.unp_conn)((u_int64_t)(u_long)(unpcb.unp_conn));
662 kf->unp_refs = PTRTOINT64(((u_int64_t)(u_long)(((&unpcb.unp_refs)->slh_first)))
663 SLIST_FIRST(&unpcb.unp_refs))((u_int64_t)(u_long)(((&unpcb.unp_refs)->slh_first)));
664 kf->unp_nextref = PTRTOINT64(((u_int64_t)(u_long)(((&unpcb)->unp_nextref.sle_next))
)
665 SLIST_NEXT(&unpcb, unp_nextref))((u_int64_t)(u_long)(((&unpcb)->unp_nextref.sle_next))
)
;
666 kf->v_un = PTRTOINT64(unpcb.unp_vnode)((u_int64_t)(u_long)(unpcb.unp_vnode));
667 if (unpcb.unp_addr != NULL((void *)0)) {
668 struct mbuf mb;
669 struct sockaddr_un un;
670
671 if (KREAD(kd, (u_long)unpcb.unp_addr, &mb)(kvm_read(kd, (u_long)unpcb.unp_addr, (void *)(&mb), sizeof
(*&mb)) != sizeof(*&mb))
) {
672 _kvm_err(kd, kd->program,
673 "can't read sockaddr_un mbuf");
674 return (-1);
675 }
676 if (KREAD(kd, (u_long)mb.m_data, &un)(kvm_read(kd, (u_long)mb.m_hdr.mh_data, (void *)(&un), sizeof
(*&un)) != sizeof(*&un))
) {
677 _kvm_err(kd, kd->program,
678 "can't read sockaddr_un");
679 return (-1);
680 }
681
682 kf->unp_addr = PTRTOINT64(unpcb.unp_addr)((u_int64_t)(u_long)(unpcb.unp_addr));
683 memcpy(kf->unp_path, un.sun_path, un.sun_len
684 - offsetof(struct sockaddr_un,sun_path)__builtin_offsetof(struct sockaddr_un, sun_path));
685 }
686
687 break;
688 }
689 }
690 break;
691 }
692
693 case DTYPE_PIPE3: {
694 struct pipe pipe;
695
696 if (KREAD(kd, (u_long)fp->f_data, &pipe)(kvm_read(kd, (u_long)fp->f_data, (void *)(&pipe), sizeof
(*&pipe)) != sizeof(*&pipe))
) {
697 _kvm_err(kd, kd->program, "can't read pipe");
698 return (-1);
699 }
700 kf->pipe_peer = PTRTOINT64(pipe.pipe_peer)((u_int64_t)(u_long)(pipe.pipe_peer));
701 kf->pipe_state = pipe.pipe_state;
702 break;
703 }
704
705 case DTYPE_KQUEUE4: {
706 struct kqueue kqi;
707
708 if (KREAD(kd, (u_long)fp->f_data, &kqi)(kvm_read(kd, (u_long)fp->f_data, (void *)(&kqi), sizeof
(*&kqi)) != sizeof(*&kqi))
) {
709 _kvm_err(kd, kd->program, "can't read kqi");
710 return (-1);
711 }
712 kf->kq_count = kqi.kq_count;
713 kf->kq_state = kqi.kq_state;
714 break;
715 }
716 }
717
718 /* per-process information for KERN_FILE_BY[PU]ID */
719 if (pr != NULL((void *)0)) {
720 kf->p_pid = pid;
721 kf->p_uid = pr->ps_ucred->cr_uid;
722 kf->p_gid = pr->ps_ucred->cr_gid;
723 kf->p_tid = -1;
724 strlcpy(kf->p_comm, pr->ps_comm, sizeof(kf->p_comm));
725 if (pr->ps_fd != NULL((void *)0))
726 kf->fd_ofileflags = pr->ps_fd->fd_ofileflags[fd];
727 }
728
729 return (0);
730}
731
732mode_t
733_kvm_getftype(enum vtype v_type)
734{
735 mode_t ftype = 0;
736
737 switch (v_type) {
738 case VREG:
739 ftype = S_IFREG0100000;
740 break;
741 case VDIR:
742 ftype = S_IFDIR0040000;
743 break;
744 case VBLK:
745 ftype = S_IFBLK0060000;
746 break;
747 case VCHR:
748 ftype = S_IFCHR0020000;
749 break;
750 case VLNK:
751 ftype = S_IFLNK0120000;
752 break;
753 case VSOCK:
754 ftype = S_IFSOCK0140000;
755 break;
756 case VFIFO:
757 ftype = S_IFIFO0010000;
758 break;
759 case VNON:
760 case VBAD:
761 break;
762 }
763
764 return (ftype);
765}
766
767static int
768ufs_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
769{
770 struct inode inode;
771 struct ufs1_dinode di1;
772
773 if (KREAD(kd, (u_long)VTOI(vp), &inode)(kvm_read(kd, (u_long)((struct inode *)(vp)->v_data), (void
*)(&inode), sizeof(*&inode)) != sizeof(*&inode))
) {
774 _kvm_err(kd, kd->program, "can't read inode at %p", VTOI(vp)((struct inode *)(vp)->v_data));
775 return (-1);
776 }
777
778 if (KREAD(kd, (u_long)inode.i_din1, &di1)(kvm_read(kd, (u_long)inode.dinode_u.ffs1_din, (void *)(&
di1), sizeof(*&di1)) != sizeof(*&di1))
) {
779 _kvm_err(kd, kd->program, "can't read dinode at %p",
780 inode.i_din1dinode_u.ffs1_din);
781 return (-1);
782 }
783
784 inode.i_din1dinode_u.ffs1_din = &di1;
785
786 kf->va_fsid = inode.i_dev & 0xffff;
787 kf->va_fileid = (long)inode.i_number;
788 kf->va_mode = inode.i_ffs1_modedinode_u.ffs1_din->di_mode;
789 kf->va_size = inode.i_ffs1_sizedinode_u.ffs1_din->di_size;
790 kf->va_rdev = inode.i_ffs1_rdevdinode_u.ffs1_din->di_db[0];
791 kf->va_nlink = inode.i_ffs1_nlinkdinode_u.ffs1_din->di_nlink;
792
793 return (0);
794}
795
796static int
797ext2fs_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
798{
799 struct inode inode;
800 struct ext2fs_dinode e2di;
801
802 if (KREAD(kd, (u_long)VTOI(vp), &inode)(kvm_read(kd, (u_long)((struct inode *)(vp)->v_data), (void
*)(&inode), sizeof(*&inode)) != sizeof(*&inode))
) {
803 _kvm_err(kd, kd->program, "can't read inode at %p", VTOI(vp)((struct inode *)(vp)->v_data));
804 return (-1);
805 }
806
807 if (KREAD(kd, (u_long)inode.i_e2din, &e2di)(kvm_read(kd, (u_long)inode.dinode_u.e2fs_din, (void *)(&
e2di), sizeof(*&e2di)) != sizeof(*&e2di))
) {
808 _kvm_err(kd, kd->program, "can't read dinode at %p",
809 inode.i_e2dindinode_u.e2fs_din);
810 return (-1);
811 }
812
813 inode.i_e2dindinode_u.e2fs_din = &e2di;
814
815 kf->va_fsid = inode.i_dev & 0xffff;
816 kf->va_fileid = (long)inode.i_number;
817 kf->va_mode = inode.i_e2fs_modedinode_u.e2fs_din->e2di_mode;
818 kf->va_size = inode.i_e2fs_sizedinode_u.e2fs_din->e2di_size;
819 kf->va_rdev = 0; /* XXX */
820 kf->va_nlink = inode.i_e2fs_nlinkdinode_u.e2fs_din->e2di_nlink;
821
822 return (0);
823}
824
825static int
826msdos_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
827{
828 struct denode de;
829 struct msdosfsmount mp;
830
831 if (KREAD(kd, (u_long)VTODE(vp), &de)(kvm_read(kd, (u_long)((struct denode *)(vp)->v_data), (void
*)(&de), sizeof(*&de)) != sizeof(*&de))
) {
832 _kvm_err(kd, kd->program, "can't read denode at %p", VTODE(vp)((struct denode *)(vp)->v_data));
833 return (-1);
834 }
835 if (KREAD(kd, (u_long)de.de_pmp, &mp)(kvm_read(kd, (u_long)de.de_pmp, (void *)(&mp), sizeof(*&
mp)) != sizeof(*&mp))
) {
836 _kvm_err(kd, kd->program, "can't read mount struct at %p",
837 de.de_pmp);
838 return (-1);
839 }
840
841 kf->va_fsid = de.de_dev & 0xffff;
842 kf->va_fileid = 0; /* XXX see msdosfs_vptofh() for more info */
843 kf->va_mode = (mp.pm_mask & 0777) | _kvm_getftype(vp->v_type);
844 kf->va_size = de.de_FileSize;
845 kf->va_rdev = 0; /* msdosfs doesn't support device files */
846 kf->va_nlink = 1;
847
848 return (0);
849}
850
851static int
852nfs_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
853{
854 struct nfsnode nfsnode;
855
856 if (KREAD(kd, (u_long)VTONFS(vp), &nfsnode)(kvm_read(kd, (u_long)((struct nfsnode *)(vp)->v_data), (void
*)(&nfsnode), sizeof(*&nfsnode)) != sizeof(*&nfsnode
))
) {
857 _kvm_err(kd, kd->program, "can't read nfsnode at %p",
858 VTONFS(vp)((struct nfsnode *)(vp)->v_data));
859 return (-1);
860 }
861 kf->va_fsid = nfsnode.n_vattr.va_fsid;
862 kf->va_fileid = nfsnode.n_vattr.va_fileid;
863 kf->va_size = nfsnode.n_size;
864 kf->va_rdev = nfsnode.n_vattr.va_rdev;
865 kf->va_mode = (mode_t)nfsnode.n_vattr.va_mode | _kvm_getftype(vp->v_type);
866 kf->va_nlink = nfsnode.n_vattr.va_nlink;
867
868 return (0);
869}
870
871static int
872spec_filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
873{
874 struct specinfo specinfo;
875 struct vnode parent;
876
877 if (KREAD(kd, (u_long)vp->v_specinfo, &specinfo)(kvm_read(kd, (u_long)vp->v_un.vu_specinfo, (void *)(&
specinfo), sizeof(*&specinfo)) != sizeof(*&specinfo))
) {
40
Assuming the condition is false
41
Taking false branch
878 _kvm_err(kd, kd->program, "can't read specinfo at %p",
879 vp->v_specinfov_un.vu_specinfo);
880 return (-1);
881 }
882
883 vp->v_specinfov_un.vu_specinfo = &specinfo;
884
885 if (KREAD(kd, (u_long)vp->v_specparent, &parent)(kvm_read(kd, (u_long)vp->v_un.vu_specinfo->si_ci.ci_parent
, (void *)(&parent), sizeof(*&parent)) != sizeof(*&
parent))
) {
42
Assuming the condition is true
43
Taking true branch
886 _kvm_err(kd, kd->program, "can't read parent vnode at %p",
887 vp->v_specparentv_un.vu_specinfo->si_ci.ci_parent);
888 return (-1);
44
Address of stack memory associated with local variable 'specinfo' is still referred to by the stack variable 'vbuf' upon returning to the caller. This will be a dangling reference
889 }
890
891 if (ufs_filestat(kd, kf, vp))
892 return (-1);
893
894 return (0);
895}
896
897static int
898filestat(kvm_t *kd, struct kinfo_file *kf, struct vnode *vp)
899{
900 int ret = 0;
901
902 if (vp->v_type != VNON && vp->v_type != VBAD) {
33
Assuming field 'v_type' is not equal to VNON
34
Assuming field 'v_type' is not equal to VBAD
35
Taking true branch
903 switch (vp->v_tag) {
36
Control jumps to 'case VT_NON:' at line 926
904 case VT_UFS:
905 case VT_MFS:
906 ret = ufs_filestat(kd, kf, vp);
907 break;
908 case VT_NFS:
909 ret = nfs_filestat(kd, kf, vp);
910 break;
911 case VT_EXT2FS:
912 ret = ext2fs_filestat(kd, kf, vp);
913 break;
914 case VT_ISOFS:
915 ret = _kvm_stat_cd9660(kd, kf, vp);
916 break;
917 case VT_MSDOSFS:
918 ret = msdos_filestat(kd, kf, vp);
919 break;
920 case VT_UDF:
921 ret = _kvm_stat_udf(kd, kf, vp);
922 break;
923 case VT_NTFS:
924 ret = _kvm_stat_ntfs(kd, kf, vp);
925 break;
926 case VT_NON:
927 if (vp->v_flag & VCLONE0x8000)
37
Assuming the condition is true
38
Taking true branch
928 ret = spec_filestat(kd, kf, vp);
39
Calling 'spec_filestat'
929 break;
930 default:
931 ret = -1;
932 break;
933 }
934 }
935 return (ret);
936}