Bug Summary

File:src/sbin/fsck_msdos/boot.c
Warning:line 65, column 7
Although the value stored to 'o' is used in the enclosing expression, the value is never actually read from 'o'

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 boot.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/fsck_msdos/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sbin/fsck_msdos/../fsck -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/fsck_msdos/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/fsck_msdos/boot.c
1/* $OpenBSD: boot.c,v 1.24 2016/10/10 00:34:50 bluhm Exp $ */
2/* $NetBSD: boot.c,v 1.5 1997/10/17 11:19:23 ws Exp $ */
3
4/*
5 * Copyright (C) 1995, 1997 Wolfgang Solfrank
6 * Copyright (c) 1995 Martin Husemann
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 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/param.h> /* DEV_BSIZE powerof2 */
30#include <sys/disklabel.h>
31
32#include <stdlib.h>
33#include <string.h>
34#include <ctype.h>
35#include <stdio.h>
36#include <unistd.h>
37
38#include "ext.h"
39
40int
41readboot(int dosfs, struct bootblock *boot)
42{
43 u_char *block = NULL((void *)0);
44 u_char *fsinfo = NULL((void *)0);
45 u_char *backup = NULL((void *)0);
46 int ret = FSOK0, secsize = lab.d_secsize, fsinfosz;
47 off_t o;
48 ssize_t n;
49
50 if (secsize < DOSBOOTBLOCKSIZE512) {
51 xperror("sector size < DOSBOOTBLOCKSIZE");
52 goto fail;
53 }
54 if (DOSBOOTBLOCKSIZE512 != DEV_BSIZE(1 << 9)) {
55 xperror("DOSBOOTBLOCKSIZE != DEV_BSIZE");
56 goto fail;
57 }
58
59 block = malloc(secsize);
60 if (block == NULL((void *)0)) {
61 xperror("could not malloc boot block");
62 goto fail;
63 }
64
65 if ((o = lseek(dosfs, 0, SEEK_SET0)) == -1) {
Although the value stored to 'o' is used in the enclosing expression, the value is never actually read from 'o'
66 xperror("could not seek boot block");
67 goto fail;
68 }
69
70 n = read(dosfs, block, secsize);
71 if (n == -1 || n != secsize) {
72 xperror("could not read boot block");
73 goto fail;
74 }
75
76 if (block[510] != 0x55 || block[511] != 0xaa) {
77 pfatal("Invalid signature in boot block: %02x%02x\n",
78 block[511], block[510]);
79 }
80
81 memset(boot, 0, sizeof *boot);
82 boot->ValidFat = -1;
83
84 /* decode bios parameter block */
85 boot->BytesPerSec = block[11] + (block[12] << 8);
86 if (boot->BytesPerSec == 0 || boot->BytesPerSec != secsize) {
87 pfatal("Invalid sector size: %u\n", boot->BytesPerSec);
88 goto fail;
89 }
90 boot->SecPerClust = block[13];
91 if (boot->SecPerClust == 0 || !powerof2(boot->SecPerClust)((((boot->SecPerClust)-1)&(boot->SecPerClust))==0)) {
92 pfatal("Invalid cluster size: %u\n", boot->SecPerClust);
93 goto fail;
94 }
95 boot->ResSectors = block[14] + (block[15] << 8);
96 boot->FATs = block[16];
97 if (boot->FATs == 0) {
98 pfatal("Invalid number of FATs: %u\n", boot->FATs);
99 goto fail;
100 }
101 boot->RootDirEnts = block[17] + (block[18] << 8);
102 boot->Sectors = block[19] + (block[20] << 8);
103 boot->Media = block[21];
104 boot->FATsmall = block[22] + (block[23] << 8);
105 boot->SecPerTrack = block[24] + (block[25] << 8);
106 boot->Heads = block[26] + (block[27] << 8);
107 boot->HiddenSecs = block[28] + (block[29] << 8) + (block[30] << 16) + (block[31] << 24);
108 boot->HugeSectors = block[32] + (block[33] << 8) + (block[34] << 16) + (block[35] << 24);
109
110 boot->FATsecs = boot->FATsmall;
111
112 if (!boot->RootDirEnts) {
113 boot->flags |= FAT321;
114 boot->FATsecs = block[36] + (block[37] << 8)
115 + (block[38] << 16) + (block[39] << 24);
116 if (block[40] & 0x80)
117 boot->ValidFat = block[40] & 0x0f;
118
119 /* check version number: */
120 if (block[42] || block[43]) {
121 /* Correct? XXX */
122 pfatal("Unknown filesystem version: %x.%x\n",
123 block[43], block[42]);
124 goto fail;
125 }
126 boot->RootCl = block[44] + (block[45] << 8)
127 + (block[46] << 16) + (block[47] << 24);
128 boot->FSInfo = block[48] + (block[49] << 8);
129 boot->Backup = block[50] + (block[51] << 8);
130
131 o = lseek(dosfs, boot->FSInfo * secsize, SEEK_SET0);
132 if (o == -1 || o != boot->FSInfo * secsize) {
133 xperror("could not seek fsinfo block");
134 goto fail;
135 }
136
137 if ((2 * DOSBOOTBLOCKSIZE512) < secsize)
138 fsinfosz = secsize;
139 else
140 fsinfosz = 2 * secsize;
141 fsinfo = malloc(fsinfosz);
142 if (fsinfo == NULL((void *)0)) {
143 xperror("could not malloc fsinfo");
144 goto fail;
145 }
146 n = read(dosfs, fsinfo, fsinfosz);
147 if (n == -1 || n != fsinfosz) {
148 xperror("could not read fsinfo block");
149 goto fail;
150 }
151
152 if (memcmp(fsinfo, "RRaA", 4)
153 || memcmp(fsinfo + 0x1e4, "rrAa", 4)
154 || fsinfo[0x1fc]
155 || fsinfo[0x1fd]
156 || fsinfo[0x1fe] != 0x55
157 || fsinfo[0x1ff] != 0xaa
158 || fsinfo[0x3fc]
159 || fsinfo[0x3fd]
160 || fsinfo[0x3fe] != 0x55
161 || fsinfo[0x3ff] != 0xaa) {
162 pwarn("Invalid signature in fsinfo block\n");
163 if (ask(0, "fix")) {
164 memcpy(fsinfo, "RRaA", 4);
165 memcpy(fsinfo + 0x1e4, "rrAa", 4);
166 fsinfo[0x1fc] = fsinfo[0x1fd] = 0;
167 fsinfo[0x1fe] = 0x55;
168 fsinfo[0x1ff] = 0xaa;
169 fsinfo[0x3fc] = fsinfo[0x3fd] = 0;
170 fsinfo[0x3fe] = 0x55;
171 fsinfo[0x3ff] = 0xaa;
172
173 o = lseek(dosfs, boot->FSInfo * secsize,
174 SEEK_SET0);
175 if (o == -1 || o != boot->FSInfo * secsize) {
176 xperror("Unable to seek FSInfo");
177 goto fail;
178 }
179 n = write(dosfs, fsinfo, fsinfosz);
180 if (n == -1 || n != fsinfosz) {
181 xperror("Unable to write FSInfo");
182 goto fail;
183 }
184 ret = FSBOOTMOD1;
185 } else
186 boot->FSInfo = 0;
187 }
188 if (boot->FSInfo) {
189 boot->FSFree = fsinfo[0x1e8] + (fsinfo[0x1e9] << 8)
190 + (fsinfo[0x1ea] << 16)
191 + (fsinfo[0x1eb] << 24);
192 boot->FSNext = fsinfo[0x1ec] + (fsinfo[0x1ed] << 8)
193 + (fsinfo[0x1ee] << 16)
194 + (fsinfo[0x1ef] << 24);
195 }
196
197 o = lseek(dosfs, boot->Backup * secsize, SEEK_SET0);
198 if (o == -1 || o != boot->Backup * secsize) {
199 xperror("could not seek backup bootblock");
200 goto fail;
201 }
202 backup = malloc(2 * secsize); /* In case we check fsinfo. */
203 if (backup == NULL((void *)0)) {
204 xperror("could not malloc backup boot block");
205 goto fail;
206 }
207 n = read(dosfs, backup, secsize);
208 if (n == -1 || n != secsize) {
209 xperror("could not read backup bootblock");
210 goto fail;
211 }
212
213 /*
214 * Check that the backup boot block matches the primary one.
215 * We don't check every byte, since some vendor utilities
216 * seem to overwrite the boot code when they feel like it,
217 * without changing the backup block. Specifically, we check
218 * the two-byte signature at the end, the BIOS parameter
219 * block (which starts after the 3-byte JMP and the 8-byte
220 * OEM name/version) and the filesystem information that
221 * follows the BPB (bsBPB[53] and bsExt[26] for FAT32, so we
222 * check 79 bytes).
223 */
224 if (backup[510] != 0x55 || backup[511] != 0xaa) {
225 pfatal("Invalid signature in backup boot block: %02x%02x\n", backup[511], backup[510]);
226 }
227 if (memcmp(block + 11, backup + 11, 79)) {
228 pfatal("backup doesn't compare to primary bootblock\n");
229 goto fail;
230 }
231 /* Check backup FSInfo? XXX */
232 }
233
234 if (boot->FATsecs == 0) {
235 pfatal("Invalid number of FAT sectors: %u\n", boot->FATsecs);
236 goto fail;
237 }
238
239 boot->ClusterOffset = (boot->RootDirEnts * 32 + secsize - 1)
240 / secsize
241 + boot->ResSectors
242 + boot->FATs * boot->FATsecs
243 - CLUST_FIRST2 * boot->SecPerClust;
244
245 if (boot->Sectors) {
246 boot->HugeSectors = 0;
247 boot->NumSectors = boot->Sectors;
248 } else
249 boot->NumSectors = boot->HugeSectors;
250
251 if (boot->ClusterOffset > boot->NumSectors) {
252 pfatal("Cluster offset too large (%u clusters)\n",
253 boot->ClusterOffset);
254 goto fail;
255 }
256 boot->NumClusters = (boot->NumSectors - boot->ClusterOffset) / boot->SecPerClust;
257
258 if (boot->flags&FAT321)
259 boot->ClustMask = CLUST32_MASK0xfffffff;
260 else if (boot->NumClusters < (CLUST_RSRVD0xfffffff6&CLUST12_MASK0xfff))
261 boot->ClustMask = CLUST12_MASK0xfff;
262 else if (boot->NumClusters < (CLUST_RSRVD0xfffffff6&CLUST16_MASK0xffff))
263 boot->ClustMask = CLUST16_MASK0xffff;
264 else {
265 pfatal("Filesystem too big (%u clusters) for non-FAT32 partition\n",
266 boot->NumClusters);
267 goto fail;
268 }
269
270 switch (boot->ClustMask) {
271 case CLUST32_MASK0xfffffff:
272 boot->NumFatEntries = (boot->FATsecs * secsize) / 4;
273 break;
274 case CLUST16_MASK0xffff:
275 boot->NumFatEntries = (boot->FATsecs * secsize) / 2;
276 break;
277 default:
278 boot->NumFatEntries = (boot->FATsecs * secsize * 2) / 3;
279 break;
280 }
281
282 if (boot->NumFatEntries < boot->NumClusters) {
283 pfatal("FAT size too small, %u entries won't fit into %u sectors\n",
284 boot->NumClusters, boot->FATsecs);
285 goto fail;
286 }
287 boot->ClusterSize = boot->SecPerClust * secsize;
288
289 boot->NumFiles = 1;
290 boot->NumFree = 0;
291
292 free(backup);
293 free(block);
294 free(fsinfo);
295 return ret;
296fail:
297 free(backup);
298 free(block);
299 free(fsinfo);
300 return FSFATAL16;
301}
302
303int
304writefsinfo(int dosfs, struct bootblock *boot)
305{
306 u_char *fsinfo = NULL((void *)0);
307 int secsize = lab.d_secsize, fsinfosz;
308 off_t o;
309 ssize_t n;
310
311 if ((2 * DOSBOOTBLOCKSIZE512) < secsize)
312 fsinfosz = secsize;
313 else
314 fsinfosz = 2 * secsize;
315
316 fsinfo = malloc(fsinfosz);
317 if (fsinfo == NULL((void *)0)) {
318 xperror("could not malloc fsinfo block");
319 goto fail;
320 }
321
322 o = lseek(dosfs, boot->FSInfo * secsize, SEEK_SET0);
323 if (o == -1 || o != boot->FSInfo * secsize) {
324 xperror("could not seek fsinfo block");
325 goto fail;
326 }
327
328 n = read(dosfs, fsinfo, fsinfosz);
329 if (n == -1 || n != fsinfosz) {
330 xperror("could not read fsinfo block");
331 goto fail;
332 }
333
334 fsinfo[0x1e8] = (u_char)boot->FSFree;
335 fsinfo[0x1e9] = (u_char)(boot->FSFree >> 8);
336 fsinfo[0x1ea] = (u_char)(boot->FSFree >> 16);
337 fsinfo[0x1eb] = (u_char)(boot->FSFree >> 24);
338 fsinfo[0x1ec] = (u_char)boot->FSNext;
339 fsinfo[0x1ed] = (u_char)(boot->FSNext >> 8);
340 fsinfo[0x1ee] = (u_char)(boot->FSNext >> 16);
341 fsinfo[0x1ef] = (u_char)(boot->FSNext >> 24);
342
343 o = lseek(dosfs, o, SEEK_SET0);
344 if (o == -1 || o != boot->FSInfo * boot->BytesPerSec) {
345 xperror("Unable to seek FSInfo");
346 goto fail;
347 }
348 n = write(dosfs, fsinfo, fsinfosz);
349 if (n == -1 || n != fsinfosz) {
350 xperror("Unable to write FSInfo");
351 goto fail;
352 }
353
354 free(fsinfo);
355
356 /*
357 * Technically, we should return FSBOOTMOD here.
358 *
359 * However, since Win95 OSR2 (the first M$ OS that has
360 * support for FAT32) doesn't maintain the FSINFO block
361 * correctly, it has to be fixed pretty often.
362 *
363 * Therefore, we handle the FSINFO block only informally,
364 * fixing it if necessary, but otherwise ignoring the
365 * fact that it was incorrect.
366 */
367 return 0;
368fail:
369 free(fsinfo);
370 return FSFATAL16;
371}