cgpt: Validate GPT headers before loading them

This CL validates the GPT headers before continue loading its fields.

BRANCH=none
BUG=chromium:422469
TEST=unittest
TEST=cpgt show on a random file. There should be some warnings.
TEST=boot from SD/USB on a device. cgpt show that boot device. It should
     not fail.

Change-Id: I1e5e986cc46620643ec8ec6914fa696a3d04d23a
Reviewed-on: https://chromium-review.googlesource.com/223800
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Commit-Queue: Nam Nguyen <namnguyen@chromium.org>
Tested-by: Nam Nguyen <namnguyen@chromium.org>
This commit is contained in:
Nam T. Nguyen
2014-10-16 15:02:40 -07:00
committed by chrome-internal-fetch
parent 731f8e8a1d
commit d92856ddfa
2 changed files with 60 additions and 21 deletions

View File

@@ -27,6 +27,9 @@
#include "flash_ts_api.h" #include "flash_ts_api.h"
#include "vboot_host.h" #include "vboot_host.h"
static const char kErrorTag[] = "ERROR";
static const char kWarningTag[] = "WARNING";
struct nand_layout nand; struct nand_layout nand;
void EnableNandImage(int bytes_per_page, int pages_per_block, void EnableNandImage(int bytes_per_page, int pages_per_block,
@@ -38,19 +41,29 @@ void EnableNandImage(int bytes_per_page, int pages_per_block,
nand.fts_block_size = fts_block_size; nand.fts_block_size = fts_block_size;
} }
static void LogToStderr(const char *tag, const char *format, va_list ap) {
fprintf(stderr, "%s: ", tag);
vfprintf(stderr, format, ap);
}
void Error(const char *format, ...) { void Error(const char *format, ...) {
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
fprintf(stderr, "ERROR: "); LogToStderr(kErrorTag, format, ap);
vfprintf(stderr, format, ap); va_end(ap);
}
void Warning(const char *format, ...) {
va_list ap;
va_start(ap, format);
LogToStderr(kWarningTag, format, ap);
va_end(ap); va_end(ap);
} }
int CheckValid(const struct drive *drive) { int CheckValid(const struct drive *drive) {
if ((drive->gpt.valid_headers != MASK_BOTH) || if ((drive->gpt.valid_headers != MASK_BOTH) ||
(drive->gpt.valid_entries != MASK_BOTH)) { (drive->gpt.valid_entries != MASK_BOTH)) {
fprintf(stderr, Warning("One of the GPT headers/entries is invalid\n\n");
"\nWARNING: one of the GPT header/entries is invalid\n\n");
return CGPT_FAILED; return CGPT_FAILED;
} }
return CGPT_OK; return CGPT_OK;
@@ -311,24 +324,36 @@ static int GptLoad(struct drive *drive, uint32_t sector_bytes) {
if (CGPT_OK != Load(drive, &drive->gpt.primary_header, if (CGPT_OK != Load(drive, &drive->gpt.primary_header,
GPT_PMBR_SECTORS, GPT_PMBR_SECTORS,
drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) { drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) {
Error("Cannot read primary GPT header\n");
return -1; return -1;
} }
if (CGPT_OK != Load(drive, &drive->gpt.secondary_header, if (CGPT_OK != Load(drive, &drive->gpt.secondary_header,
drive->gpt.drive_sectors - GPT_PMBR_SECTORS, drive->gpt.drive_sectors - GPT_PMBR_SECTORS,
drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) { drive->gpt.sector_bytes, GPT_HEADER_SECTORS)) {
Error("Cannot read secondary GPT header\n");
return -1; return -1;
} }
GptHeader* primary_header = (GptHeader*)drive->gpt.primary_header; GptHeader* primary_header = (GptHeader*)drive->gpt.primary_header;
if (CGPT_OK != Load(drive, &drive->gpt.primary_entries, if (CheckHeader(primary_header, 0, drive->gpt.drive_sectors) == 0) {
primary_header->entries_lba, if (CGPT_OK != Load(drive, &drive->gpt.primary_entries,
drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) { primary_header->entries_lba,
return -1; drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) {
Error("Cannot read primary partition entry array\n");
return -1;
}
} else {
Warning("Primary GPT header is invalid\n");
} }
GptHeader* secondary_header = (GptHeader*)drive->gpt.secondary_header; GptHeader* secondary_header = (GptHeader*)drive->gpt.secondary_header;
if (CGPT_OK != Load(drive, &drive->gpt.secondary_entries, if (CheckHeader(secondary_header, 1, drive->gpt.drive_sectors) == 0) {
secondary_header->entries_lba, if (CGPT_OK != Load(drive, &drive->gpt.secondary_entries,
drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) { secondary_header->entries_lba,
return -1; drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS)) {
Error("Cannot read secondary partition entry array\n");
return -1;
}
} else {
Warning("Secondary GPT header is invalid\n");
} }
return 0; return 0;
} }

View File

@@ -9,16 +9,30 @@
#include "cgptlib_internal.h" #include "cgptlib_internal.h"
#include "vboot_host.h" #include "vboot_host.h"
static void AllocAndClear(uint8_t **buf, uint64_t size) {
if (*buf) {
memset(*buf, 0, size);
} else {
*buf = calloc(1, size);
if (!*buf) {
Error("Cannot allocate %u bytes.\n", size);
abort();
}
}
}
static int GptCreate(struct drive *drive, CgptCreateParams *params) { static int GptCreate(struct drive *drive, CgptCreateParams *params) {
// Erase the data // Allocate and/or erase the data.
memset(drive->gpt.primary_header, 0, // We cannot assume the GPT headers or entry arrays have been allocated
drive->gpt.sector_bytes * GPT_HEADER_SECTORS); // by GptLoad() because those fields might have failed validation checks.
memset(drive->gpt.secondary_header, 0, AllocAndClear(&drive->gpt.primary_header,
drive->gpt.sector_bytes * GPT_HEADER_SECTORS); drive->gpt.sector_bytes * GPT_HEADER_SECTORS);
memset(drive->gpt.primary_entries, 0, AllocAndClear(&drive->gpt.secondary_header,
drive->gpt.sector_bytes * GPT_ENTRIES_SECTORS); drive->gpt.sector_bytes * GPT_HEADER_SECTORS);
memset(drive->gpt.secondary_entries, 0, AllocAndClear(&drive->gpt.primary_entries,
drive->gpt.sector_bytes * GPT_ENTRIES_SECTORS); drive->gpt.sector_bytes * GPT_ENTRIES_SECTORS);
AllocAndClear(&drive->gpt.secondary_entries,
drive->gpt.sector_bytes * GPT_ENTRIES_SECTORS);
drive->gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 | drive->gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2); GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2);