From 66b47ba37d3658cceecf30d25edc3becbb692c4a Mon Sep 17 00:00:00 2001 From: Louis Yung-Chieh Lo Date: Fri, 22 Jun 2012 14:44:02 +0800 Subject: [PATCH] cgpt: verify the modifications of 'cgpt add' before effected. Current code only does basic check on parameters, but doesn't validate if it can pass the CheckEntries(). So a user can accidentally break the cgpt table by: cgpt add /dev/sda -i 6 -s 0 # 0 sector is not allowed for a partition. cgpt show /dev/sda ... INVALID_ENTRIES ... This CL checks the new entry before we write it to disk. If new entry is not good, we return fail. Signed-off-by: Louis Yung-Chieh Lo BUG=None TEST=tested on link. % cgpt add /dev/sda -i 6 -s 0 ERROR: cgpt add: A given parameter is not allowed. % cgpt show /dev/sda (no error, and partition 6 is still good) Change-Id: Iee0ad24f73ca12028c0b8a0a5490b67c815488cf Reviewed-on: https://gerrit.chromium.org/gerrit/25914 Commit-Ready: Yung-Chieh Lo Reviewed-by: Yung-Chieh Lo Tested-by: Yung-Chieh Lo --- cgpt/cgpt_add.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/cgpt/cgpt_add.c b/cgpt/cgpt_add.c index a3d0fb9990..f72b4de5b5 100644 --- a/cgpt/cgpt_add.c +++ b/cgpt/cgpt_add.c @@ -9,6 +9,59 @@ #include "cgptlib_internal.h" #include "cgpt_params.h" + +static const char* DumpCgptAddParams(const CgptAddParams *params) { + static char buf[256]; + char tmp[64]; + + buf[0] = 0; + snprintf(tmp, sizeof(tmp), "-i %d ", params->partition); + strncat(buf, tmp, sizeof(buf)); + if (params->label) { + snprintf(tmp, sizeof(tmp), "-l %s ", params->label); + strncat(buf, tmp, sizeof(buf)); + } + if (params->set_begin) { + snprintf(tmp, sizeof(tmp), "-b %llu ", (unsigned long long)params->begin); + strncat(buf, tmp, sizeof(buf)); + } + if (params->set_size) { + snprintf(tmp, sizeof(tmp), "-s %llu ", (unsigned long long)params->size); + strncat(buf, tmp, sizeof(buf)); + } + if (params->set_type) { + GuidToStr(¶ms->type_guid, tmp, sizeof(tmp)); + strncat(buf, "-t ", sizeof(buf)); + strncat(buf, tmp, sizeof(buf)); + strncat(buf, " ", sizeof(buf)); + } + if (params->set_unique) { + GuidToStr(¶ms->unique_guid, tmp, sizeof(tmp)); + strncat(buf, "-u ", sizeof(buf)); + strncat(buf, tmp, sizeof(buf)); + strncat(buf, " ", sizeof(buf)); + } + if (params->set_successful) { + snprintf(tmp, sizeof(tmp), "-S %d ", params->successful); + strncat(buf, tmp, sizeof(buf)); + } + if (params->set_tries) { + snprintf(tmp, sizeof(tmp), "-T %d ", params->tries); + strncat(buf, tmp, sizeof(buf)); + } + if (params->set_priority) { + snprintf(tmp, sizeof(tmp), "-P %d ", params->priority); + strncat(buf, tmp, sizeof(buf)); + } + if (params->set_raw) { + snprintf(tmp, sizeof(tmp), "-A 0x%x ", params->raw_value); + strncat(buf, tmp, sizeof(buf)); + } + + strncat(buf, "\n", sizeof(buf)); + return buf; +} + // This is an internal helper function which assumes no NULL args are passed. // It sets the given attribute values for a single entry at the given index. static void set_entry_attributes(struct drive drive, @@ -177,7 +230,7 @@ int cgpt_add(CgptAddParams *params) { struct drive drive; int gpt_retval; - GptEntry *entry; + GptEntry *entry, backup; uint32_t index; if (params == NULL) @@ -221,6 +274,7 @@ int cgpt_add(CgptAddParams *params) { goto bad; } } + memcpy(&backup, entry, sizeof(backup)); // New partitions must specify type, begin, and size. if (IsZero(&entry->type)) { @@ -265,6 +319,15 @@ int cgpt_add(CgptAddParams *params) { GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2); UpdateCrc(&drive.gpt); + // If the modified entry is illegal, recovery it and return error. + if (0 != CheckEntries((GptEntry*)drive.gpt.primary_entries, + (GptHeader*)drive.gpt.primary_header)) { + memcpy(entry, &backup, sizeof(*entry)); + Error("At least a parameter is not allowed:\n"); + Error(DumpCgptAddParams(params)); + goto bad; + } + // Write it all out. return DriveClose(&drive, 1); @@ -272,4 +335,3 @@ bad: DriveClose(&drive, 0); return CGPT_FAILED; } -