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

Unified Diff: dm-bht.c

Issue 6880209: verity: remove special-case logic for the root node (Closed) Base URL: http://git.chromium.org/git/dm-verity.git@master
Patch Set: Created 9 years, 8 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 | « dm-bht.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dm-bht.c
diff --git a/dm-bht.c b/dm-bht.c
index 1b53ffcaf5f623f466fbc931f471066ce3a09255..d2541603b043575463283bb3797947f9a061d428 100644
--- a/dm-bht.c
+++ b/dm-bht.c
@@ -241,11 +241,6 @@ int dm_bht_create(struct dm_bht *bht, unsigned int block_count,
status = -ENOMEM;
goto bad_root_digest_alloc;
}
- /* We use the same defines for root state but just:
- * UNALLOCATED, REQUESTED, and VERIFIED since the workflow is
- * different.
- */
- atomic_set(&bht->root_state, DM_BHT_ENTRY_UNALLOCATED);
/* Configure the tree */
bht->block_count = block_count;
@@ -533,84 +528,6 @@ static int dm_bht_compare_hash(struct dm_bht *bht, u8 *known, u8 *computed)
return memcmp(known, computed, bht->digest_size);
}
-static int dm_bht_update_hash(struct dm_bht *bht, u8 *known, u8 *computed)
-{
-#ifdef CONFIG_DM_DEBUG
- u8 hex[DM_BHT_MAX_DIGEST_SIZE * 2 + 1];
-#endif
- memcpy(known, computed, bht->digest_size);
-#ifdef CONFIG_DM_DEBUG
- dm_bht_bin_to_hex(computed, hex, bht->digest_size);
- DMDEBUG("updating with hash: %s", hex);
-#endif
- return 0;
-}
-
-/* Walk all entries at level 0 to compute the root digest.
- * 0 on success.
- */
-static int dm_bht_compute_root(struct dm_bht *bht, u8 *digest)
-{
- struct dm_bht_entry *entry;
- unsigned int count;
- struct scatterlist sg; /* feeds digest() */
- struct hash_desc *hash_desc;
- hash_desc = &bht->hash_desc[smp_processor_id()];
- entry = bht->levels[0].entries;
-
- if (crypto_hash_init(hash_desc)) {
- DMCRIT("failed to reinitialize crypto hash (proc:%d)",
- smp_processor_id());
- return -EINVAL;
- }
-
- /* Point the scatterlist to the entries, then compute the digest */
- for (count = 0; count < bht->levels[0].count; ++count, ++entry) {
- if (atomic_read(&entry->state) <= DM_BHT_ENTRY_PENDING) {
- DMCRIT("data not ready to compute root: %u",
- count);
- return 1;
- }
- sg_init_table(&sg, 1);
- sg_set_buf(&sg, entry->nodes, PAGE_SIZE);
- if (crypto_hash_update(hash_desc, &sg, PAGE_SIZE)) {
- DMCRIT("Failed to update crypto hash");
- return -EINVAL;
- }
- }
-
- if (crypto_hash_final(hash_desc, digest)) {
- DMCRIT("Failed to compute final digest");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int dm_bht_verify_root(struct dm_bht *bht,
- dm_bht_compare_cb compare_cb)
-{
- int status = 0;
- u8 digest[DM_BHT_MAX_DIGEST_SIZE];
- if (atomic_read(&bht->root_state) == DM_BHT_ENTRY_VERIFIED)
- return 0;
- status = dm_bht_compute_root(bht, digest);
- if (status) {
- DMCRIT("Failed to compute root digest for verification");
- return status;
- }
- DMDEBUG("root computed");
- status = compare_cb(bht, bht->root_digest, digest);
- if (status) {
- DMCRIT("invalid root digest: %d", status);
- dm_bht_log_mismatch(bht, bht->root_digest, digest);
- return DM_BHT_ENTRY_ERROR_MISMATCH;
- }
- /* Could do a cmpxchg, but this should be safe. */
- atomic_set(&bht->root_state, DM_BHT_ENTRY_VERIFIED);
- return 0;
-}
-
/* dm_bht_verify_path
* Verifies the path. Returns 0 on ok.
*/
@@ -618,13 +535,12 @@ static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index,
struct page *pg, unsigned int offset)
{
unsigned int depth = bht->depth;
+ u8 digest[DM_BHT_MAX_DIGEST_SIZE];
struct dm_bht_entry *entry;
+ u8 *node;
int state;
do {
- u8 digest[DM_BHT_MAX_DIGEST_SIZE];
- u8 *node;
-
/* Need to check that the hash of the current block is accurate
* in its parent.
*/
@@ -647,6 +563,13 @@ static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index,
offset = 0;
} while (--depth > 0 && state != DM_BHT_ENTRY_VERIFIED);
+ if (depth == 0 && state != DM_BHT_ENTRY_VERIFIED) {
+ if (dm_bht_compute_hash(bht, pg, offset, digest) ||
+ dm_bht_compare_hash(bht, digest, bht->root_digest))
+ goto mismatch;
+ atomic_set(&entry->state, DM_BHT_ENTRY_VERIFIED);
+ }
+
/* Mark path to leaf as verified. */
for (depth++; depth < bht->depth; depth++) {
entry = dm_bht_get_entry(bht, depth, block_index);
@@ -660,8 +583,9 @@ static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index,
return 0;
mismatch:
- DMERR("verify_path: failed to verify hash against parent (d=%u,bi=%u)",
- depth, block_index);
+ DMERR_LIMIT("verify_path: failed to verify hash (d=%u,bi=%u)",
+ depth, block_index);
+ dm_bht_log_mismatch(bht, node, digest);
return DM_BHT_ENTRY_ERROR_MISMATCH;
}
@@ -786,7 +710,7 @@ EXPORT_SYMBOL(dm_bht_zeroread_callback);
*/
int dm_bht_compute(struct dm_bht *bht, void *read_cb_ctx)
{
- int depth, r;
+ int depth, r = 0;
for (depth = bht->depth - 2; depth >= 0; depth--) {
struct dm_bht_level *level = dm_bht_get_level(bht, depth);
@@ -821,9 +745,12 @@ int dm_bht_compute(struct dm_bht *bht, void *read_cb_ctx)
}
}
}
- /* Don't forget the root digest! */
- DMDEBUG("Calling verify_root with update_hash");
- r = dm_bht_verify_root(bht, dm_bht_update_hash);
+ r = dm_bht_compute_hash(bht,
+ virt_to_page(bht->levels[0].entries->nodes),
+ 0, bht->root_digest);
+ if (r)
+ DMERR("Failed to update root hash");
+
out:
return r;
}
@@ -890,10 +817,8 @@ bool dm_bht_is_populated(struct dm_bht *bht, unsigned int block_index)
{
unsigned int depth;
- if (atomic_read(&bht->root_state) < DM_BHT_ENTRY_READY)
- return false;
-
- for (depth = bht->depth - 1; depth > 0; depth--) {
+ /* TODO(msb) convert depth to int and avoid ugly cast */
+ for (depth = bht->depth - 1; (int)depth >= 0; depth--) {
struct dm_bht_entry *entry = dm_bht_get_entry(bht, depth,
block_index);
if (atomic_read(&entry->state) < DM_BHT_ENTRY_READY)
@@ -910,66 +835,35 @@ EXPORT_SYMBOL(dm_bht_is_populated);
* @read_cb_ctx:context used for all read_cb calls on this request
* @block_index:specific block data is expected from
*
- * Callers may wish to call dm_bht_populate(0) immediately after initialization
- * to start loading in all the level[0] entries.
+ * Returns negative value on error.
*/
int dm_bht_populate(struct dm_bht *bht, void *read_cb_ctx,
unsigned int block_index)
{
- unsigned int depth;
- struct dm_bht_level *level;
- int populated = 0; /* return value */
- unsigned int entry_index = 0;
- int read_status = 0;
- int root_state = 0;
+ unsigned int depth, entry_index;
+ int status, populated = 0;
- if (block_index >= bht->block_count) {
- DMERR("Request to populate for invalid block: %u",
- block_index);
- return -EIO;
- }
- DMDEBUG("dm_bht_populate(%u)", block_index);
+ BUG_ON(block_index >= bht->block_count);
- /* Load in all of level 0 if the root is unverified */
- root_state = atomic_read(&bht->root_state);
- /* TODO(wad) create a separate io object for the root request which
- * can continue on and be verified and stop making every request
- * check.
- */
- if (root_state != DM_BHT_ENTRY_VERIFIED) {
- DMDEBUG("root data is not yet loaded");
- /* If positive, it means some are pending. */
- populated = dm_bht_maybe_read_entry(bht, read_cb_ctx, 0, 0);
- if (populated < 0) {
- DMCRIT("an error occurred while reading level[0]");
- /* TODO(wad) define std error codes */
- return populated;
- }
- }
+ DMDEBUG("dm_bht_populate(%u)", block_index);
- for (depth = 1; depth < bht->depth; ++depth) {
- level = dm_bht_get_level(bht, depth);
- entry_index = dm_bht_index_at_level(bht, depth,
- block_index);
- DMDEBUG("populate for bi=%u on d=%d ei=%u (max=%u)",
- block_index, depth, entry_index, level->count);
+ for (depth = 0; depth < bht->depth; ++depth) {
+ entry_index = dm_bht_index_at_level(bht, depth, block_index);
+ status = dm_bht_maybe_read_entry(bht, read_cb_ctx, depth,
+ entry_index);
+ if (status < 0)
+ goto read_error;
- /* Except for the root node case, we should only ever need
- * to load one entry along the path.
- */
- read_status = dm_bht_maybe_read_entry(bht, read_cb_ctx,
- depth, entry_index);
- if (unlikely(read_status < 0)) {
- DMCRIT("failure occurred reading entry %u depth %u",
- entry_index, depth);
- return read_status;
- }
/* Accrue return code flags */
- populated |= read_status;
+ populated |= status;
}
- /* All nodes are ready. The hash for the block_index can be verified */
return populated;
+
+read_error:
+ DMCRIT("failure reading entry %u depth %u", entry_index, depth);
+ return status;
+
}
EXPORT_SYMBOL(dm_bht_populate);
@@ -988,26 +882,9 @@ EXPORT_SYMBOL(dm_bht_populate);
int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index,
struct page *pg, unsigned int offset)
{
- int r = 0;
-
BUG_ON(offset != 0);
- /* Make sure that the root has been verified */
- if (atomic_read(&bht->root_state) != DM_BHT_ENTRY_VERIFIED) {
- r = dm_bht_verify_root(bht, dm_bht_compare_hash);
- if (r) {
- DMERR_LIMIT("Failed to verify root: %d", r);
- goto out;
- }
- }
-
- /* Now check levels in between */
- r = dm_bht_verify_path(bht, block_index, pg, offset);
- if (r)
- DMERR_LIMIT("Failed to verify block: %u (%d)", block_index, r);
-
-out:
- return r;
+ return dm_bht_verify_path(bht, block_index, pg, offset);
}
EXPORT_SYMBOL(dm_bht_verify_block);
@@ -1119,10 +996,6 @@ int dm_bht_set_root_hexdigest(struct dm_bht *bht, const u8 *hexdigest)
DMINFO("Set root digest to %s. Parsed as -> ", hexdigest);
dm_bht_log_mismatch(bht, bht->root_digest, bht->root_digest);
#endif
- /* Mark the root as unallocated to ensure that it transitions to
- * requested just in case the levels aren't loaded at this point.
- */
- atomic_set(&bht->root_state, DM_BHT_ENTRY_UNALLOCATED);
return 0;
}
EXPORT_SYMBOL(dm_bht_set_root_hexdigest);
« no previous file with comments | « dm-bht.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698