Bug Summary

File:src/usr.sbin/vmd/fw_cfg.c
Warning:line 462, column 1
Potential leak of memory pointed to by 'data'

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 fw_cfg.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/usr.sbin/vmd/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/usr.sbin/vmd -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/vmd/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/usr.sbin/vmd/fw_cfg.c
1/* $OpenBSD: fw_cfg.c,v 1.7 2023/02/06 20:33:34 dv Exp $ */
2/*
3 * Copyright (c) 2018 Claudio Jeker <claudio@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17#include <sys/types.h>
18#include <sys/uio.h>
19#include <machine/biosvar.h> /* bios_memmap_t */
20#include <machine/vmmvar.h>
21#include <dev/pv/virtioreg.h>
22
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26
27#include "atomicio.h"
28#include "pci.h"
29#include "vmd.h"
30#include "vmm.h"
31#include "fw_cfg.h"
32
33#define FW_CFG_SIGNATURE0x0000 0x0000
34#define FW_CFG_ID0x0001 0x0001
35#define FW_CFG_NOGRAPHIC0x0004 0x0004
36#define FW_CFG_FILE_DIR0x0019 0x0019
37#define FW_CFG_FILE_FIRST0x0020 0x0020
38
39#define FW_CFG_DMA_SIGNATURE0x51454d5520434647ULL 0x51454d5520434647ULL /* QEMU CFG */
40
41struct fw_cfg_dma_access {
42 uint32_t control;
43#define FW_CFG_DMA_ERROR0x0001 0x0001
44#define FW_CFG_DMA_READ0x0002 0x0002
45#define FW_CFG_DMA_SKIP0x0004 0x0004
46#define FW_CFG_DMA_SELECT0x0008 0x0008
47#define FW_CFG_DMA_WRITE0x0010 0x0010 /* not implemented */
48 uint32_t length;
49 uint64_t address;
50};
51
52struct fw_cfg_file {
53 uint32_t size;
54 uint16_t selector;
55 uint16_t reserved;
56 char name[56];
57};
58
59extern char *__progname;
60
61static struct fw_cfg_state {
62 size_t offset;
63 size_t size;
64 uint8_t *data;
65} fw_cfg_state;
66
67static uint64_t fw_cfg_dma_addr;
68
69static bios_memmap_t e820[VMM_MAX_MEM_RANGES16];
70
71static int fw_cfg_select_file(uint16_t);
72static void fw_cfg_file_dir(void);
73
74void
75fw_cfg_init(struct vmop_create_params *vmc)
76{
77 unsigned int sd = 0;
78 size_t i, e820_len = 0;
79 char bootorder[64];
80 const char *bootfmt;
81 int bootidx = -1;
82
83 /* Define e820 memory ranges. */
84 memset(&e820, 0, sizeof(e820));
85 for (i = 0; i < vmc->vmc_params.vcp_nmemranges; i++) {
86 struct vm_mem_range *range = &vmc->vmc_params.vcp_memranges[i];
87 bios_memmap_t *entry = &e820[i];
88 entry->addr = range->vmr_gpa;
89 entry->size = range->vmr_size;
90 if (range->vmr_type == VM_MEM_RAM0)
91 entry->type = BIOS_MAP_FREE0x01;
92 else
93 entry->type = BIOS_MAP_RES0x02;
94 e820_len += sizeof(bios_memmap_t);
95 }
96 fw_cfg_add_file("etc/e820", &e820, e820_len);
97
98 /* do not double print chars on serial port */
99 fw_cfg_add_file("etc/screen-and-debug", &sd, sizeof(sd));
100
101 switch (vmc->vmc_bootdevice) {
102 case VMBOOTDEV_DISK1:
103 bootidx = pci_find_first_device(PCI_PRODUCT_VIRTIO_BLOCK2);
104 bootfmt = "/pci@i0cf8/*@%d\nHALT";
105 break;
106 case VMBOOTDEV_CDROM2:
107 bootidx = pci_find_first_device(PCI_PRODUCT_VIRTIO_SCSI8);
108 bootfmt = "/pci@i0cf8/*@%d/*@0/*@0,40000100\nHALT";
109 break;
110 case VMBOOTDEV_NET3:
111 /* XXX not yet */
112 bootidx = pci_find_first_device(PCI_PRODUCT_VIRTIO_NETWORK1);
113 bootfmt = "HALT";
114 break;
115 }
116 if (bootidx > -1) {
117 snprintf(bootorder, sizeof(bootorder), bootfmt, bootidx);
118 log_debug("%s: bootorder: %s", __func__, bootorder);
119 fw_cfg_add_file("bootorder", bootorder, strlen(bootorder) + 1);
120 }
121}
122
123int
124fw_cfg_dump(int fd)
125{
126 log_debug("%s: sending fw_cfg state", __func__);
127 if (atomicio(vwrite(ssize_t (*)(int, void *, size_t))write, fd, &fw_cfg_dma_addr,
128 sizeof(fw_cfg_dma_addr)) != sizeof(fw_cfg_dma_addr)) {
129 log_warnx("%s: error writing fw_cfg to fd", __func__);
130 return -1;
131 }
132 if (atomicio(vwrite(ssize_t (*)(int, void *, size_t))write, fd, &fw_cfg_state.offset,
133 sizeof(fw_cfg_state.offset)) != sizeof(fw_cfg_state.offset)) {
134 log_warnx("%s: error writing fw_cfg to fd", __func__);
135 return -1;
136 }
137 if (atomicio(vwrite(ssize_t (*)(int, void *, size_t))write, fd, &fw_cfg_state.size,
138 sizeof(fw_cfg_state.size)) != sizeof(fw_cfg_state.size)) {
139 log_warnx("%s: error writing fw_cfg to fd", __func__);
140 return -1;
141 }
142 if (fw_cfg_state.size != 0)
143 if (atomicio(vwrite(ssize_t (*)(int, void *, size_t))write, fd, fw_cfg_state.data,
144 fw_cfg_state.size) != fw_cfg_state.size) {
145 log_warnx("%s: error writing fw_cfg to fd", __func__);
146 return (-1);
147 }
148 return 0;
149}
150
151int
152fw_cfg_restore(int fd)
153{
154 log_debug("%s: receiving fw_cfg state", __func__);
155 if (atomicio(read, fd, &fw_cfg_dma_addr,
156 sizeof(fw_cfg_dma_addr)) != sizeof(fw_cfg_dma_addr)) {
157 log_warnx("%s: error reading fw_cfg from fd", __func__);
158 return -1;
159 }
160 if (atomicio(read, fd, &fw_cfg_state.offset,
161 sizeof(fw_cfg_state.offset)) != sizeof(fw_cfg_state.offset)) {
162 log_warnx("%s: error reading fw_cfg from fd", __func__);
163 return -1;
164 }
165 if (atomicio(read, fd, &fw_cfg_state.size,
166 sizeof(fw_cfg_state.size)) != sizeof(fw_cfg_state.size)) {
167 log_warnx("%s: error reading fw_cfg from fd", __func__);
168 return -1;
169 }
170 fw_cfg_state.data = NULL((void *)0);
171 if (fw_cfg_state.size != 0) {
172 if ((fw_cfg_state.data = malloc(fw_cfg_state.size)) == NULL((void *)0))
173 fatal("%s", __func__);
174 if (atomicio(read, fd, fw_cfg_state.data,
175 fw_cfg_state.size) != fw_cfg_state.size) {
176 log_warnx("%s: error reading fw_cfg from fd", __func__);
177 return -1;
178 }
179 }
180 return 0;
181}
182
183static void
184fw_cfg_reset_state(void)
185{
186 free(fw_cfg_state.data);
187 fw_cfg_state.offset = 0;
188 fw_cfg_state.size = 0;
189 fw_cfg_state.data = NULL((void *)0);
190}
191
192static void
193fw_cfg_set_state(void *data, size_t len)
194{
195 if ((fw_cfg_state.data = malloc(len)) == NULL((void *)0)) {
196 log_warn("%s", __func__);
197 return;
198 }
199 memcpy(fw_cfg_state.data, data, len);
200 fw_cfg_state.size = len;
201 fw_cfg_state.offset = 0;
202}
203
204static void
205fw_cfg_select(uint16_t selector)
206{
207 uint16_t one = 1;
208 uint32_t id = htole32(0x3)((__uint32_t)(0x3));
209
210 fw_cfg_reset_state();
211 switch (selector) {
16
Control jumps to 'case 25:' at line 221
212 case FW_CFG_SIGNATURE0x0000:
213 fw_cfg_set_state("QEMU", 4);
214 break;
215 case FW_CFG_ID0x0001:
216 fw_cfg_set_state(&id, sizeof(id));
217 break;
218 case FW_CFG_NOGRAPHIC0x0004:
219 fw_cfg_set_state(&one, sizeof(one));
220 break;
221 case FW_CFG_FILE_DIR0x0019:
222 fw_cfg_file_dir();
17
Calling 'fw_cfg_file_dir'
223 break;
224 default:
225 if (!fw_cfg_select_file(selector))
226 log_debug("%s: unhandled selector %x",
227 __func__, selector);
228 break;
229 }
230}
231
232static void
233fw_cfg_handle_dma(struct fw_cfg_dma_access *fw)
234{
235 uint32_t len = 0, control = fw->control;
236
237 fw->control = 0;
238 if (control & FW_CFG_DMA_SELECT0x0008) {
13
Assuming the condition is true
14
Taking true branch
239 uint16_t selector = control >> 16;
240 log_debug("%s: selector 0x%04x", __func__, selector);
241 fw_cfg_select(selector);
15
Calling 'fw_cfg_select'
242 }
243
244 /* calculate correct length of operation */
245 if (fw_cfg_state.offset < fw_cfg_state.size)
246 len = fw_cfg_state.size - fw_cfg_state.offset;
247 if (len > fw->length)
248 len = fw->length;
249
250 if (control & FW_CFG_DMA_WRITE0x0010) {
251 fw->control |= FW_CFG_DMA_ERROR0x0001;
252 } else if (control & FW_CFG_DMA_READ0x0002) {
253 if (write_mem(fw->address,
254 fw_cfg_state.data + fw_cfg_state.offset, len)) {
255 log_warnx("%s: write_mem error", __func__);
256 fw->control |= FW_CFG_DMA_ERROR0x0001;
257 }
258 /* clear rest of buffer */
259 if (len < fw->length)
260 if (write_mem(fw->address + len, NULL((void *)0),
261 fw->length - len)) {
262 log_warnx("%s: write_mem error", __func__);
263 fw->control |= FW_CFG_DMA_ERROR0x0001;
264 }
265 }
266 fw_cfg_state.offset += len;
267
268 if (fw_cfg_state.offset == fw_cfg_state.size)
269 fw_cfg_reset_state();
270}
271
272uint8_t
273vcpu_exit_fw_cfg(struct vm_run_params *vrp)
274{
275 uint32_t data = 0;
276 struct vm_exit *vei = vrp->vrp_exit;
277
278 get_input_data(vei, &data);
279
280 switch (vei->vei.vei_port) {
281 case FW_CFG_IO_SELECT0x510:
282 if (vei->vei.vei_dir == VEI_DIR_IN) {
283 log_warnx("%s: fw_cfg: read from selector port "
284 "unsupported", __progname);
285 set_return_data(vei, 0);
286 break;
287 }
288 log_debug("%s: selector 0x%04x", __func__, data);
289 fw_cfg_select(data);
290 break;
291 case FW_CFG_IO_DATA0x511:
292 if (vei->vei.vei_dir == VEI_DIR_OUT) {
293 log_debug("%s: fw_cfg: discarding data written to "
294 "data port", __progname);
295 break;
296 }
297 /* fw_cfg only defines 1-byte reads via IO port */
298 if (fw_cfg_state.offset < fw_cfg_state.size) {
299 set_return_data(vei,
300 fw_cfg_state.data[fw_cfg_state.offset++]);
301 if (fw_cfg_state.offset == fw_cfg_state.size)
302 fw_cfg_reset_state();
303 } else
304 set_return_data(vei, 0);
305 break;
306 }
307
308 return 0xFF;
309}
310
311uint8_t
312vcpu_exit_fw_cfg_dma(struct vm_run_params *vrp)
313{
314 struct fw_cfg_dma_access fw_dma;
315 uint32_t data = 0;
316 struct vm_exit *vei = vrp->vrp_exit;
317
318 if (vei->vei.vei_size != 4) {
1
Assuming field 'vei_size' is equal to 4
2
Taking false branch
319 log_debug("%s: fw_cfg_dma: discarding data written to "
320 "dma addr", __progname);
321 if (vei->vei.vei_dir == VEI_DIR_OUT)
322 fw_cfg_dma_addr = 0;
323 return 0xFF;
324 }
325
326 if (vei->vei.vei_dir == VEI_DIR_OUT) {
3
Assuming field 'vei_dir' is equal to VEI_DIR_OUT
4
Taking true branch
327 get_input_data(vei, &data);
328 switch (vei->vei.vei_port) {
5
Control jumps to 'case 1304:' at line 332
329 case FW_CFG_IO_DMA_ADDR_HIGH0x514:
330 fw_cfg_dma_addr = (uint64_t)be32toh(data)(__uint32_t)(__builtin_constant_p(data) ? (__uint32_t)(((__uint32_t
)(data) & 0xff) << 24 | ((__uint32_t)(data) & 0xff00
) << 8 | ((__uint32_t)(data) & 0xff0000) >> 8
| ((__uint32_t)(data) & 0xff000000) >> 24) : __swap32md
(data))
<< 32;
331 break;
332 case FW_CFG_IO_DMA_ADDR_LOW0x518:
333 fw_cfg_dma_addr |= be32toh(data)(__uint32_t)(__builtin_constant_p(data) ? (__uint32_t)(((__uint32_t
)(data) & 0xff) << 24 | ((__uint32_t)(data) & 0xff00
) << 8 | ((__uint32_t)(data) & 0xff0000) >> 8
| ((__uint32_t)(data) & 0xff000000) >> 24) : __swap32md
(data))
;
6
'?' condition is false
334
335 /* writing least significant half triggers operation */
336 if (read_mem(fw_cfg_dma_addr, &fw_dma, sizeof(fw_dma)))
7
Assuming the condition is false
337 break;
338 /* adjust byteorder */
339 fw_dma.control = be32toh(fw_dma.control)(__uint32_t)(__builtin_constant_p(fw_dma.control) ? (__uint32_t
)(((__uint32_t)(fw_dma.control) & 0xff) << 24 | ((__uint32_t
)(fw_dma.control) & 0xff00) << 8 | ((__uint32_t)(fw_dma
.control) & 0xff0000) >> 8 | ((__uint32_t)(fw_dma.control
) & 0xff000000) >> 24) : __swap32md(fw_dma.control)
)
;
8
Taking false branch
9
'?' condition is false
340 fw_dma.length = be32toh(fw_dma.length)(__uint32_t)(__builtin_constant_p(fw_dma.length) ? (__uint32_t
)(((__uint32_t)(fw_dma.length) & 0xff) << 24 | ((__uint32_t
)(fw_dma.length) & 0xff00) << 8 | ((__uint32_t)(fw_dma
.length) & 0xff0000) >> 8 | ((__uint32_t)(fw_dma.length
) & 0xff000000) >> 24) : __swap32md(fw_dma.length))
;
10
'?' condition is false
341 fw_dma.address = be64toh(fw_dma.address)(__uint64_t)(__builtin_constant_p(fw_dma.address) ? (__uint64_t
)((((__uint64_t)(fw_dma.address) & 0xff) << 56) | (
(__uint64_t)(fw_dma.address) & 0xff00ULL) << 40 | (
(__uint64_t)(fw_dma.address) & 0xff0000ULL) << 24 |
((__uint64_t)(fw_dma.address) & 0xff000000ULL) << 8
| ((__uint64_t)(fw_dma.address) & 0xff00000000ULL) >>
8 | ((__uint64_t)(fw_dma.address) & 0xff0000000000ULL) >>
24 | ((__uint64_t)(fw_dma.address) & 0xff000000000000ULL
) >> 40 | ((__uint64_t)(fw_dma.address) & 0xff00000000000000ULL
) >> 56) : __swap64md(fw_dma.address))
;
11
'?' condition is false
342
343 fw_cfg_handle_dma(&fw_dma);
12
Calling 'fw_cfg_handle_dma'
344
345 /* just write control byte back */
346 data = be32toh(fw_dma.control)(__uint32_t)(__builtin_constant_p(fw_dma.control) ? (__uint32_t
)(((__uint32_t)(fw_dma.control) & 0xff) << 24 | ((__uint32_t
)(fw_dma.control) & 0xff00) << 8 | ((__uint32_t)(fw_dma
.control) & 0xff0000) >> 8 | ((__uint32_t)(fw_dma.control
) & 0xff000000) >> 24) : __swap32md(fw_dma.control)
)
;
347 if (write_mem(fw_cfg_dma_addr, &data, sizeof(data)))
348 break;
349
350 /* done, reset base address */
351 fw_cfg_dma_addr = 0;
352 break;
353 }
354 } else {
355 uint64_t sig = htobe64(FW_CFG_DMA_SIGNATURE)(__uint64_t)(__builtin_constant_p(0x51454d5520434647ULL) ? (__uint64_t
)((((__uint64_t)(0x51454d5520434647ULL) & 0xff) << 56
) | ((__uint64_t)(0x51454d5520434647ULL) & 0xff00ULL) <<
40 | ((__uint64_t)(0x51454d5520434647ULL) & 0xff0000ULL)
<< 24 | ((__uint64_t)(0x51454d5520434647ULL) & 0xff000000ULL
) << 8 | ((__uint64_t)(0x51454d5520434647ULL) & 0xff00000000ULL
) >> 8 | ((__uint64_t)(0x51454d5520434647ULL) & 0xff0000000000ULL
) >> 24 | ((__uint64_t)(0x51454d5520434647ULL) & 0xff000000000000ULL
) >> 40 | ((__uint64_t)(0x51454d5520434647ULL) & 0xff00000000000000ULL
) >> 56) : __swap64md(0x51454d5520434647ULL))
;
356 switch (vei->vei.vei_port) {
357 case FW_CFG_IO_DMA_ADDR_HIGH0x514:
358 set_return_data(vei, sig >> 32);
359 break;
360 case FW_CFG_IO_DMA_ADDR_LOW0x518:
361 set_return_data(vei, sig & 0xffffffff);
362 break;
363 }
364 }
365 return 0xFF;
366}
367
368static uint16_t file_id = FW_CFG_FILE_FIRST0x0020;
369
370struct fw_cfg_file_entry {
371 TAILQ_ENTRY(fw_cfg_file_entry)struct { struct fw_cfg_file_entry *tqe_next; struct fw_cfg_file_entry
**tqe_prev; }
entry;
372 struct fw_cfg_file file;
373 void *data;
374};
375
376TAILQ_HEAD(, fw_cfg_file_entry)struct { struct fw_cfg_file_entry *tqh_first; struct fw_cfg_file_entry
**tqh_last; }
fw_cfg_files =
377 TAILQ_HEAD_INITIALIZER(fw_cfg_files){ ((void *)0), &(fw_cfg_files).tqh_first };
378
379static struct fw_cfg_file_entry *
380fw_cfg_lookup_file(const char *name)
381{
382 struct fw_cfg_file_entry *f;
383
384 TAILQ_FOREACH(f, &fw_cfg_files, entry)for((f) = ((&fw_cfg_files)->tqh_first); (f) != ((void *
)0); (f) = ((f)->entry.tqe_next))
{
385 if (strcmp(name, f->file.name) == 0)
386 return f;
387 }
388 return NULL((void *)0);
389}
390
391void
392fw_cfg_add_file(const char *name, const void *data, size_t len)
393{
394 struct fw_cfg_file_entry *f;
395
396 if (fw_cfg_lookup_file(name))
397 fatalx("%s: fw_cfg: file %s exists", __progname, name);
398
399 if ((f = calloc(sizeof(*f), 1)) == NULL((void *)0))
400 fatal("%s", __func__);
401
402 if ((f->data = malloc(len)) == NULL((void *)0))
403 fatal("%s", __func__);
404
405 if (strlcpy(f->file.name, name, sizeof(f->file.name)) >=
406 sizeof(f->file.name))
407 fatalx("%s: fw_cfg: file name too long", __progname);
408
409 f->file.size = htobe32(len)(__uint32_t)(__builtin_constant_p(len) ? (__uint32_t)(((__uint32_t
)(len) & 0xff) << 24 | ((__uint32_t)(len) & 0xff00
) << 8 | ((__uint32_t)(len) & 0xff0000) >> 8 |
((__uint32_t)(len) & 0xff000000) >> 24) : __swap32md
(len))
;
410 f->file.selector = htobe16(file_id++)(__uint16_t)(__builtin_constant_p(file_id++) ? (__uint16_t)((
(__uint16_t)(file_id++) & 0xffU) << 8 | ((__uint16_t
)(file_id++) & 0xff00U) >> 8) : __swap16md(file_id++
))
;
411 memcpy(f->data, data, len);
412
413 TAILQ_INSERT_TAIL(&fw_cfg_files, f, entry)do { (f)->entry.tqe_next = ((void *)0); (f)->entry.tqe_prev
= (&fw_cfg_files)->tqh_last; *(&fw_cfg_files)->
tqh_last = (f); (&fw_cfg_files)->tqh_last = &(f)->
entry.tqe_next; } while (0)
;
414}
415
416static int
417fw_cfg_select_file(uint16_t id)
418{
419 struct fw_cfg_file_entry *f;
420
421 id = htobe16(id)(__uint16_t)(__builtin_constant_p(id) ? (__uint16_t)(((__uint16_t
)(id) & 0xffU) << 8 | ((__uint16_t)(id) & 0xff00U
) >> 8) : __swap16md(id))
;
422 TAILQ_FOREACH(f, &fw_cfg_files, entry)for((f) = ((&fw_cfg_files)->tqh_first); (f) != ((void *
)0); (f) = ((f)->entry.tqe_next))
423 if (f->file.selector == id) {
424 size_t size = be32toh(f->file.size)(__uint32_t)(__builtin_constant_p(f->file.size) ? (__uint32_t
)(((__uint32_t)(f->file.size) & 0xff) << 24 | ((
__uint32_t)(f->file.size) & 0xff00) << 8 | ((__uint32_t
)(f->file.size) & 0xff0000) >> 8 | ((__uint32_t)
(f->file.size) & 0xff000000) >> 24) : __swap32md
(f->file.size))
;
425 fw_cfg_set_state(f->data, size);
426 log_debug("%s: accessing file %s", __func__,
427 f->file.name);
428 return 1;
429 }
430 return 0;
431}
432
433static void
434fw_cfg_file_dir(void)
435{
436 struct fw_cfg_file_entry *f;
437 struct fw_cfg_file *fp;
438 uint32_t count = 0;
439 uint32_t *data;
440 size_t size;
441
442 TAILQ_FOREACH(f, &fw_cfg_files, entry)for((f) = ((&fw_cfg_files)->tqh_first); (f) != ((void *
)0); (f) = ((f)->entry.tqe_next))
18
Assuming 'f' is equal to null
19
Loop condition is false. Execution continues on line 445
443 count++;
444
445 size = sizeof(count) + count * sizeof(struct fw_cfg_file);
446 if ((data = malloc(size)) == NULL((void *)0))
20
Memory is allocated
21
Assuming the condition is false
447 fatal("%s", __func__);
448 *data = htobe32(count)(__uint32_t)(__builtin_constant_p(count) ? (__uint32_t)(((__uint32_t
)(count) & 0xff) << 24 | ((__uint32_t)(count) &
0xff00) << 8 | ((__uint32_t)(count) & 0xff0000) >>
8 | ((__uint32_t)(count) & 0xff000000) >> 24) : __swap32md
(count))
;
22
Taking false branch
23
'?' condition is false
449 fp = (struct fw_cfg_file *)(data + 1);
450
451 log_debug("%s: file directory with %d files", __func__, count);
452 TAILQ_FOREACH(f, &fw_cfg_files, entry)for((f) = ((&fw_cfg_files)->tqh_first); (f) != ((void *
)0); (f) = ((f)->entry.tqe_next))
{
24
Assuming 'f' is equal to null
25
Loop condition is false. Execution continues on line 461
453 log_debug(" %6dB %04x %s", be32toh(f->file.size)(__uint32_t)(__builtin_constant_p(f->file.size) ? (__uint32_t
)(((__uint32_t)(f->file.size) & 0xff) << 24 | ((
__uint32_t)(f->file.size) & 0xff00) << 8 | ((__uint32_t
)(f->file.size) & 0xff0000) >> 8 | ((__uint32_t)
(f->file.size) & 0xff000000) >> 24) : __swap32md
(f->file.size))
,
454 be16toh(f->file.selector)(__uint16_t)(__builtin_constant_p(f->file.selector) ? (__uint16_t
)(((__uint16_t)(f->file.selector) & 0xffU) << 8 |
((__uint16_t)(f->file.selector) & 0xff00U) >> 8
) : __swap16md(f->file.selector))
, f->file.name);
455 memcpy(fp, &f->file, sizeof(f->file));
456 fp++;
457 }
458
459 /* XXX should sort by name but SeaBIOS does not care */
460
461 fw_cfg_set_state(data, size);
462}
26
Potential leak of memory pointed to by 'data'