Bug Summary

File:isofs/cd9660/cd9660_lookup.c
Warning:line 259, column 18
Although the value stored to 'res' is used in the enclosing expression, the value is never actually read from 'res'

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 cd9660_lookup.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 static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/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 -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/isofs/cd9660/cd9660_lookup.c
1/* $OpenBSD: cd9660_lookup.c,v 1.30 2022/01/11 03:13:58 jsg Exp $ */
2/* $NetBSD: cd9660_lookup.c,v 1.18 1997/05/08 16:19:59 mycroft Exp $ */
3
4/*-
5 * Copyright (c) 1989, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley
9 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
10 * Support code is derived from software contributed to Berkeley
11 * by Atsushi Murai (amurai@spec.co.jp).
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * from: @(#)ufs_lookup.c 7.33 (Berkeley) 5/19/91
38 *
39 * @(#)cd9660_lookup.c 8.5 (Berkeley) 12/5/94
40 */
41
42#include <sys/param.h>
43#include <sys/namei.h>
44#include <sys/buf.h>
45#include <sys/vnode.h>
46#include <sys/lock.h>
47#include <sys/mount.h>
48#include <sys/systm.h>
49#include <sys/malloc.h>
50
51#include <isofs/cd9660/iso.h>
52#include <isofs/cd9660/cd9660_extern.h>
53#include <isofs/cd9660/cd9660_node.h>
54#include <isofs/cd9660/iso_rrip.h>
55
56struct nchstats iso_nchstats;
57
58/*
59 * Convert a component of a pathname into a pointer to a locked inode.
60 * This is a very central and rather complicated routine.
61 * If the file system is not maintained in a strict tree hierarchy,
62 * this can result in a deadlock situation (see comments in code below).
63 *
64 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
65 * whether the name is to be looked up, created, renamed, or deleted.
66 * When CREATE, RENAME, or DELETE is specified, information usable in
67 * creating, renaming, or deleting a directory entry may be calculated.
68 * If flag has LOCKPARENT or'ed into it and the target of the pathname
69 * exists, lookup returns both the target and its parent directory locked.
70 * When creating or renaming and LOCKPARENT is specified, the target may
71 * not be ".". When deleting and LOCKPARENT is specified, the target may
72 * be "."., but the caller must check to ensure it does an vrele and iput
73 * instead of two iputs.
74 *
75 * Overall outline of cd9660_lookup:
76 *
77 * check accessibility of directory
78 * look for name in cache, if found, then if at end of path
79 * and deleting or creating, drop it, else return name
80 * search for name in directory, to found or notfound
81 * notfound:
82 * if creating, return locked directory, leaving info on available slots
83 * else return error
84 * found:
85 * if at end of path and deleting, return information to allow delete
86 * if at end of path and rewriting (RENAME and LOCKPARENT), lock target
87 * inode and return info to allow rewrite
88 * if not at end, add name to cache; if at end and neither creating
89 * nor deleting, add name to cache
90 *
91 * NOTE: (LOOKUP | LOCKPARENT) currently returns the parent inode unlocked.
92 */
93int
94cd9660_lookup(void *v)
95{
96 struct vop_lookup_args *ap = v;
97 struct vnode *vdp; /* vnode for directory being searched */
98 struct iso_node *dp; /* inode for directory being searched */
99 struct iso_mnt *imp; /* file system that directory is in */
100 struct buf *bp; /* a buffer of directory entries */
101 struct iso_directory_record *ep = NULL((void *)0);
102 /* the current directory entry */
103 int entryoffsetinblock; /* offset of ep in bp's buffer */
104 int saveoffset = -1; /* offset of last directory entry in dir */
105 int numdirpasses; /* strategy for directory search */
106 doff_tu_quad_t endsearch; /* offset to end directory search */
107 struct vnode *pdp; /* saved dp during symlink work */
108 struct vnode *tdp; /* returned by cd9660_vget_internal */
109 u_long bmask; /* block offset mask */
110 int lockparent; /* 1 => lockparent flag is set */
111 int error;
112 cdino_t ino = 0;
113 int reclen;
114 u_short namelen;
115 char *altname;
116 int res;
117 int assoc, len;
118 char *name;
119 struct vnode **vpp = ap->a_vpp;
120 struct componentname *cnp = ap->a_cnp;
121 struct ucred *cred = cnp->cn_cred;
122 int flags;
123 int nameiop = cnp->cn_nameiop;
124
125 cnp->cn_flags &= ~PDIRUNLOCK0x200000;
126 flags = cnp->cn_flags;
127
128 bp = NULL((void *)0);
129 *vpp = NULL((void *)0);
130 vdp = ap->a_dvp;
131 dp = VTOI(vdp)((struct iso_node *)(vdp)->v_data);
132 imp = dp->i_mnt;
133 lockparent = flags & LOCKPARENT0x0008;
134
135 /*
136 * Check accessibility of directory.
137 */
138 if ((error = VOP_ACCESS(vdp, VEXEC00100, cred, cnp->cn_proc)) != 0)
139 return (error);
140
141 if ((flags & ISLASTCN0x008000) && (vdp->v_mount->mnt_flag & MNT_RDONLY0x00000001) &&
142 (cnp->cn_nameiop == DELETE2 || cnp->cn_nameiop == RENAME3))
143 return (EROFS30);
144
145 /*
146 * We now have a segment name to search for, and a directory to search.
147 *
148 * Before tediously performing a linear scan of the directory,
149 * check the name cache to see if the directory/name pair
150 * we are looking for is known already.
151 */
152 if ((error = cache_lookup(vdp, vpp, cnp)) >= 0)
153 return (error);
154
155 len = cnp->cn_namelen;
156 name = cnp->cn_nameptr;
157 /*
158 * A leading `=' means, we are looking for an associated file
159 */
160 assoc = (imp->iso_ftype != ISO_FTYPE_RRIP && *name == ASSOCCHAR'=');
161 if (assoc) {
162 len--;
163 name++;
164 }
165
166 /*
167 * If there is cached information on a previous search of
168 * this directory, pick up where we last left off.
169 * We cache only lookups as these are the most common
170 * and have the greatest payoff. Caching CREATE has little
171 * benefit as it usually must search the entire directory
172 * to determine that the entry does not exist. Caching the
173 * location of the last DELETE or RENAME has not reduced
174 * profiling time and hence has been removed in the interest
175 * of simplicity.
176 */
177 bmask = imp->im_bmask;
178 if (nameiop != LOOKUP0 || dp->i_diroff == 0 ||
179 dp->i_diroff > dp->i_size) {
180 entryoffsetinblock = 0;
181 dp->i_offset = 0;
182 numdirpasses = 1;
183 } else {
184 dp->i_offset = dp->i_diroff;
185 if ((entryoffsetinblock = dp->i_offset & bmask) &&
186 (error = cd9660_bufatoff(dp, (off_t)dp->i_offset, NULL((void *)0),
187 &bp)))
188 return (error);
189 numdirpasses = 2;
190 iso_nchstats.ncs_2passes++;
191 }
192 endsearch = dp->i_size;
193
194searchloop:
195 while (dp->i_offset < endsearch) {
196 /*
197 * If offset is on a block boundary,
198 * read the next directory block.
199 * Release previous if it exists.
200 */
201 if ((dp->i_offset & bmask) == 0) {
202 if (bp != NULL((void *)0))
203 brelse(bp);
204 error = cd9660_bufatoff(dp, (off_t)dp->i_offset,
205 NULL((void *)0), &bp);
206 if (error)
207 return (error);
208 entryoffsetinblock = 0;
209 }
210 /*
211 * Get pointer to next entry.
212 */
213 ep = (struct iso_directory_record *)
214 ((char *)bp->b_data + entryoffsetinblock);
215
216 reclen = isonum_711(ep->length);
217 if (reclen == 0) {
218 /* skip to next block, if any */
219 dp->i_offset =
220 (dp->i_offset & ~bmask) + imp->logical_block_size;
221 continue;
222 }
223
224 if (reclen < ISO_DIRECTORY_RECORD_SIZE33)
225 /* illegal entry, stop */
226 break;
227
228 if (entryoffsetinblock + reclen > imp->logical_block_size)
229 /* entries are not allowed to cross boundaries */
230 break;
231
232 namelen = isonum_711(ep->name_len);
233
234 if (reclen < ISO_DIRECTORY_RECORD_SIZE33 + namelen)
235 /* illegal entry, stop */
236 break;
237
238 /*
239 * Check for a name match.
240 */
241 switch (imp->iso_ftype) {
242 default:
243 if ((!(isonum_711(ep->flags)&4)) == !assoc) {
244 if ((len == 1
245 && *name == '.')
246 || (flags & ISDOTDOT0x002000)) {
247 if (namelen == 1
248 && ep->name[0] == ((flags & ISDOTDOT0x002000) ? 1 : 0)) {
249 /*
250 * Save directory entry's inode number and
251 * release directory buffer.
252 */
253 dp->i_ino = isodirino(ep, imp);
254 goto found;
255 }
256 if (namelen != 1
257 || ep->name[0] != 0)
258 goto notfound;
259 } else if (!(res = isofncmp(name, len,
Although the value stored to 'res' is used in the enclosing expression, the value is never actually read from 'res'
260 ep->name, namelen, imp->joliet_level))) {
261 if (isonum_711(ep->flags)&2)
262 ino = isodirino(ep, imp);
263 else
264 ino = dbtob(bp->b_blkno)((bp->b_blkno) << 9)
265 + entryoffsetinblock;
266 saveoffset = dp->i_offset;
267 } else if (ino)
268 goto foundino;
269#ifdef NOSORTBUG /* On some CDs directory entries are not sorted correctly */
270 else if (res < 0)
271 goto notfound;
272 else if (res > 0 && numdirpasses == 2)
273 numdirpasses++;
274#endif
275 }
276 break;
277 case ISO_FTYPE_RRIP:
278 if (isonum_711(ep->flags)&2)
279 ino = isodirino(ep, imp);
280 else
281 ino = dbtob(bp->b_blkno)((bp->b_blkno) << 9) + entryoffsetinblock;
282 dp->i_ino = ino;
283 altname = malloc(NAME_MAX255, M_TEMP127, M_WAITOK0x0001);
284 cd9660_rrip_getname(ep,altname,&namelen,&dp->i_ino,imp);
285 if (namelen == cnp->cn_namelen
286 && !bcmp(name,altname,namelen)) {
287 free(altname, M_TEMP127, 0);
288 goto found;
289 }
290 free(altname, M_TEMP127, 0);
291 ino = 0;
292 break;
293 }
294 dp->i_offset += reclen;
295 entryoffsetinblock += reclen;
296 }
297 if (ino) {
298foundino:
299 dp->i_ino = ino;
300 if (saveoffset != dp->i_offset) {
301 if (lblkno(imp, dp->i_offset)((dp->i_offset) >> (imp)->im_bshift) !=
302 lblkno(imp, saveoffset)((saveoffset) >> (imp)->im_bshift)) {
303 if (bp != NULL((void *)0))
304 brelse(bp);
305 if ((error = cd9660_bufatoff(dp,
306 (off_t)saveoffset, NULL((void *)0), &bp)) != 0)
307 return (error);
308 }
309 entryoffsetinblock = saveoffset & bmask;
310 ep = (struct iso_directory_record *)
311 ((char *)bp->b_data + entryoffsetinblock);
312 dp->i_offset = saveoffset;
313 }
314 goto found;
315 }
316notfound:
317 /*
318 * If we started in the middle of the directory and failed
319 * to find our target, we must check the beginning as well.
320 */
321 if (numdirpasses == 2) {
322 numdirpasses--;
323 dp->i_offset = 0;
324 endsearch = dp->i_diroff;
325 goto searchloop;
326 }
327 if (bp != NULL((void *)0))
328 brelse(bp);
329
330 /*
331 * Insert name into cache (as non-existent) if appropriate.
332 */
333 if (cnp->cn_flags & MAKEENTRY0x004000)
334 cache_enter(vdp, *vpp, cnp);
335 if (nameiop == CREATE1 || nameiop == RENAME3)
336 return (EJUSTRETURN-2);
337 return (ENOENT2);
338
339found:
340 if (numdirpasses == 2)
341 iso_nchstats.ncs_pass2++;
342
343 /*
344 * Found component in pathname.
345 * If the final component of path name, save information
346 * in the cache as to where the entry was found.
347 */
348 if ((flags & ISLASTCN0x008000) && nameiop == LOOKUP0)
349 dp->i_diroff = dp->i_offset;
350
351 /*
352 * Step through the translation in the name. We do not `iput' the
353 * directory because we may need it again if a symbolic link
354 * is relative to the current directory. Instead we save it
355 * unlocked as "pdp". We must get the target inode before unlocking
356 * the directory to insure that the inode will not be removed
357 * before we get it. We prevent deadlock by always fetching
358 * inodes from the root, moving down the directory tree. Thus
359 * when following backward pointers ".." we must unlock the
360 * parent directory before getting the requested directory.
361 * There is a potential race condition here if both the current
362 * and parent directories are removed before the `iget' for the
363 * inode associated with ".." returns. We hope that this occurs
364 * infrequently since we cannot avoid this race condition without
365 * implementing a sophisticated deadlock detection algorithm.
366 * Note also that this simple deadlock detection scheme will not
367 * work if the file system has any hard links other than ".."
368 * that point backwards in the directory structure.
369 */
370 pdp = vdp;
371 /*
372 * If ino is different from dp->i_ino,
373 * it's a relocated directory.
374 */
375 if (flags & ISDOTDOT0x002000) {
376 brelse(bp);
377 VOP_UNLOCK(pdp); /* race to get the inode */
378 cnp->cn_flags |= PDIRUNLOCK0x200000;
379 error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp,
380 dp->i_ino != ino, NULL((void *)0));
381 if (error) {
382 if (vn_lock(pdp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL) == 0)
383 cnp->cn_flags &= ~PDIRUNLOCK0x200000;
384 return (error);
385 }
386 if (lockparent && (flags & ISLASTCN0x008000)) {
387 if ((error = vn_lock(pdp, LK_EXCLUSIVE0x0001UL))) {
388 vput(tdp);
389 return (error);
390 }
391 cnp->cn_flags &= ~PDIRUNLOCK0x200000;
392 }
393 *vpp = tdp;
394 } else if (dp->i_number == dp->i_ino) {
395 brelse(bp);
396 vref(vdp); /* we want ourself, ie "." */
397 *vpp = vdp;
398 } else {
399 error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp,
400 dp->i_ino != ino, ep);
401 brelse(bp);
402 if (error)
403 return (error);
404 if (!lockparent || !(flags & ISLASTCN0x008000)) {
405 VOP_UNLOCK(pdp);
406 cnp->cn_flags |= PDIRUNLOCK0x200000;
407 }
408 *vpp = tdp;
409 }
410
411 /*
412 * Insert name into cache if appropriate.
413 */
414 if (cnp->cn_flags & MAKEENTRY0x004000)
415 cache_enter(vdp, *vpp, cnp);
416 return (0);
417}
418
419/*
420 * Return buffer with the contents of block "offset" from the beginning of
421 * directory "ip". If "res" is non-zero, fill it in with a pointer to the
422 * remaining space in the directory.
423 */
424int
425cd9660_bufatoff(struct iso_node *ip, off_t offset, char **res,
426 struct buf **bpp)
427{
428 struct iso_mnt *imp;
429 struct buf *bp;
430 daddr_t lbn;
431 int bsize, error;
432 struct vnode *vp = ITOV(ip)((ip)->i_vnode);
433
434 imp = ip->i_mnt;
435 lbn = lblkno(imp, offset)((offset) >> (imp)->im_bshift);
436 bsize = blksize(imp, ip, lbn)((imp)->logical_block_size);
437
438 if ((error = bread(vp, lbn, bsize, &bp)) != 0) {
439 brelse(bp);
440 *bpp = NULL((void *)0);
441 return (error);
442 }
443 if (res)
444 *res = (char *)bp->b_data + blkoff(imp, offset)((offset) & (imp)->im_bmask);
445 *bpp = bp;
446 return (0);
447}