diff options
author | Louis Yung-Chieh Lo <yjlou@chromium.org> | 2010-11-18 09:53:10 +0800 |
---|---|---|
committer | Louis Yung-Chieh Lo <yjlou@chromium.org> | 2010-11-18 09:53:10 +0800 |
commit | 2b23c021f3137427a8b3f00e7702850be6e1c242 (patch) | |
tree | 41236a552e70e816083eec3ed3c14718b01b57da /cgpt/cgpt_common.c | |
parent | fd337168bb4add01ccf9faa64a904052bd36b8ee (diff) | |
download | vboot-2b23c021f3137427a8b3f00e7702850be6e1c242.tar.gz |
Fixing the bug of CGPT when primary entry table is invalid.
http://code.google.com/p/chromium-os/issues/detail?id=9279
This issue disclosed a bug of cgpt. The bug comes from the 'show' command always
reads the primary entry table when '-i partition' is specified. I added an
ANY_VALID constant for GetEntry to automatically select valid entry table.
Also fixed the bugs in cmd_boot.c and cmd_find.c. In cmd_add.c, stop user to
continue if any header/entry table is invalid.
Also fixed the bug that untrusted header size could cause segmentation failure.
Hungte, this is FYI. But welcome to do review.
BUG=chromium-os:9279
TEST=RUNTESTS=1 emerge-x86-generic vboot_reference
Manually tested:
cgpt show /tmp/test -i 1 -b
cgpt show /tmp/test
cgpt add /tmp/test -i 1 -l TEST
cgpt find /tmp/test -l STATE
cgpt boot /tmp/test -i 1
Change-Id: Iaba9c635754096a82b3ec74634af184362d4e264
Change-Id: I6f3e87e3998457676e3388d2a6ed36c0564796d8
Review URL: http://codereview.chromium.org/5115002
Diffstat (limited to 'cgpt/cgpt_common.c')
-rw-r--r-- | cgpt/cgpt_common.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/cgpt/cgpt_common.c b/cgpt/cgpt_common.c index 4b9a5a14..0e466fdc 100644 --- a/cgpt/cgpt_common.c +++ b/cgpt/cgpt_common.c @@ -480,8 +480,16 @@ GptEntry *GetEntry(GptData *gpt, int secondary, uint32_t entry_index) { if (secondary == PRIMARY) { entries = gpt->primary_entries; - } else { + } else if (secondary == SECONDARY) { entries = gpt->secondary_entries; + } else { /* ANY_VALID */ + require(secondary == ANY_VALID); + if (gpt->valid_entries & MASK_PRIMARY) { + entries = gpt->primary_entries; + } else { + require(gpt->valid_entries & MASK_SECONDARY); + entries = gpt->secondary_entries; + } } return (GptEntry*)(&entries[stride * entry_index]); @@ -570,12 +578,12 @@ void UpdateCrc(GptData *gpt) { if (gpt->modified & GPT_MODIFIED_HEADER1) { primary_header->header_crc32 = 0; primary_header->header_crc32 = Crc32( - (const uint8_t *)primary_header, primary_header->size); + (const uint8_t *)primary_header, sizeof(GptHeader)); } if (gpt->modified & GPT_MODIFIED_HEADER2) { secondary_header->header_crc32 = 0; secondary_header->header_crc32 = Crc32( - (const uint8_t *)secondary_header, secondary_header->size); + (const uint8_t *)secondary_header, sizeof(GptHeader)); } } /* Two headers are NOT bitwise identical. For example, my_lba pointers to header @@ -662,14 +670,14 @@ uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers) { return GPT_MODIFIED_HEADER2; } } else if (valid_headers == MASK_PRIMARY) { - memcpy(secondary_header, primary_header, primary_header->size); + memcpy(secondary_header, primary_header, sizeof(GptHeader)); secondary_header->my_lba = gpt->drive_sectors - 1; /* the last sector */ secondary_header->alternate_lba = primary_header->my_lba; secondary_header->entries_lba = secondary_header->my_lba - GPT_ENTRIES_SECTORS; return GPT_MODIFIED_HEADER2; } else if (valid_headers == MASK_SECONDARY) { - memcpy(primary_header, secondary_header, secondary_header->size); + memcpy(primary_header, secondary_header, sizeof(GptHeader)); primary_header->my_lba = GPT_PMBR_SECTOR; /* the second sector on drive */ primary_header->alternate_lba = secondary_header->my_lba; primary_header->entries_lba = primary_header->my_lba + GPT_HEADER_SECTOR; @@ -693,4 +701,3 @@ void PMBRToStr(struct pmbr *pmbr, char *str, unsigned int buflen) { require(snprintf(str, buflen, "PMBR (Boot GUID: %s)", buf) < buflen); } } - |