Bug Summary

File:3rdparty/vboot/firmware/lib/gpt_misc.c
Warning:line 36, column 42
Result of 'malloc' is converted to a pointer of type 'uint8_t', which is incompatible with sizeof operand type 'GptEntry'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name gpt_misc.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 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/vboot -resource-dir /opt/xgcc/lib/clang/17 -D CHROMEOS_ENVIRONMENT -D EC_EFS=0 -D EXTERNAL_TPM_CLEAR_REQUEST=0 -D _GNU_SOURCE -D _FILE_OFFSET_BITS=64 -D HAVE_EXECINFO_H -D HAVE_CROSID -D HAVE_NSS -I firmware/include -I firmware/lib/include -I firmware/lib/cgptlib/include -I firmware/lib/tpm_lite/include -I firmware/2lib/include -I host/include -I host/lib/include -I host/lib21/include -internal-isystem /opt/xgcc/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -source-date-epoch 1714465709 -Os -Wno-trigraphs -Wwrite-strings -Wno-format-security -Wno-address-of-packed-member -Wno-unknown-warning -std=gnu11 -fconst-strings -fdebug-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/vboot -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /cb-build/coreboot_scanbuild.0/sharedutils-scanbuildtmp/2024-05-02-073004-2299942-1 -x c firmware/lib/gpt_misc.c
1/* Copyright 2013 The ChromiumOS Authors
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6#include "2common.h"
7#include "2sysincludes.h"
8#include "cgptlib.h"
9#include "cgptlib_internal.h"
10#include "crc32.h"
11#include "gpt.h"
12#include "vboot_api.h"
13
14/**
15 * Allocate and read GPT data from the drive.
16 *
17 * The sector_bytes and gpt_drive_sectors fields should be filled on input. The
18 * primary and secondary header and entries are filled on output.
19 *
20 * Returns 0 if successful, 1 if error.
21 */
22int AllocAndReadGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata)
23{
24 int primary_valid = 0, secondary_valid = 0;
25
26 /* No data to be written yet */
27 gptdata->modified = 0;
28 /* This should get overwritten by GptInit() */
29 gptdata->ignored = 0;
30
31 /* Allocate all buffers */
32 gptdata->primary_header = (uint8_t *)malloc(gptdata->sector_bytes);
33 gptdata->secondary_header =
34 (uint8_t *)malloc(gptdata->sector_bytes);
35 gptdata->primary_entries = (uint8_t *)malloc(GPT_ENTRIES_ALLOC_SIZE(128 * sizeof(GptEntry)));
36 gptdata->secondary_entries = (uint8_t *)malloc(GPT_ENTRIES_ALLOC_SIZE(128 * sizeof(GptEntry)));
Result of 'malloc' is converted to a pointer of type 'uint8_t', which is incompatible with sizeof operand type 'GptEntry'
37
38 /* In some cases we try to validate header1 with entries2 or vice versa,
39 so make sure the entries buffers always got fully initialized. */
40 memset(gptdata->primary_entries, 0, GPT_ENTRIES_ALLOC_SIZE(128 * sizeof(GptEntry)));
41 memset(gptdata->secondary_entries, 0, GPT_ENTRIES_ALLOC_SIZE(128 * sizeof(GptEntry)));
42
43 if (gptdata->primary_header == NULL((void*)0) ||
44 gptdata->secondary_header == NULL((void*)0) ||
45 gptdata->primary_entries == NULL((void*)0) ||
46 gptdata->secondary_entries == NULL((void*)0))
47 return 1;
48
49 /* Read primary header from the drive, skipping the protective MBR */
50 if (0 != VbExDiskRead(disk_handle, 1, 1, gptdata->primary_header)) {
51 VB2_DEBUG("Read error in primary GPT header\n")vb2ex_printf(__func__, "Read error in primary GPT header\n");
52 memset(gptdata->primary_header, 0, gptdata->sector_bytes);
53 }
54
55 /* Only read primary GPT if the primary header is valid */
56 GptHeader* primary_header = (GptHeader*)gptdata->primary_header;
57 if (0 == CheckHeader(primary_header, 0,
58 gptdata->streaming_drive_sectors,
59 gptdata->gpt_drive_sectors,
60 gptdata->flags,
61 gptdata->sector_bytes)) {
62 primary_valid = 1;
63 uint64_t entries_bytes =
64 (uint64_t)primary_header->number_of_entries
65 * primary_header->size_of_entry;
66 uint64_t entries_sectors =
67 (entries_bytes + gptdata->sector_bytes - 1)
68 / gptdata->sector_bytes;
69 if (0 != VbExDiskRead(disk_handle,
70 primary_header->entries_lba,
71 entries_sectors,
72 gptdata->primary_entries)) {
73 VB2_DEBUG("Read error in primary GPT entries\n")vb2ex_printf(__func__, "Read error in primary GPT entries\n");
74 primary_valid = 0;
75 }
76 } else {
77 VB2_DEBUG("Primary GPT header is %s\n",vb2ex_printf(__func__, "Primary GPT header is %s\n", memcmp(primary_header
->signature, "IGNOREME", 8) ? "invalid" : "being ignored")
78 memcmp(primary_header->signature,vb2ex_printf(__func__, "Primary GPT header is %s\n", memcmp(primary_header
->signature, "IGNOREME", 8) ? "invalid" : "being ignored")
79 GPT_HEADER_SIGNATURE_IGNORED,vb2ex_printf(__func__, "Primary GPT header is %s\n", memcmp(primary_header
->signature, "IGNOREME", 8) ? "invalid" : "being ignored")
80 GPT_HEADER_SIGNATURE_SIZE)vb2ex_printf(__func__, "Primary GPT header is %s\n", memcmp(primary_header
->signature, "IGNOREME", 8) ? "invalid" : "being ignored")
81 ? "invalid" : "being ignored")vb2ex_printf(__func__, "Primary GPT header is %s\n", memcmp(primary_header
->signature, "IGNOREME", 8) ? "invalid" : "being ignored")
;
82 }
83
84 /* Read secondary header from the end of the drive */
85 if (0 != VbExDiskRead(disk_handle, gptdata->gpt_drive_sectors - 1, 1,
86 gptdata->secondary_header)) {
87 VB2_DEBUG("Read error in secondary GPT header\n")vb2ex_printf(__func__, "Read error in secondary GPT header\n"
)
;
88 memset(gptdata->secondary_header, 0, gptdata->sector_bytes);
89 }
90
91 /* Only read secondary GPT if the secondary header is valid */
92 GptHeader* secondary_header = (GptHeader*)gptdata->secondary_header;
93 if (0 == CheckHeader(secondary_header, 1,
94 gptdata->streaming_drive_sectors,
95 gptdata->gpt_drive_sectors,
96 gptdata->flags,
97 gptdata->sector_bytes)) {
98 secondary_valid = 1;
99 uint64_t entries_bytes =
100 (uint64_t)secondary_header->number_of_entries
101 * secondary_header->size_of_entry;
102 uint64_t entries_sectors =
103 (entries_bytes + gptdata->sector_bytes - 1)
104 / gptdata->sector_bytes;
105 if (0 != VbExDiskRead(disk_handle,
106 secondary_header->entries_lba,
107 entries_sectors,
108 gptdata->secondary_entries)) {
109 VB2_DEBUG("Read error in secondary GPT entries\n")vb2ex_printf(__func__, "Read error in secondary GPT entries\n"
)
;
110 secondary_valid = 0;
111 }
112 } else {
113 VB2_DEBUG("Secondary GPT header is %s\n",vb2ex_printf(__func__, "Secondary GPT header is %s\n", memcmp
(secondary_header->signature, "IGNOREME", 8) ? "invalid" :
"being ignored")
114 memcmp(secondary_header->signature,vb2ex_printf(__func__, "Secondary GPT header is %s\n", memcmp
(secondary_header->signature, "IGNOREME", 8) ? "invalid" :
"being ignored")
115 GPT_HEADER_SIGNATURE_IGNORED,vb2ex_printf(__func__, "Secondary GPT header is %s\n", memcmp
(secondary_header->signature, "IGNOREME", 8) ? "invalid" :
"being ignored")
116 GPT_HEADER_SIGNATURE_SIZE)vb2ex_printf(__func__, "Secondary GPT header is %s\n", memcmp
(secondary_header->signature, "IGNOREME", 8) ? "invalid" :
"being ignored")
117 ? "invalid" : "being ignored")vb2ex_printf(__func__, "Secondary GPT header is %s\n", memcmp
(secondary_header->signature, "IGNOREME", 8) ? "invalid" :
"being ignored")
;
118 }
119
120 /* Return 0 if least one GPT header was valid */
121 return (primary_valid || secondary_valid) ? 0 : 1;
122}
123
124/**
125 * Write any changes for the GPT data back to the drive, then free the buffers.
126 *
127 * Returns 0 if successful, 1 if error.
128 */
129int WriteAndFreeGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata)
130{
131 int skip_primary = 0;
132 GptHeader *header;
133 uint64_t entries_bytes, entries_sectors;
134 int ret = 1;
135
136 header = (GptHeader *)gptdata->primary_header;
137 if (!header)
138 header = (GptHeader *)gptdata->secondary_header;
139 if (!header)
140 return 1; /* No headers at all, so nothing to write */
141
142 entries_bytes = (uint64_t)header->number_of_entries
143 * header->size_of_entry;
144 entries_sectors = entries_bytes / gptdata->sector_bytes;
145
146 /*
147 * TODO(namnguyen): Preserve padding between primary GPT header and
148 * its entries.
149 */
150 uint64_t entries_lba = GPT_PMBR_SECTORS1 + GPT_HEADER_SECTORS1;
151 if (gptdata->primary_header) {
152 GptHeader *h = (GptHeader *)(gptdata->primary_header);
153 entries_lba = h->entries_lba;
154
155 if (gptdata->ignored & MASK_PRIMARY) {
156 VB2_DEBUG("Not updating primary GPT: "vb2ex_printf(__func__, "Not updating primary GPT: " "marked to be ignored.\n"
)
157 "marked to be ignored.\n")vb2ex_printf(__func__, "Not updating primary GPT: " "marked to be ignored.\n"
)
;
158 skip_primary = 1;
159 } else if (gptdata->modified & GPT_MODIFIED_HEADER10x01) {
160 if (!memcmp(h->signature, GPT_HEADER_SIGNATURE2"CHROMEOS",
161 GPT_HEADER_SIGNATURE_SIZE8)) {
162 VB2_DEBUG("Not updating primary GPT: "vb2ex_printf(__func__, "Not updating primary GPT: " "legacy mode is enabled.\n"
)
163 "legacy mode is enabled.\n")vb2ex_printf(__func__, "Not updating primary GPT: " "legacy mode is enabled.\n"
)
;
164 skip_primary = 1;
165 } else {
166 VB2_DEBUG("Updating GPT header 1\n")vb2ex_printf(__func__, "Updating GPT header 1\n");
167 if (0 != VbExDiskWrite(disk_handle, 1, 1,
168 gptdata->primary_header))
169 goto fail;
170 }
171 }
172 }
173
174 if (gptdata->primary_entries && !skip_primary) {
175 if (gptdata->modified & GPT_MODIFIED_ENTRIES10x04) {
176 VB2_DEBUG("Updating GPT entries 1\n")vb2ex_printf(__func__, "Updating GPT entries 1\n");
177 if (0 != VbExDiskWrite(disk_handle, entries_lba,
178 entries_sectors,
179 gptdata->primary_entries))
180 goto fail;
181 }
182 }
183
184 entries_lba = (gptdata->gpt_drive_sectors - entries_sectors -
185 GPT_HEADER_SECTORS1);
186 if (gptdata->secondary_header && !(gptdata->ignored & MASK_SECONDARY)) {
187 GptHeader *h = (GptHeader *)(gptdata->secondary_header);
188 entries_lba = h->entries_lba;
189 if (gptdata->modified & GPT_MODIFIED_HEADER20x02) {
190 VB2_DEBUG("Updating GPT header 2\n")vb2ex_printf(__func__, "Updating GPT header 2\n");
191 if (0 != VbExDiskWrite(disk_handle,
192 gptdata->gpt_drive_sectors - 1, 1,
193 gptdata->secondary_header))
194 goto fail;
195 }
196 }
197
198 if (gptdata->secondary_entries && !(gptdata->ignored & MASK_SECONDARY)){
199 if (gptdata->modified & GPT_MODIFIED_ENTRIES20x08) {
200 VB2_DEBUG("Updating GPT entries 2\n")vb2ex_printf(__func__, "Updating GPT entries 2\n");
201 if (0 != VbExDiskWrite(disk_handle,
202 entries_lba, entries_sectors,
203 gptdata->secondary_entries))
204 goto fail;
205 }
206 }
207
208 ret = 0;
209
210 fail:
211 /* Avoid leaking memory on disk write failure */
212 if (gptdata->primary_header)
213 free(gptdata->primary_header);
214 if (gptdata->primary_entries)
215 free(gptdata->primary_entries);
216 if (gptdata->secondary_entries)
217 free(gptdata->secondary_entries);
218 if (gptdata->secondary_header)
219 free(gptdata->secondary_header);
220
221 /* Success */
222 return ret;
223}
224
225int IsUnusedEntry(const GptEntry *e)
226{
227 static Guid zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
228 return !memcmp(&zero, (const uint8_t*)(&e->type), sizeof(zero));
229}
230
231/*
232 * Func: GptGetEntrySize
233 * Desc: This function returns size(in lba) of a partition represented by
234 * given GPT entry.
235 */
236size_t GptGetEntrySizeLba(const GptEntry *e)
237{
238 return (e->ending_lba - e->starting_lba + 1);
239}
240
241/*
242 * Func: GptGetEntrySize
243 * Desc: This function returns size(in bytes) of a partition represented by
244 * given GPT entry.
245 */
246size_t GptGetEntrySizeBytes(const GptData *gpt, const GptEntry *e)
247{
248 return GptGetEntrySizeLba(e) * gpt->sector_bytes;
249}