Bug Summary

File:src/usr.bin/fstat/fstat.c
Warning:line 620, column 10
Passed-by-value struct argument contains uninitialized data (e.g., field: 'data')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name fstat.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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/usr.bin/fstat/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/fstat/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/fstat/fstat.c
1/* $OpenBSD: fstat.c,v 1.102 2021/07/17 20:46:02 kn 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) 1988, 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#include <sys/types.h>
49#include <sys/queue.h>
50#include <sys/mount.h>
51#include <sys/stat.h>
52#include <sys/vnode.h>
53#include <sys/socket.h>
54#include <sys/socketvar.h>
55#include <sys/eventvar.h>
56#include <sys/sysctl.h>
57#include <sys/filedesc.h>
58#define _KERNEL /* for DTYPE_* */
59#include <sys/file.h>
60#undef _KERNEL
61
62#include <net/route.h>
63#include <netinet/in.h>
64
65#include <netdb.h>
66#include <arpa/inet.h>
67
68#include <sys/pipe.h>
69
70#include <ctype.h>
71#include <errno(*__errno()).h>
72#include <fcntl.h>
73#include <kvm.h>
74#include <limits.h>
75#include <nlist.h>
76#include <pwd.h>
77#include <search.h>
78#include <signal.h>
79#include <stdio.h>
80#include <stdint.h>
81#include <stdlib.h>
82#include <string.h>
83#include <unistd.h>
84#include <err.h>
85
86#include "fstat.h"
87
88#define MAXIMUM(a, b)(((a) > (b)) ? (a) : (b)) (((a) > (b)) ? (a) : (b))
89
90struct fstat_filter {
91 int what;
92 int arg;
93};
94
95struct fileargs fileargs = SLIST_HEAD_INITIALIZER(fileargs){ ((void *)0) };
96
97int fsflg; /* show files on same filesystem as file(s) argument */
98int uflg; /* show files open by a particular (effective) user */
99int checkfile; /* true if restricting to particular files or filesystems */
100int nflg; /* (numerical) display f.s. and rdev as dev_t */
101int oflg; /* display file offset */
102int sflg; /* display file xfer/bytes counters */
103int vflg; /* display errors in locating kernel data objects etc... */
104int cflg; /* fuser only */
105
106int fuser; /* 1 if we are fuser, 0 if we are fstat */
107int signo; /* signal to send (fuser only) */
108
109int nfilter = 0; /* How many uid/pid filters are in place */
110struct fstat_filter *filter = NULL((void *)0); /* An array of uid/pid filters */
111
112kvm_t *kd;
113uid_t uid;
114
115void fstat_dofile(struct kinfo_file *);
116void fstat_header(void);
117void getinetproto(int);
118__dead__attribute__((__noreturn__)) void usage(void);
119int getfname(char *);
120void kqueuetrans(struct kinfo_file *);
121void pipetrans(struct kinfo_file *);
122struct kinfo_file *splice_find(char, u_int64_t);
123void splice_insert(char, u_int64_t, struct kinfo_file *);
124void find_splices(struct kinfo_file *, int);
125void print_inet_details(struct kinfo_file *);
126void print_inet6_details(struct kinfo_file *);
127void print_sock_details(struct kinfo_file *);
128void socktrans(struct kinfo_file *);
129void vtrans(struct kinfo_file *);
130const char *inet6_addrstr(struct in6_addr *);
131int signame_to_signum(char *);
132void hide(void *p);
133
134int hideroot;
135
136void
137hide(void *p)
138{
139 printf("%p", hideroot ? NULL((void *)0) : p);
140}
141
142int
143main(int argc, char *argv[])
144{
145 struct kinfo_file *kf, *kflast;
146 int ch;
147 char *memf, *nlistf, *optstr;
148 char buf[_POSIX2_LINE_MAX2048];
149 const char *errstr;
150 int cnt, flags;
151
152 hideroot = getuid();
153
154 nlistf = memf = NULL((void *)0);
155 oflg = 0;
156
157 /* are we fstat(1) or fuser(1)? */
158 if (strcmp(__progname, "fuser") == 0) {
1
Assuming the condition is false
2
Taking false branch
159 fuser = 1;
160 optstr = "cfks:uM:N:";
161 } else {
162 fuser = 0;
163 optstr = "fnop:su:vN:M:";
164 }
165
166 /*
167 * fuser and fstat share three flags: -f, -s and -u. In both cases
168 * -f is a boolean, but for -u fstat wants an argument while fuser
169 * does not and for -s fuser wants an argument whereas fstat does not.
170 */
171 while ((ch = getopt(argc, argv, optstr)) != -1)
3
Assuming the condition is false
4
Loop condition is false. Execution continues on line 254
172 switch ((char)ch) {
173 case 'c':
174 if (fsflg)
175 usage();
176 cflg = 1;
177 break;
178 case 'f':
179 if (cflg)
180 usage();
181 fsflg = 1;
182 break;
183 case 'k':
184 sflg = 1;
185 signo = SIGKILL9;
186 break;
187 case 'M':
188 memf = optarg;
189 break;
190 case 'N':
191 nlistf = optarg;
192 break;
193 case 'n':
194 nflg = 1;
195 break;
196 case 'o':
197 oflg = 1;
198 break;
199 case 'p':
200 if ((filter = recallocarray(filter, nfilter, nfilter + 1,
201 sizeof(*filter))) == NULL((void *)0))
202 err(1, NULL((void *)0));
203 filter[nfilter].arg = strtonum(optarg, 0, INT_MAX2147483647,
204 &errstr);
205 if (errstr != NULL((void *)0)) {
206 warnx("-p requires a process id, %s: %s",
207 errstr, optarg);
208 usage();
209 }
210 filter[nfilter].what = KERN_FILE_BYPID2;
211 nfilter++;
212 break;
213 case 's':
214 sflg = 1;
215 if (fuser) {
216 signo = signame_to_signum(optarg);
217 if (signo == -1) {
218 warnx("invalid signal %s", optarg);
219 usage();
220 }
221 }
222 break;
223 case 'u':
224 uflg = 1;
225 if (!fuser) {
226 uid_t uid;
227
228 if (uid_from_user(optarg, &uid) == -1) {
229 uid = strtonum(optarg, 0, UID_MAX(2147483647 *2U +1U),
230 &errstr);
231 if (errstr != NULL((void *)0)) {
232 errx(1, "%s: unknown uid",
233 optarg);
234 }
235 }
236 if ((filter = recallocarray(filter, nfilter,
237 nfilter + 1, sizeof(*filter))) == NULL((void *)0))
238 err(1, NULL((void *)0));
239 filter[nfilter].arg = uid;
240 filter[nfilter].what = KERN_FILE_BYUID3;
241 nfilter++;
242 }
243 break;
244 case 'v':
245 vflg = 1;
246 break;
247 default:
248 usage();
249 }
250
251 /*
252 * get the uid, for oflg and sflg
253 */
254 uid = getuid();
255
256 /*
257 * Use sysctl unless inspecting an alternate kernel.
258 */
259 if (nlistf
4.1
'nlistf' is equal to NULL
== NULL((void *)0) || memf == NULL((void *)0))
260 flags = KVM_NO_FILES0x80000000;
261 else
262 flags = O_RDONLY0x0000;
263
264 if ((kd = kvm_openfiles(nlistf, memf, NULL((void *)0), flags, buf)) == NULL((void *)0))
5
Assuming the condition is false
6
Taking false branch
265 errx(1, "%s", buf);
266
267 if (*(argv += optind)) {
7
Assuming the condition is false
8
Taking false branch
268 for (; *argv; ++argv) {
269 if (getfname(*argv))
270 checkfile = 1;
271 }
272 /* file(s) specified, but none accessible */
273 if (!checkfile)
274 exit(1);
275 } else if (fuser
8.1
'fuser' is 0
)
9
Taking false branch
276 usage();
277
278 if (!fuser
9.1
'fuser' is 0
&& fsflg && !checkfile) {
10
Assuming 'fsflg' is 0
279 /* fstat -f with no files means use wd */
280 if (getfname(".") == 0)
281 exit(1);
282 checkfile = 1;
283 }
284
285 if (nfilter
10.1
'nfilter' is not equal to 1
== 1) {
11
Taking false branch
286 if ((kf = kvm_getfiles(kd, filter[0].what, filter[0].arg,
287 sizeof(*kf), &cnt)) == NULL((void *)0))
288 errx(1, "%s", kvm_geterr(kd));
289 } else {
290 if ((kf = kvm_getfiles(kd, KERN_FILE_BYPID2, -1, sizeof(*kf),
12
Assuming the condition is false
13
Taking false branch
291 &cnt)) == NULL((void *)0))
292 errx(1, "%s", kvm_geterr(kd));
293 }
294
295 if (fuser
13.1
'fuser' is 0
) {
14
Taking false branch
296 /*
297 * fuser
298 * uflg: need "getpw"
299 * sflg: need "proc" (might call kill(2))
300 */
301 if (uflg && sflg) {
302 if (pledge("stdio rpath getpw proc", NULL((void *)0)) == -1)
303 err(1, "pledge");
304 } else if (uflg) {
305 if (pledge("stdio rpath getpw", NULL((void *)0)) == -1)
306 err(1, "pledge");
307 } else if (sflg) {
308 if (pledge("stdio rpath proc", NULL((void *)0)) == -1)
309 err(1, "pledge");
310 } else {
311 if (pledge("stdio rpath", NULL((void *)0)) == -1)
312 err(1, "pledge");
313 }
314 } else {
315 /* fstat */
316 if (pledge("stdio rpath getpw", NULL((void *)0)) == -1)
15
Assuming the condition is false
16
Taking false branch
317 err(1, "pledge");
318 }
319
320 find_splices(kf, cnt);
321 if (!fuser
16.1
'fuser' is 0
)
17
Taking true branch
322 fstat_header();
323 for (kflast = &kf[cnt]; kf < kflast; ++kf) {
18
Loop condition is true. Entering loop body
324 if (fuser
18.1
'fuser' is 0
)
19
Taking false branch
325 fuser_check(kf);
326 else
327 fstat_dofile(kf);
20
Calling 'fstat_dofile'
328 }
329 if (fuser)
330 fuser_run();
331
332 exit(0);
333}
334
335void
336fstat_header(void)
337{
338 if (nflg)
339 printf("%s",
340"USER CMD PID FD DEV INUM MODE R/W SZ|DV");
341 else
342 printf("%s",
343"USER CMD PID FD MOUNT INUM MODE R/W SZ|DV");
344 if (oflg)
345 printf("%s", ":OFFSET ");
346 if (checkfile && fsflg == 0)
347 printf(" NAME");
348 if (sflg)
349 printf(" XFERS KBYTES");
350 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
351}
352
353const char *Uname, *Comm;
354uid_t *procuid;
355pid_t Pid;
356
357#define PREFIX(i)do { printf("%-8.8s %-10s %5ld", Uname, Comm, (long)Pid); switch
(i) { case -1: printf(" text"); break; case -2: printf(" wd"
); break; case -3: printf(" root"); break; case -4: printf(" tr"
); break; default: printf(" %4d", i); break; } } while (0)
do { \
358 printf("%-8.8s %-10s %5ld", Uname, Comm, (long)Pid); \
359 switch (i) { \
360 case KERN_FILE_TEXT-1: \
361 printf(" text"); \
362 break; \
363 case KERN_FILE_CDIR-2: \
364 printf(" wd"); \
365 break; \
366 case KERN_FILE_RDIR-3: \
367 printf(" root"); \
368 break; \
369 case KERN_FILE_TRACE-4: \
370 printf(" tr"); \
371 break; \
372 default: \
373 printf(" %4d", i); \
374 break; \
375 } \
376} while (0)
377
378/*
379 * print open files attributed to this process
380 */
381void
382fstat_dofile(struct kinfo_file *kf)
383{
384 int i;
385
386 Uname = user_from_uid(kf->p_uid, 0);
387 procuid = &kf->p_uid;
388 Pid = kf->p_pid;
389 Comm = kf->p_comm;
390
391 for (i = 0; i < nfilter; i++) {
21
Loop condition is false. Execution continues on line 399
392 if (filter[i].what == KERN_FILE_BYPID2) {
393 if (filter[i].arg == Pid)
394 break;
395 } else if (filter[i].arg == *procuid) {
396 break;
397 }
398 }
399 if (i
21.1
'i' is equal to 'nfilter'
== nfilter && nfilter
21.2
'nfilter' is equal to 0
!= 0)
22
Taking false branch
400 return;
401
402 switch (kf->f_type) {
23
Control jumps to 'case 2:' at line 406
403 case DTYPE_VNODE1:
404 vtrans(kf);
405 break;
406 case DTYPE_SOCKET2:
407 socktrans(kf);
24
Calling 'socktrans'
408 break;
409 case DTYPE_PIPE3:
410 if (checkfile == 0)
411 pipetrans(kf);
412 break;
413 case DTYPE_KQUEUE4:
414 if (checkfile == 0)
415 kqueuetrans(kf);
416 break;
417 default:
418 if (vflg) {
419 warnx("unknown file type %d for file %d of pid %ld",
420 kf->f_type, kf->fd_fd, (long)Pid);
421 }
422 break;
423 }
424}
425
426void
427vtrans(struct kinfo_file *kf)
428{
429 const char *badtype = NULL((void *)0);
430 char rwep[5], mode[12];
431 char *filename = NULL((void *)0);
432
433 if (kf->v_type == VNON)
434 badtype = "none";
435 else if (kf->v_type == VBAD)
436 badtype = "bad";
437 else if (kf->v_tag == VT_NON && !(kf->v_flag & VCLONE0x8000))
438 badtype = "none"; /* not a clone */
439
440 if (checkfile) {
441 int fsmatch = 0;
442 struct filearg *fa;
443
444 if (badtype)
445 return;
446 SLIST_FOREACH(fa, &fileargs, next)for((fa) = ((&fileargs)->slh_first); (fa) != ((void *)
0); (fa) = ((fa)->next.sle_next))
{
447 if (fa->dev == kf->va_fsid) {
448 fsmatch = 1;
449 if (fa->ino == kf->va_fileid) {
450 filename = fa->name;
451 break;
452 }
453 }
454 }
455 if (fsmatch == 0 || (filename == NULL((void *)0) && fsflg == 0))
456 return;
457 }
458 PREFIX(kf->fd_fd)do { printf("%-8.8s %-10s %5ld", Uname, Comm, (long)Pid); switch
(kf->fd_fd) { case -1: printf(" text"); break; case -2: printf
(" wd"); break; case -3: printf(" root"); break; case -4: printf
(" tr"); break; default: printf(" %4d", kf->fd_fd); break
; } } while (0)
;
459 if (badtype) {
460 (void)printf(" - - %10s -\n", badtype);
461 return;
462 }
463
464 if (nflg)
465 (void)printf(" %2lu,%-2lu", (long)major(kf->va_fsid)(((unsigned)(kf->va_fsid) >> 8) & 0xff),
466 (long)minor(kf->va_fsid)((unsigned)((kf->va_fsid) & 0xff) | (((kf->va_fsid)
& 0xffff0000) >> 8))
);
467 else if (!(kf->v_flag & VCLONE0x8000))
468 (void)printf(" %-8s", kf->f_mntonname);
469 else
470 (void)printf(" clone ");
471 if (nflg)
472 (void)snprintf(mode, sizeof(mode), "%o", kf->va_mode);
473 else
474 strmode(kf->va_mode, mode);
475 printf(" %8llu%s %11s", kf->va_fileid,
476 kf->va_nlink == 0 ? "*" : " ",
477 mode);
478 rwep[0] = '\0';
479 if (kf->f_flag & FREAD0x0001)
480 strlcat(rwep, "r", sizeof rwep);
481 if (kf->f_flag & FWRITE0x0002)
482 strlcat(rwep, "w", sizeof rwep);
483 if (kf->fd_ofileflags & UF_EXCLOSE0x01)
484 strlcat(rwep, "e", sizeof rwep);
485 if (kf->fd_ofileflags & UF_PLEDGED0x02)
486 strlcat(rwep, "p", sizeof rwep);
487 printf(" %4s", rwep);
488 switch (kf->v_type) {
489 case VBLK:
490 case VCHR: {
491 char *name;
492
493 if (nflg || ((name = devname(kf->va_rdev,
494 kf->v_type == VCHR ? S_IFCHR0020000 : S_IFBLK0060000)) == NULL((void *)0)))
495 printf(" %2u,%-3u", major(kf->va_rdev)(((unsigned)(kf->va_rdev) >> 8) & 0xff), minor(kf->va_rdev)((unsigned)((kf->va_rdev) & 0xff) | (((kf->va_rdev)
& 0xffff0000) >> 8))
);
496 else
497 printf(" %7s", name);
498 if (oflg)
499 printf(" ");
500 break;
501 }
502 default:
503 printf(" %8llu", kf->va_size);
504 if (oflg) {
505 if (uid == 0 || uid == *procuid)
506 printf(":%-8llu", kf->f_offset);
507 else
508 printf(":%-8s", "*");
509 }
510 }
511 if (sflg) {
512 if (uid == 0 || uid == *procuid) {
513 printf(" %8llu %8llu",
514 (kf->f_rxfer + kf->f_rwfer),
515 (kf->f_rbytes + kf->f_wbytes) / 1024);
516 } else {
517 printf(" %8s %8s", "*", "*");
518 }
519 }
520 if (filename && !fsflg)
521 printf(" %s", filename);
522 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
523}
524
525void
526pipetrans(struct kinfo_file *kf)
527{
528 void *maxaddr;
529
530 PREFIX(kf->fd_fd)do { printf("%-8.8s %-10s %5ld", Uname, Comm, (long)Pid); switch
(kf->fd_fd) { case -1: printf(" text"); break; case -2: printf
(" wd"); break; case -3: printf(" root"); break; case -4: printf
(" tr"); break; default: printf(" %4d", kf->fd_fd); break
; } } while (0)
;
531
532 printf(" ");
533
534 /*
535 * We don't have enough space to fit both peer and own address, so
536 * we select the higher address so both ends of the pipe have the
537 * same visible addr. (it's the higher address because when the other
538 * end closes, it becomes 0)
539 */
540 maxaddr = (void *)(uintptr_t)MAXIMUM(kf->f_data, kf->pipe_peer)(((kf->f_data) > (kf->pipe_peer)) ? (kf->f_data) :
(kf->pipe_peer))
;
541
542 printf("pipe ");
543 hide(maxaddr);
544 printf(" state: %s%s%s",
545 (kf->pipe_state & PIPE_WANTR0x008) ? "R" : "",
546 (kf->pipe_state & PIPE_WANTW0x010) ? "W" : "",
547 (kf->pipe_state & PIPE_EOF0x080) ? "E" : "");
548 if (sflg)
549 printf("\t%8llu %8llu",
550 (kf->f_rxfer + kf->f_rwfer),
551 (kf->f_rbytes + kf->f_wbytes) / 1024);
552 printf("\n");
553 return;
554}
555
556void
557kqueuetrans(struct kinfo_file *kf)
558{
559 PREFIX(kf->fd_fd)do { printf("%-8.8s %-10s %5ld", Uname, Comm, (long)Pid); switch
(kf->fd_fd) { case -1: printf(" text"); break; case -2: printf
(" wd"); break; case -3: printf(" root"); break; case -4: printf
(" tr"); break; default: printf(" %4d", kf->fd_fd); break
; } } while (0)
;
560
561 printf(" ");
562
563 printf("kqueue ");
564 hide((void *)(uintptr_t)kf->f_data);
565 printf(" %d state: %s%s\n",
566 kf->kq_count,
567 (kf->kq_state & KQ_SEL0x01) ? "S" : "",
568 (kf->kq_state & KQ_SLEEP0x02) ? "W" : "");
569 return;
570}
571
572const char *
573inet6_addrstr(struct in6_addr *p)
574{
575 struct sockaddr_in6 sin6;
576 static char hbuf[NI_MAXHOST256];
577 const int niflags = NI_NUMERICHOST1;
578
579 memset(&sin6, 0, sizeof(sin6));
580 sin6.sin6_family = AF_INET624;
581 sin6.sin6_len = sizeof(struct sockaddr_in6);
582 sin6.sin6_addr = *p;
583 if (IN6_IS_ADDR_LINKLOCAL(p)(((p)->__u6_addr.__u6_addr8[0] == 0xfe) && (((p)->
__u6_addr.__u6_addr8[1] & 0xc0) == 0x80))
&&
584 *(u_int16_t *)&sin6.sin6_addr.s6_addr__u6_addr.__u6_addr8[2] != 0) {
585 sin6.sin6_scope_id =
586 ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2])(__uint16_t)(__builtin_constant_p(*(u_int16_t *)&sin6.sin6_addr
.__u6_addr.__u6_addr8[2]) ? (__uint16_t)(((__uint16_t)(*(u_int16_t
*)&sin6.sin6_addr.__u6_addr.__u6_addr8[2]) & 0xffU) <<
8 | ((__uint16_t)(*(u_int16_t *)&sin6.sin6_addr.__u6_addr
.__u6_addr8[2]) & 0xff00U) >> 8) : __swap16md(*(u_int16_t
*)&sin6.sin6_addr.__u6_addr.__u6_addr8[2]))
;
587 sin6.sin6_addr.s6_addr__u6_addr.__u6_addr8[2] = sin6.sin6_addr.s6_addr__u6_addr.__u6_addr8[3] = 0;
588 }
589
590 if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
591 hbuf, sizeof(hbuf), NULL((void *)0), 0, niflags))
592 return "invalid";
593
594 return hbuf;
595}
596
597void
598splice_insert(char type, u_int64_t ptr, struct kinfo_file *data)
599{
600 ENTRY entry, *found;
601
602 if (asprintf(&entry.key, "%c%llx", type, hideroot ? 0 : ptr) == -1)
603 err(1, NULL((void *)0));
604 entry.data = data;
605 if ((found = hsearch(entry, ENTER)) == NULL((void *)0))
606 err(1, "hsearch");
607 /* if it's ambiguous, set the data to NULL */
608 if (found->data != data)
609 found->data = NULL((void *)0);
610}
611
612struct kinfo_file *
613splice_find(char type, u_int64_t ptr)
614{
615 ENTRY entry, *found;
39
'entry' initialized here
616 char buf[20];
617
618 snprintf(buf, sizeof(buf), "%c%llx", type, hideroot ? 0 : ptr);
40
Assuming 'hideroot' is not equal to 0
41
'?' condition is true
619 entry.key = buf;
620 found = hsearch(entry, FIND);
42
Passed-by-value struct argument contains uninitialized data (e.g., field: 'data')
621 return (found != NULL((void *)0) ? found->data : NULL((void *)0));
622}
623
624void
625find_splices(struct kinfo_file *kf, int cnt)
626{
627 int i, created;
628
629 created = 0;
630 for (i = 0; i < cnt; i++) {
631 if (kf[i].f_type != DTYPE_SOCKET2 ||
632 (kf[i].so_splice == 0 && kf[i].so_splicelen != -1))
633 continue;
634 if (created++ == 0) {
635 if (hcreate(1000) == 0)
636 err(1, "hcreate");
637 }
638 splice_insert('>', kf[i].f_data, &kf[i]);
639 if (kf[i].so_splice != 0)
640 splice_insert('<', kf[i].so_splice, &kf[i]);
641 }
642}
643
644void
645print_inet_details(struct kinfo_file *kf)
646{
647 struct in_addr laddr, faddr;
648
649 memcpy(&laddr, kf->inp_laddru, sizeof(laddr));
650 memcpy(&faddr, kf->inp_faddru, sizeof(faddr));
651 if (kf->so_protocol == IPPROTO_TCP6) {
652 printf(" ");
653 hide((void *)(uintptr_t)kf->inp_ppcb);
654 printf(" %s:%d", laddr.s_addr == INADDR_ANY((u_int32_t)(0x00000000)) ? "*" :
655 inet_ntoa(laddr), ntohs(kf->inp_lport)(__uint16_t)(__builtin_constant_p(kf->inp_lport) ? (__uint16_t
)(((__uint16_t)(kf->inp_lport) & 0xffU) << 8 | (
(__uint16_t)(kf->inp_lport) & 0xff00U) >> 8) : __swap16md
(kf->inp_lport))
);
656 if (kf->inp_fport) {
657 if (kf->so_state & SS_CONNECTOUT0x1000)
658 printf(" --> ");
659 else
660 printf(" <-- ");
661 printf("%s:%d",
662 faddr.s_addr == INADDR_ANY((u_int32_t)(0x00000000)) ? "*" :
663 inet_ntoa(faddr), ntohs(kf->inp_fport)(__uint16_t)(__builtin_constant_p(kf->inp_fport) ? (__uint16_t
)(((__uint16_t)(kf->inp_fport) & 0xffU) << 8 | (
(__uint16_t)(kf->inp_fport) & 0xff00U) >> 8) : __swap16md
(kf->inp_fport))
);
664 }
665 } else if (kf->so_protocol == IPPROTO_UDP17) {
666 printf(" %s:%d", laddr.s_addr == INADDR_ANY((u_int32_t)(0x00000000)) ? "*" :
667 inet_ntoa(laddr), ntohs(kf->inp_lport)(__uint16_t)(__builtin_constant_p(kf->inp_lport) ? (__uint16_t
)(((__uint16_t)(kf->inp_lport) & 0xffU) << 8 | (
(__uint16_t)(kf->inp_lport) & 0xff00U) >> 8) : __swap16md
(kf->inp_lport))
);
668 if (kf->inp_fport) {
669 printf(" <-> %s:%d",
670 faddr.s_addr == INADDR_ANY((u_int32_t)(0x00000000)) ? "*" :
671 inet_ntoa(faddr), ntohs(kf->inp_fport)(__uint16_t)(__builtin_constant_p(kf->inp_fport) ? (__uint16_t
)(((__uint16_t)(kf->inp_fport) & 0xffU) << 8 | (
(__uint16_t)(kf->inp_fport) & 0xff00U) >> 8) : __swap16md
(kf->inp_fport))
);
672 }
673 } else if (kf->so_pcb) {
674 printf(" ");
675 hide((void *)(uintptr_t)kf->so_pcb);
676 }
677}
678
679void
680print_inet6_details(struct kinfo_file *kf)
681{
682 char xaddrbuf[NI_MAXHOST256 + 2];
683 struct in6_addr laddr6, faddr6;
684
685 memcpy(&laddr6, kf->inp_laddru, sizeof(laddr6));
686 memcpy(&faddr6, kf->inp_faddru, sizeof(faddr6));
687 if (kf->so_protocol == IPPROTO_TCP6) {
688 printf(" ");
689 hide((void *)(uintptr_t)kf->inp_ppcb);
690 snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]",
691 inet6_addrstr(&laddr6));
692 printf(" %s:%d",
693 IN6_IS_ADDR_UNSPECIFIED(&laddr6)((*(const u_int32_t *)(const void *)(&(&laddr6)->__u6_addr
.__u6_addr8[0]) == 0) && (*(const u_int32_t *)(const void
*)(&(&laddr6)->__u6_addr.__u6_addr8[4]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&laddr6)->__u6_addr
.__u6_addr8[8]) == 0) && (*(const u_int32_t *)(const void
*)(&(&laddr6)->__u6_addr.__u6_addr8[12]) == 0))
? "*" :
694 xaddrbuf, ntohs(kf->inp_lport)(__uint16_t)(__builtin_constant_p(kf->inp_lport) ? (__uint16_t
)(((__uint16_t)(kf->inp_lport) & 0xffU) << 8 | (
(__uint16_t)(kf->inp_lport) & 0xff00U) >> 8) : __swap16md
(kf->inp_lport))
);
695 if (kf->inp_fport) {
696 if (kf->so_state & SS_CONNECTOUT0x1000)
697 printf(" --> ");
698 else
699 printf(" <-- ");
700 snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]",
701 inet6_addrstr(&faddr6));
702 printf("%s:%d",
703 IN6_IS_ADDR_UNSPECIFIED(&faddr6)((*(const u_int32_t *)(const void *)(&(&faddr6)->__u6_addr
.__u6_addr8[0]) == 0) && (*(const u_int32_t *)(const void
*)(&(&faddr6)->__u6_addr.__u6_addr8[4]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&faddr6)->__u6_addr
.__u6_addr8[8]) == 0) && (*(const u_int32_t *)(const void
*)(&(&faddr6)->__u6_addr.__u6_addr8[12]) == 0))
? "*" :
704 xaddrbuf, ntohs(kf->inp_fport)(__uint16_t)(__builtin_constant_p(kf->inp_fport) ? (__uint16_t
)(((__uint16_t)(kf->inp_fport) & 0xffU) << 8 | (
(__uint16_t)(kf->inp_fport) & 0xff00U) >> 8) : __swap16md
(kf->inp_fport))
);
705 }
706 } else if (kf->so_protocol == IPPROTO_UDP17) {
707 snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]",
708 inet6_addrstr(&laddr6));
709 printf(" %s:%d",
710 IN6_IS_ADDR_UNSPECIFIED(&laddr6)((*(const u_int32_t *)(const void *)(&(&laddr6)->__u6_addr
.__u6_addr8[0]) == 0) && (*(const u_int32_t *)(const void
*)(&(&laddr6)->__u6_addr.__u6_addr8[4]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&laddr6)->__u6_addr
.__u6_addr8[8]) == 0) && (*(const u_int32_t *)(const void
*)(&(&laddr6)->__u6_addr.__u6_addr8[12]) == 0))
? "*" :
711 xaddrbuf, ntohs(kf->inp_lport)(__uint16_t)(__builtin_constant_p(kf->inp_lport) ? (__uint16_t
)(((__uint16_t)(kf->inp_lport) & 0xffU) << 8 | (
(__uint16_t)(kf->inp_lport) & 0xff00U) >> 8) : __swap16md
(kf->inp_lport))
);
712 if (kf->inp_fport) {
713 snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]",
714 inet6_addrstr(&faddr6));
715 printf(" <-> %s:%d",
716 IN6_IS_ADDR_UNSPECIFIED(&faddr6)((*(const u_int32_t *)(const void *)(&(&faddr6)->__u6_addr
.__u6_addr8[0]) == 0) && (*(const u_int32_t *)(const void
*)(&(&faddr6)->__u6_addr.__u6_addr8[4]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&faddr6)->__u6_addr
.__u6_addr8[8]) == 0) && (*(const u_int32_t *)(const void
*)(&(&faddr6)->__u6_addr.__u6_addr8[12]) == 0))
? "*" :
717 xaddrbuf, ntohs(kf->inp_fport)(__uint16_t)(__builtin_constant_p(kf->inp_fport) ? (__uint16_t
)(((__uint16_t)(kf->inp_fport) & 0xffU) << 8 | (
(__uint16_t)(kf->inp_fport) & 0xff00U) >> 8) : __swap16md
(kf->inp_fport))
);
718 }
719 } else if (kf->so_pcb) {
720 printf(" ");
721 hide((void *)(uintptr_t)kf->so_pcb);
722 }
723}
724
725void
726print_sock_details(struct kinfo_file *kf)
727{
728 if (kf->so_family == AF_INET2)
729 print_inet_details(kf);
730 else if (kf->so_family == AF_INET624)
731 print_inet6_details(kf);
732}
733
734void
735socktrans(struct kinfo_file *kf)
736{
737 static char *stypename[] = {
738 "unused", /* 0 */
739 "stream", /* 1 */
740 "dgram", /* 2 */
741 "raw", /* 3 */
742 "rdm", /* 4 */
743 "seqpak" /* 5 */
744 };
745#define STYPEMAX5 5
746 char *stype, stypebuf[24];
747
748 if (checkfile
24.1
'checkfile' is 0
) {
25
Taking false branch
749 struct filearg *fa;
750
751 if (kf->so_type != AF_UNIX1)
752 return;
753 SLIST_FOREACH(fa, &fileargs, next)for((fa) = ((&fileargs)->slh_first); (fa) != ((void *)
0); (fa) = ((fa)->next.sle_next))
{
754 if (fa->dev != 0)
755 continue;
756 if (strcmp(kf->unp_path, fa->name) == 0)
757 break;
758 }
759 if (fa == NULL((void *)0))
760 return;
761 }
762
763 PREFIX(kf->fd_fd)do { printf("%-8.8s %-10s %5ld", Uname, Comm, (long)Pid); switch
(kf->fd_fd) { case -1: printf(" text"); break; case -2: printf
(" wd"); break; case -3: printf(" root"); break; case -4: printf
(" tr"); break; default: printf(" %4d", kf->fd_fd); break
; } } while (0)
;
26
Control jumps to the 'default' case at line 763
27
Execution continues on line 763
28
Loop condition is false. Exiting loop
764
765 if (kf->so_type > STYPEMAX5) {
29
Assuming field 'so_type' is <= STYPEMAX
30
Taking false branch
766 snprintf(stypebuf, sizeof(stypebuf), "?%d", kf->so_type);
767 stype = stypebuf;
768 } else {
769 stype = stypename[kf->so_type];
770 }
771
772 /*
773 * protocol specific formatting
774 *
775 * Try to find interesting things to print. For tcp, the interesting
776 * thing is the address of the tcpcb, for udp and others, just the
777 * inpcb (socket pcb). For unix domain, its the address of the socket
778 * pcb and the address of the connected pcb (if connected). Otherwise
779 * just print the protocol number and address of the socket itself.
780 * The idea is not to duplicate netstat, but to make available enough
781 * information for further analysis.
782 */
783 switch (kf->so_family) {
31
Control jumps to 'case 1:' at line 798
784 case AF_INET2:
785 printf("* internet %s", stype);
786 getinetproto(kf->so_protocol);
787 print_inet_details(kf);
788 if (kf->inp_rtableid)
789 printf(" rtable %u", kf->inp_rtableid);
790 break;
791 case AF_INET624:
792 printf("* internet6 %s", stype);
793 getinetproto(kf->so_protocol);
794 print_inet6_details(kf);
795 if (kf->inp_rtableid)
796 printf(" rtable %u", kf->inp_rtableid);
797 break;
798 case AF_UNIX1:
799 /* print address of pcb and connected pcb */
800 printf("* unix %s", stype);
801 if (kf->so_pcb) {
32
Assuming field 'so_pcb' is 0
33
Taking false branch
802 printf(" ");
803 hide((void *)(uintptr_t)kf->so_pcb);
804 if (kf->unp_conn) {
805 char shoconn[4], *cp;
806
807 cp = shoconn;
808 if (!(kf->so_state & SS_CANTRCVMORE0x020))
809 *cp++ = '<';
810 *cp++ = '-';
811 if (!(kf->so_state & SS_CANTSENDMORE0x010))
812 *cp++ = '>';
813 *cp = '\0';
814 printf(" %s ", shoconn);
815 hide((void *)(uintptr_t)kf->unp_conn);
816 }
817 }
818 if (kf->unp_path[0] != '\0')
34
Assuming the condition is false
35
Taking false branch
819 printf(" %s", kf->unp_path);
820 break;
36
Execution continues on line 844
821 case AF_MPLS33:
822 /* print protocol number and socket address */
823 printf("* mpls %s", stype);
824 printf(" %d ", kf->so_protocol);
825 hide((void *)(uintptr_t)kf->f_data);
826 break;
827 case AF_ROUTE17:
828 /* print protocol number and socket address */
829 printf("* route %s", stype);
830 printf(" %d ", kf->so_protocol);
831 hide((void *)(uintptr_t)kf->f_data);
832 break;
833 case AF_KEY30:
834 printf("* pfkey %s", stype);
835 printf(" %d ", kf->so_protocol);
836 hide((void *)(uintptr_t)kf->f_data);
837 break;
838 default:
839 /* print protocol number and socket address */
840 printf("* %d %s", kf->so_family, stype);
841 printf(" %d ", kf->so_protocol);
842 hide((void *)(uintptr_t)kf->f_data);
843 }
844 if (kf->so_splice != 0 || kf->so_splicelen == -1) {
37
Assuming field 'so_splice' is not equal to 0
845 struct kinfo_file *from, *to;
846
847 from = splice_find('<', kf->f_data);
38
Calling 'splice_find'
848 to = NULL((void *)0);
849 if (kf->so_splice != 0)
850 to = splice_find('>', kf->so_splice);
851
852 if (to != NULL((void *)0) && from == to) {
853 printf(" <==>");
854 print_sock_details(to);
855 } else if (kf->so_splice != 0) {
856 printf(" ==>");
857 if (to != NULL((void *)0))
858 print_sock_details(to);
859 } else if (kf->so_splicelen == -1) {
860 printf(" <==");
861 if (from != NULL((void *)0))
862 print_sock_details(from);
863 }
864 }
865 if (sflg)
866 printf("\t%8llu %8llu",
867 (kf->f_rxfer + kf->f_rwfer),
868 (kf->f_rbytes + kf->f_wbytes) / 1024);
869 printf("\n");
870}
871
872/*
873 * getinetproto --
874 * print name of protocol number
875 */
876void
877getinetproto(int number)
878{
879 static int isopen;
880 struct protoent *pe;
881
882 if (!isopen)
883 setprotoent(++isopen);
884 if ((pe = getprotobynumber(number)) != NULL((void *)0))
885 printf(" %s", pe->p_name);
886 else
887 printf(" %d", number);
888}
889
890int
891getfname(char *filename)
892{
893 static struct statfs *mntbuf;
894 static int nmounts;
895 int i;
896 struct stat sb;
897 struct filearg *cur;
898
899 if (stat(filename, &sb)) {
900 warn("%s", filename);
901 return (0);
902 }
903
904 /*
905 * POSIX specifies "For block special devices, all processes using any
906 * file on that device are listed". However the -f flag description
907 * states "The report shall be only for the named files", so we only
908 * look up a block device if the -f flag has not be specified.
909 */
910 if (fuser && !fsflg && S_ISBLK(sb.st_mode)((sb.st_mode & 0170000) == 0060000)) {
911 if (mntbuf == NULL((void *)0)) {
912 nmounts = getmntinfo(&mntbuf, MNT_NOWAIT2);
913 if (nmounts == -1)
914 err(1, "getmntinfo");
915 }
916 for (i = 0; i < nmounts; i++) {
917 if (!strcmp(mntbuf[i].f_mntfromname, filename)) {
918 if (stat(mntbuf[i].f_mntonname, &sb) == -1) {
919 warn("%s", filename);
920 return (0);
921 }
922 cflg = 1;
923 break;
924 }
925 }
926 }
927 if (!fuser && S_ISSOCK(sb.st_mode)((sb.st_mode & 0170000) == 0140000)) {
928 char *newname = realpath(filename, NULL((void *)0));
929 if (newname != NULL((void *)0))
930 filename = newname;
931 }
932
933 if ((cur = calloc(1, sizeof(*cur))) == NULL((void *)0))
934 err(1, NULL((void *)0));
935
936 if (!S_ISSOCK(sb.st_mode)((sb.st_mode & 0170000) == 0140000)) {
937 cur->ino = sb.st_ino;
938 cur->dev = sb.st_dev & 0xffff;
939 }
940 cur->name = filename;
941 TAILQ_INIT(&cur->fusers)do { (&cur->fusers)->tqh_first = ((void *)0); (&
cur->fusers)->tqh_last = &(&cur->fusers)->
tqh_first; } while (0)
;
942 SLIST_INSERT_HEAD(&fileargs, cur, next)do { (cur)->next.sle_next = (&fileargs)->slh_first;
(&fileargs)->slh_first = (cur); } while (0)
;
943 return (1);
944}
945
946int
947signame_to_signum(char *sig)
948{
949 int n;
950 const char *errstr = NULL((void *)0);
951
952 if (isdigit((unsigned char)*sig)) {
953 n = strtonum(sig, 0, NSIG33 - 1, &errstr);
954 return (errstr ? -1 : n);
955 }
956 if (!strncasecmp(sig, "sig", 3))
957 sig += 3;
958 for (n = 1; n < NSIG33; n++) {
959 if (!strcasecmp(sys_signame[n], sig))
960 return (n);
961 }
962 return (-1);
963}
964
965void
966usage(void)
967{
968 if (fuser) {
969 fprintf(stderr(&__sF[2]), "usage: fuser [-cfku] [-M core] "
970 "[-N system] [-s signal] file ...\n");
971 } else {
972 fprintf(stderr(&__sF[2]), "usage: fstat [-fnosv] [-M core] [-N system] "
973 "[-p pid] [-u user] [file ...]\n");
974 }
975 exit(1);
976}