Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: firmware/lib/vboot_kernel.c

Issue 3186013: Security fixes for LoadKernel() (Closed) Base URL: ssh://gitrw.chromium.org/vboot_reference.git
Patch Set: Add local var for offset sectors Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | firmware/version.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be 2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file. 3 * found in the LICENSE file.
4 * 4 *
5 * Functions for loading a kernel from disk. 5 * Functions for loading a kernel from disk.
6 * (Firmware portion) 6 * (Firmware portion)
7 */ 7 */
8 8
9 #include "vboot_kernel.h" 9 #include "vboot_kernel.h"
10 10
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 !params->kernel_buffer || 134 !params->kernel_buffer ||
135 !params->kernel_buffer_size) { 135 !params->kernel_buffer_size) {
136 VBDEBUG(("LoadKernel() called with invalid params\n")); 136 VBDEBUG(("LoadKernel() called with invalid params\n"));
137 return LOAD_KERNEL_INVALID; 137 return LOAD_KERNEL_INVALID;
138 } 138 }
139 139
140 /* Initialization */ 140 /* Initialization */
141 kernel_subkey = (VbPublicKey*)params->header_sign_key_blob; 141 kernel_subkey = (VbPublicKey*)params->header_sign_key_blob;
142 blba = params->bytes_per_lba; 142 blba = params->bytes_per_lba;
143 kbuf_sectors = KBUF_SIZE / blba; 143 kbuf_sectors = KBUF_SIZE / blba;
144 if (0 == kbuf_sectors) {
145 VBDEBUG(("LoadKernel() called with sector size > KBUF_SIZE\n"));
146 return LOAD_KERNEL_INVALID;
147 }
148
144 is_dev = (BOOT_FLAG_DEVELOPER & params->boot_flags ? 1 : 0); 149 is_dev = (BOOT_FLAG_DEVELOPER & params->boot_flags ? 1 : 0);
145 is_rec = (BOOT_FLAG_RECOVERY & params->boot_flags ? 1 : 0); 150 is_rec = (BOOT_FLAG_RECOVERY & params->boot_flags ? 1 : 0);
146 is_normal = (!is_dev && !is_rec); 151 is_normal = (!is_dev && !is_rec);
147 152
148 /* Clear output params in case we fail */ 153 /* Clear output params in case we fail */
149 params->partition_number = 0; 154 params->partition_number = 0;
150 params->bootloader_address = 0; 155 params->bootloader_address = 0;
151 params->bootloader_size = 0; 156 params->bootloader_size = 0;
152 157
153 /* Let the TPM know if we're in recovery mode */ 158 /* Let the TPM know if we're in recovery mode */
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 break; 196 break;
192 197
193 /* Loop over candidate kernel partitions */ 198 /* Loop over candidate kernel partitions */
194 while (GPT_SUCCESS == GptNextKernelEntry(&gpt, &part_start, &part_size)) { 199 while (GPT_SUCCESS == GptNextKernelEntry(&gpt, &part_start, &part_size)) {
195 VbKeyBlockHeader* key_block; 200 VbKeyBlockHeader* key_block;
196 VbKernelPreambleHeader* preamble; 201 VbKernelPreambleHeader* preamble;
197 RSAPublicKey* data_key; 202 RSAPublicKey* data_key;
198 uint64_t key_version; 203 uint64_t key_version;
199 uint64_t combined_version; 204 uint64_t combined_version;
200 uint64_t body_offset; 205 uint64_t body_offset;
206 uint64_t body_offset_sectors;
207 uint64_t body_sectors;
201 208
202 VBDEBUG(("Found kernel entry at %" PRIu64 " size %" PRIu64 "\n", 209 VBDEBUG(("Found kernel entry at %" PRIu64 " size %" PRIu64 "\n",
203 part_start, part_size)); 210 part_start, part_size));
204 211
205 /* Found at least one kernel partition. */ 212 /* Found at least one kernel partition. */
206 found_partitions++; 213 found_partitions++;
207 214
208 /* Read the first part of the kernel partition */ 215 /* Read the first part of the kernel partition */
209 if (part_size < kbuf_sectors) 216 if (part_size < kbuf_sectors)
210 continue; 217 continue;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 continue; 299 continue;
293 } 300 }
294 301
295 /* Verify kernel body starts at a multiple of the sector size. */ 302 /* Verify kernel body starts at a multiple of the sector size. */
296 body_offset = key_block->key_block_size + preamble->preamble_size; 303 body_offset = key_block->key_block_size + preamble->preamble_size;
297 if (0 != body_offset % blba) { 304 if (0 != body_offset % blba) {
298 VBDEBUG(("Kernel body not at multiple of sector size.\n")); 305 VBDEBUG(("Kernel body not at multiple of sector size.\n"));
299 RSAPublicKeyFree(data_key); 306 RSAPublicKeyFree(data_key);
300 continue; 307 continue;
301 } 308 }
309 body_offset_sectors = body_offset / blba;
310
311 /* Verify kernel body fits in the buffer */
312 body_sectors = (preamble->body_signature.data_size + blba - 1) / blba;
313 if (body_sectors * blba > params->kernel_buffer_size) {
314 VBDEBUG(("Kernel body doesn't fit in memory.\n"));
315 RSAPublicKeyFree(data_key);
316 continue;
317 }
302 318
303 /* Verify kernel body fits in the partition */ 319 /* Verify kernel body fits in the partition */
304 if (body_offset + preamble->body_signature.data_size > 320 if (body_offset_sectors + body_sectors > part_size) {
305 part_size * blba) {
306 VBDEBUG(("Kernel body doesn't fit in partition.\n")); 321 VBDEBUG(("Kernel body doesn't fit in partition.\n"));
307 RSAPublicKeyFree(data_key); 322 RSAPublicKeyFree(data_key);
308 continue; 323 continue;
309 } 324 }
310 325
311 /* Read the kernel data */ 326 /* Read the kernel data */
312 if (0 != BootDeviceReadLBA( 327 if (0 != BootDeviceReadLBA(part_start + body_offset_sectors,
313 part_start + (body_offset / blba), 328 body_sectors,
314 (preamble->body_signature.data_size + blba - 1) / blba, 329 params->kernel_buffer)) {
315 params->kernel_buffer)) {
316 VBDEBUG(("Unable to read kernel data.\n")); 330 VBDEBUG(("Unable to read kernel data.\n"));
317 RSAPublicKeyFree(data_key); 331 RSAPublicKeyFree(data_key);
318 continue; 332 continue;
319 } 333 }
320 334
321 /* Verify kernel data */ 335 /* Verify kernel data */
322 if (0 != VerifyData((const uint8_t*)params->kernel_buffer, 336 if (0 != VerifyData((const uint8_t*)params->kernel_buffer,
323 params->kernel_buffer_size, 337 params->kernel_buffer_size,
324 &preamble->body_signature, data_key)) { 338 &preamble->body_signature, data_key)) {
325 VBDEBUG(("Kernel data verification failed.\n")); 339 VBDEBUG(("Kernel data verification failed.\n"));
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 /* Success! */ 418 /* Success! */
405 return LOAD_KERNEL_SUCCESS; 419 return LOAD_KERNEL_SUCCESS;
406 } 420 }
407 421
408 // Handle error cases 422 // Handle error cases
409 if (found_partitions) 423 if (found_partitions)
410 return LOAD_KERNEL_INVALID; 424 return LOAD_KERNEL_INVALID;
411 else 425 else
412 return LOAD_KERNEL_NOT_FOUND; 426 return LOAD_KERNEL_NOT_FOUND;
413 } 427 }
OLDNEW
« no previous file with comments | « no previous file | firmware/version.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698