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

Unified Diff: firmware/lib/vboot_kernel.c

Issue 3130040: Fix LoadKernel() failing to update GPT flags. (Closed) Base URL: ssh://gitrw.chromium.org/vboot_reference.git
Patch Set: 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | firmware/version.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: firmware/lib/vboot_kernel.c
diff --git a/firmware/lib/vboot_kernel.c b/firmware/lib/vboot_kernel.c
index d1d4004b32fb8633fca4bc0b309475ee5d84039d..93ed4d1ec35ac1775eae963de1283fa133d6c359 100644
--- a/firmware/lib/vboot_kernel.c
+++ b/firmware/lib/vboot_kernel.c
@@ -199,7 +199,7 @@ int LoadKernel(LoadKernelParams* params) {
while (GPT_SUCCESS == GptNextKernelEntry(&gpt, &part_start, &part_size)) {
VbKeyBlockHeader* key_block;
VbKernelPreambleHeader* preamble;
- RSAPublicKey* data_key;
+ RSAPublicKey* data_key = NULL;
uint64_t key_version;
uint64_t combined_version;
uint64_t body_offset;
@@ -214,9 +214,9 @@ int LoadKernel(LoadKernelParams* params) {
/* Read the first part of the kernel partition */
if (part_size < kbuf_sectors)
- continue;
+ goto bad_kernel;
if (0 != BootDeviceReadLBA(part_start, kbuf_sectors, kbuf))
- continue;
+ goto bad_kernel;
/* Verify the key block. In developer mode, we ignore the key
* and use only the SHA-512 hash to verify the key block. */
@@ -224,7 +224,7 @@ int LoadKernel(LoadKernelParams* params) {
if ((0 != KeyBlockVerify(key_block, KBUF_SIZE, kernel_subkey,
is_dev && !is_rec))) {
VBDEBUG(("Verifying key block failed.\n"));
- continue;
+ goto bad_kernel;
}
/* Check the key block flags against the current boot mode in normal
@@ -234,13 +234,13 @@ int LoadKernel(LoadKernelParams* params) {
(is_dev ? KEY_BLOCK_FLAG_DEVELOPER_1 :
KEY_BLOCK_FLAG_DEVELOPER_0))) {
VBDEBUG(("Developer flag mismatch.\n"));
- continue;
+ goto bad_kernel;
}
if (!(key_block->key_block_flags &
(is_rec ? KEY_BLOCK_FLAG_RECOVERY_1 :
KEY_BLOCK_FLAG_RECOVERY_0))) {
VBDEBUG(("Recovery flag mismatch.\n"));
- continue;
+ goto bad_kernel;
}
}
@@ -250,13 +250,13 @@ int LoadKernel(LoadKernelParams* params) {
key_version = key_block->data_key.key_version;
if (key_version < (tpm_version >> 16)) {
VBDEBUG(("Key version too old.\n"));
- continue;
+ goto bad_kernel;
}
/* Get the key for preamble/data verification from the key block */
data_key = PublicKeyToRSA(&key_block->data_key);
if (!data_key)
- continue;
+ goto bad_kernel;
/* Verify the preamble, which follows the key block */
preamble = (VbKernelPreambleHeader*)(kbuf + key_block->key_block_size);
@@ -264,8 +264,7 @@ int LoadKernel(LoadKernelParams* params) {
KBUF_SIZE - key_block->key_block_size,
data_key))) {
VBDEBUG(("Preamble verification failed.\n"));
- RSAPublicKeyFree(data_key);
- continue;
+ goto bad_kernel;
}
/* Check for rollback of kernel version. Note this is implicitly
@@ -275,8 +274,7 @@ int LoadKernel(LoadKernelParams* params) {
(preamble->kernel_version & 0xFFFF));
if (combined_version < tpm_version) {
VBDEBUG(("Kernel version too low.\n"));
- RSAPublicKeyFree(data_key);
- continue;
+ goto bad_kernel;
}
VBDEBUG(("Kernel preamble is good.\n"));
@@ -289,22 +287,20 @@ int LoadKernel(LoadKernelParams* params) {
* one; we only needed to look at the versions to check for
* rollback. */
if (-1 != good_partition)
- continue;
+ goto bad_kernel;
Randall Spangler 2010/08/20 21:20:47 Heh, note that we'd previously missed freeing the
/* Verify body load address matches what we expect */
if ((preamble->body_load_address != (size_t)params->kernel_buffer) &&
!(params->boot_flags & BOOT_FLAG_SKIP_ADDR_CHECK)) {
VBDEBUG(("Wrong body load address.\n"));
- RSAPublicKeyFree(data_key);
- continue;
+ goto bad_kernel;
}
/* Verify kernel body starts at a multiple of the sector size. */
body_offset = key_block->key_block_size + preamble->preamble_size;
if (0 != body_offset % blba) {
VBDEBUG(("Kernel body not at multiple of sector size.\n"));
- RSAPublicKeyFree(data_key);
- continue;
+ goto bad_kernel;
}
body_offset_sectors = body_offset / blba;
@@ -312,15 +308,13 @@ int LoadKernel(LoadKernelParams* params) {
body_sectors = (preamble->body_signature.data_size + blba - 1) / blba;
if (body_sectors * blba > params->kernel_buffer_size) {
VBDEBUG(("Kernel body doesn't fit in memory.\n"));
- RSAPublicKeyFree(data_key);
- continue;
+ goto bad_kernel;
}
/* Verify kernel body fits in the partition */
if (body_offset_sectors + body_sectors > part_size) {
VBDEBUG(("Kernel body doesn't fit in partition.\n"));
- RSAPublicKeyFree(data_key);
- continue;
+ goto bad_kernel;
}
/* Read the kernel data */
@@ -328,8 +322,7 @@ int LoadKernel(LoadKernelParams* params) {
body_sectors,
params->kernel_buffer)) {
VBDEBUG(("Unable to read kernel data.\n"));
- RSAPublicKeyFree(data_key);
- continue;
+ goto bad_kernel;
}
/* Verify kernel data */
@@ -337,12 +330,12 @@ int LoadKernel(LoadKernelParams* params) {
params->kernel_buffer_size,
&preamble->body_signature, data_key)) {
VBDEBUG(("Kernel data verification failed.\n"));
- RSAPublicKeyFree(data_key);
- continue;
+ goto bad_kernel;
}
/* Done with the kernel signing key, so can free it now */
RSAPublicKeyFree(data_key);
+ data_key = NULL;
/* If we're still here, the kernel is valid. */
/* Save the first good partition we find; that's the one we'll boot */
@@ -356,6 +349,10 @@ int LoadKernel(LoadKernelParams* params) {
* the dest should be a struct, so we know it's big enough. */
params->bootloader_address = preamble->bootloader_address;
params->bootloader_size = preamble->bootloader_size;
+
+ /* Update GPT to note this is the kernel we're trying */
+ GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_TRY);
+
/* If we're in developer or recovery mode, there's no rollback
* protection, so we can stop at the first valid kernel. */
if (!is_normal) {
@@ -372,6 +369,19 @@ int LoadKernel(LoadKernelParams* params) {
VBDEBUG(("Same kernel version\n"));
break;
}
+
+ /* Continue, so that we skip the error handling code below */
+ continue;
+
+ bad_kernel:
+ /* Handle errors parsing this kernel */
+ if (NULL != data_key)
gauravsh 2010/08/20 21:29:01 this null check is not needed. All the *Free() fun
+ RSAPublicKeyFree(data_key);
+
+ VBDEBUG(("Marking kernel as invalid.\n"));
+ GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_BAD);
+
+
} /* while(GptNextKernelEntry) */
} while(0);
« 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