Bug Summary

File:src/sbin/umount/umount.c
Warning:line 224, column 10
The left operand of '!=' is a garbage value

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 umount.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/sbin/umount/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/sbin/umount/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/sbin/umount/umount.c
1/* $OpenBSD: umount.c,v 1.29 2019/06/28 13:32:46 deraadt Exp $ */
2/* $NetBSD: umount.c,v 1.16 1996/05/11 14:13:55 mycroft Exp $ */
3
4/*-
5 * Copyright (c) 1980, 1989, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/stat.h>
34#include <sys/mount.h>
35#include <sys/time.h>
36#include <sys/socket.h>
37
38#include <netdb.h>
39#include <rpc/rpc.h>
40#include <rpc/pmap_clnt.h>
41#include <rpc/pmap_prot.h>
42#include <nfs/rpcv2.h>
43
44#include <err.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <unistd.h>
49#include <limits.h>
50#include <util.h>
51
52typedef enum { MNTON, MNTFROM } mntwhat;
53
54int fflag, verbose;
55char **typelist = NULL((void *)0);
56char *nfshost;
57
58char *getmntname(char *, mntwhat, char *);
59void maketypelist(char *);
60int selected(const char *);
61int namematch(struct hostent *);
62int umountall(void);
63int umountfs(char *);
64void usage(void);
65int xdr_dir(XDR *, char *);
66
67int
68main(int argc, char *argv[])
69{
70 int all, ch, errs;
71
72 /* Start disks transferring immediately. */
73 sync();
74
75 all = 0;
76 while ((ch = getopt(argc, argv, "afh:t:v")) != -1)
1
Assuming the condition is false
2
Loop condition is false. Execution continues on line 100
77 switch (ch) {
78 case 'a':
79 all = 1;
80 break;
81 case 'f':
82 fflag = MNT_FORCE0x00080000;
83 break;
84 case 'h': /* -h implies -a. */
85 all = 1;
86 nfshost = optarg;
87 break;
88 case 't':
89 if (typelist != NULL((void *)0))
90 errx(1, "only one -t option may be specified.");
91 maketypelist(optarg);
92 break;
93 case 'v':
94 verbose = 1;
95 break;
96 default:
97 usage();
98 /* NOTREACHED */
99 }
100 argc -= optind;
101 argv += optind;
102
103 if ((argc == 0 && !all) || (argc
3.1
'argc' is not equal to 0
!= 0 && all
3.2
'all' is 0
))
3
Assuming 'argc' is not equal to 0
4
Taking false branch
104 usage();
105
106 /* -h implies "-t nfs" if no -t flag. */
107 if ((nfshost != NULL((void *)0)) && (typelist == NULL((void *)0)))
5
Assuming 'nfshost' is equal to NULL
108 maketypelist(MOUNT_NFS"nfs");
109
110 if (all
5.1
'all' is 0
)
6
Taking false branch
111 errs = umountall();
112 else
113 for (errs = 0; *argv != NULL((void *)0); ++argv)
7
Loop condition is true. Entering loop body
114 if (umountfs(*argv) != 0)
8
Calling 'umountfs'
115 errs = 1;
116 return (errs);
117}
118
119int
120umountall(void)
121{
122 struct statfs *fs;
123 int n;
124 int rval;
125
126 n = getmntinfo(&fs, MNT_NOWAIT2);
127 if (n == 0)
128 err(1, NULL((void *)0));
129
130 rval = 0;
131 while (--n >= 0) {
132 /* Ignore the root. */
133 if (strncmp(fs[n].f_mntonname, "/", MNAMELEN90) == 0)
134 continue;
135 if (!selected(fs[n].f_fstypename))
136 continue;
137 if (umountfs(fs[n].f_mntonname))
138 rval = 1;
139 }
140 return (rval);
141}
142
143int
144umountfs(char *oname)
145{
146 struct hostent *hp;
9
'hp' declared without an initial value
147#ifndef NO_NFS
148 struct sockaddr_in saddr;
149 struct timeval pertry, try;
150 CLIENT *clp;
151 int so;
152#endif
153 struct stat sb;
154 char *delimp, *hostp, *mntpt;
155 char *name, *newname, rname[PATH_MAX1024], type[MFSNAMELEN16];
156
157 if (isduid(oname, 0) || realpath(oname, rname) == NULL((void *)0))
10
Assuming the condition is true
158 mntpt = name = oname;
159 else
160 mntpt = name = rname;
161 newname = NULL((void *)0);
162
163 /* If we can stat the file, check to see if it is a device or non-dir */
164 if (stat(name, &sb) == 0) {
11
Assuming the condition is false
12
Taking false branch
165 if (S_ISBLK(sb.st_mode)((sb.st_mode & 0170000) == 0060000)) {
166 if ((mntpt = getmntname(name, MNTON, type)) == NULL((void *)0)) {
167 warnx("%s: not currently mounted", name);
168 return (1);
169 }
170 } else if (!S_ISDIR(sb.st_mode)((sb.st_mode & 0170000) == 0040000)) {
171 warnx("%s: not a directory or special device", name);
172 return (1);
173 }
174 }
175
176 /*
177 * Look up the name in the mount table.
178 * 99.9% of the time the path in the kernel is the one
179 * realpath() returns but check the original just in case...
180 */
181 if (!(newname = getmntname(name, MNTFROM, type)) &&
13
Assuming 'newname' is non-null
182 !(mntpt = getmntname(name, MNTON, type)) ) {
183 mntpt = oname;
184 if (!(newname = getmntname(oname, MNTFROM, type)) &&
185 !(mntpt = getmntname(oname, MNTON, type))) {
186 warnx("%s: not currently mounted", oname);
187 return (1);
188 }
189 }
190 if (newname
13.1
'newname' is non-null
)
14
Taking true branch
191 name = newname;
192
193 if (!selected(type))
15
Assuming the condition is false
16
Taking false branch
194 return (1);
195
196 if (!strncmp(type, MOUNT_NFS"nfs", MFSNAMELEN16)) {
17
Assuming the condition is false
18
Taking false branch
197 if ((delimp = strchr(name, '@')) != NULL((void *)0)) {
198 hostp = delimp + 1;
199 *delimp = '\0';
200 hp = gethostbyname(hostp);
201 *delimp = '@';
202 } else if ((delimp = strchr(name, ':')) != NULL((void *)0)) {
203 *delimp = '\0';
204 hostp = name;
205 hp = gethostbyname(hostp);
206 name = delimp + 1;
207 *delimp = ':';
208 } else
209 hp = NULL((void *)0);
210 if (!namematch(hp))
211 return (1);
212 }
213
214 if (verbose)
19
Assuming 'verbose' is 0
20
Taking false branch
215 printf("%s: unmount from %s\n", name, mntpt);
216
217 if (unmount(mntpt, fflag) == -1) {
21
Assuming the condition is false
22
Taking false branch
218 warn("%s", mntpt);
219 return (1);
220 }
221
222#ifndef NO_NFS
223 if (!strncmp(type, MOUNT_NFS"nfs", MFSNAMELEN16) &&
23
Assuming the condition is true
224 (hp != NULL((void *)0)) && !(fflag & MNT_FORCE0x00080000)) {
24
The left operand of '!=' is a garbage value
225 enum clnt_stat clnt_stat;
226
227 *delimp = '\0';
228 memset(&saddr, 0, sizeof(saddr));
229 saddr.sin_family = AF_INET2;
230 saddr.sin_port = 0;
231 memmove(&saddr.sin_addr, hp->h_addrh_addr_list[0], hp->h_length);
232 pertry.tv_sec = 3;
233 pertry.tv_usec = 0;
234 so = RPC_ANYSOCK-1;
235 if ((clp = clntudp_create(&saddr,
236 RPCPROG_MNT100005, RPCMNT_VER11, pertry, &so)) == NULL((void *)0)) {
237 clnt_pcreateerror("Cannot MNT RPC");
238 return (1);
239 }
240 clp->cl_auth = authunix_create_default();
241 try.tv_sec = 20;
242 try.tv_usec = 0;
243 clnt_stat = clnt_call(clp,((*(clp)->cl_ops->cl_call)(clp, 3, xdr_dir, (caddr_t)name
, xdr_void, (caddr_t)(caddr_t)0, try))
244 RPCMNT_UMOUNT, xdr_dir, name, xdr_void, (caddr_t)0, try)((*(clp)->cl_ops->cl_call)(clp, 3, xdr_dir, (caddr_t)name
, xdr_void, (caddr_t)(caddr_t)0, try))
;
245 if (clnt_stat != RPC_SUCCESS) {
246 clnt_perror(clp, "Bad MNT RPC");
247 return (1);
248 }
249 auth_destroy(clp->cl_auth)((*((clp->cl_auth)->ah_ops->ah_destroy))(clp->cl_auth
))
;
250 clnt_destroy(clp)((*(clp)->cl_ops->cl_destroy)(clp));
251 }
252#endif
253 return (0);
254}
255
256char *
257getmntname(char *name, mntwhat what, char *type)
258{
259 struct statfs *mntbuf;
260 int n;
261
262 if ((n = getmntinfo(&mntbuf, MNT_NOWAIT2)) == 0) {
263 warn("getmntinfo");
264 return (NULL((void *)0));
265 }
266 while (--n >= 0) {
267 if ((what == MNTON) &&
268 (strncmp(mntbuf[n].f_mntfromname, name, MNAMELEN90) == 0 ||
269 strncmp(mntbuf[n].f_mntfromspec, name, MNAMELEN90) == 0)) {
270 if (type)
271 memcpy(type, mntbuf[n].f_fstypename,
272 sizeof(mntbuf[n].f_fstypename));
273 return (mntbuf[n].f_mntonname);
274 }
275 if ((what == MNTFROM) &&
276 (strncmp(mntbuf[n].f_mntonname, name, MNAMELEN90) == 0)) {
277 if (type)
278 memcpy(type, mntbuf[n].f_fstypename,
279 sizeof(mntbuf[n].f_fstypename));
280 return (mntbuf[n].f_mntfromname);
281 }
282 }
283 return (NULL((void *)0));
284}
285
286static enum { IN_LIST, NOT_IN_LIST } which;
287
288int
289selected(const char *type)
290{
291 char **av;
292
293 /* If no type specified, it's always selected. */
294 if (typelist == NULL((void *)0))
295 return (1);
296 for (av = typelist; *av != NULL((void *)0); ++av)
297 if (!strncmp(type, *av, MFSNAMELEN16))
298 return (which == IN_LIST ? 1 : 0);
299 return (which == IN_LIST ? 0 : 1);
300}
301
302void
303maketypelist(char *fslist)
304{
305 int i;
306 char *nextcp, **av;
307
308 if ((fslist == NULL((void *)0)) || (fslist[0] == '\0'))
309 errx(1, "empty type list");
310
311 /*
312 * XXX
313 * Note: the syntax is "noxxx,yyy" for no xxx's and
314 * no yyy's, not the more intuitive "noxxx,noyyy".
315 */
316 if (fslist[0] == 'n' && fslist[1] == 'o') {
317 fslist += 2;
318 which = NOT_IN_LIST;
319 } else
320 which = IN_LIST;
321
322 /* Count the number of types. */
323 for (i = 1, nextcp = fslist; (nextcp = strchr(nextcp, ',')); i++)
324 ++nextcp;
325
326 /* Build an array of that many types. */
327 if ((av = typelist = calloc(i + 1, sizeof(char *))) == NULL((void *)0))
328 err(1, NULL((void *)0));
329 av[0] = fslist;
330 for (i = 1, nextcp = fslist; (nextcp = strchr(nextcp, ',')); i++) {
331 *nextcp = '\0';
332 av[i] = ++nextcp;
333 }
334 /* Terminate the array. */
335 av[i] = NULL((void *)0);
336}
337
338int
339namematch(struct hostent *hp)
340{
341 char *cp, **np;
342
343 if ((hp == NULL((void *)0)) || (nfshost == NULL((void *)0)))
344 return (1);
345
346 if (strcasecmp(nfshost, hp->h_name) == 0)
347 return (1);
348
349 if ((cp = strchr(hp->h_name, '.')) != NULL((void *)0)) {
350 *cp = '\0';
351 if (strcasecmp(nfshost, hp->h_name) == 0)
352 return (1);
353 }
354 for (np = hp->h_aliases; *np; np++) {
355 if (strcasecmp(nfshost, *np) == 0)
356 return (1);
357 if ((cp = strchr(*np, '.')) != NULL((void *)0)) {
358 *cp = '\0';
359 if (strcasecmp(nfshost, *np) == 0)
360 return (1);
361 }
362 }
363 return (0);
364}
365
366#ifndef NO_NFS
367/*
368 * xdr routines for mount rpc's
369 */
370int
371xdr_dir(XDR *xdrsp, char *dirp)
372{
373 return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN1024));
374}
375#endif
376
377void
378usage(void)
379{
380 fprintf(stderr(&__sF[2]),
381 "usage: %s\n %s\n",
382 "umount [-fv] special | node",
383 "umount -a [-fv] [-h host] [-t type]");
384 exit(1);
385}