From 84b968f1ee85e65c1c2a2f8bf0120240247c379c Mon Sep 17 00:00:00 2001 From: Sami Tolvanen Date: Wed, 19 Oct 2016 15:58:13 -0700 Subject: libfec: correct verity table only if it's invalid To increase reliability in the case where part of the partition is corrupt and error correction might fail, attempt to use raw verity table before the corrected one. Bug: 32288104 Test: tested on angler Change-Id: I201fdc6162c87b1808979486df5707d683a6d20c (cherry picked from commit b5afa97f093e0b87614cb9e96a754f7c0e169c4f) --- libfec/fec_verity.cpp | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/libfec/fec_verity.cpp b/libfec/fec_verity.cpp index 5dea53dd..3f636dd0 100644 --- a/libfec/fec_verity.cpp +++ b/libfec/fec_verity.cpp @@ -312,6 +312,11 @@ static int verify_tree(fec_handle *f, const uint8_t *root) debug("valid"); + if (v->hash) { + delete[] v->hash; + v->hash = NULL; + } + v->hash = data_hashes.release(); return 0; } @@ -319,7 +324,7 @@ static int verify_tree(fec_handle *f, const uint8_t *root) /* reads, corrects and parses the verity table, validates parameters, and if `f->flags' does not have `FEC_VERITY_DISABLE' set, calls `verify_tree' to load and validate the hash tree */ -static int parse_table(fec_handle *f, uint64_t offset, uint32_t size) +static int parse_table(fec_handle *f, uint64_t offset, uint32_t size, bool useecc) { check(f); check(size >= VERITY_MIN_TABLE_SIZE); @@ -335,8 +340,13 @@ static int parse_table(fec_handle *f, uint64_t offset, uint32_t size) return -1; } - if (fec_pread(f, table.get(), size, offset) != (ssize_t)size) { - error("failed to read verity table: %s", strerror(errno)); + if (!useecc) { + if (!raw_pread(f, table.get(), size, offset)) { + error("failed to read verity table: %s", strerror(errno)); + return -1; + } + } else if (fec_pread(f, table.get(), size, offset) != (ssize_t)size) { + error("failed to ecc read verity table: %s", strerror(errno)); return -1; } @@ -430,7 +440,18 @@ static int parse_table(fec_handle *f, uint64_t offset, uint32_t size) check(v->data_blocks == v->hash_start / FEC_BLOCKSIZE); } + if (v->salt) { + delete[] v->salt; + v->salt = NULL; + } + v->salt = salt.release(); + + if (v->table) { + delete[] v->table; + v->table = NULL; + } + v->table = table.release(); if (!(f->flags & FEC_VERITY_DISABLE)) { @@ -589,7 +610,10 @@ int verity_parse_header(fec_handle *f, uint64_t offset) v->metadata_start = offset; - if (parse_table(f, offset + sizeof(v->header), v->header.length) == -1) { + if (parse_table(f, offset + sizeof(v->header), v->header.length, + false) == -1 && + parse_table(f, offset + sizeof(v->header), v->header.length, + true) == -1) { return -1; } -- cgit v1.2.3