| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 The Chromium OS Authors <chromium-os-dev@chromium.org> | 2 * Copyright (C) 2010 The Chromium OS Authors <chromium-os-dev@chromium.org> |
| 3 * | 3 * |
| 4 * Device-Mapper block hash tree interface. | 4 * Device-Mapper block hash tree interface. |
| 5 * See Documentation/device-mapper/dm-bht.txt for details. | 5 * See Documentation/device-mapper/dm-bht.txt for details. |
| 6 * | 6 * |
| 7 * This file is released under the GPL. | 7 * This file is released under the GPL. |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 #include <asm/atomic.h> | 10 #include <asm/atomic.h> |
| (...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 memcpy(known, computed, bht->digest_size); | 581 memcpy(known, computed, bht->digest_size); |
| 582 #ifdef CONFIG_DM_DEBUG | 582 #ifdef CONFIG_DM_DEBUG |
| 583 dm_bht_bin_to_hex(computed, hex, bht->digest_size); | 583 dm_bht_bin_to_hex(computed, hex, bht->digest_size); |
| 584 DMDEBUG("updating with hash: %s", hex); | 584 DMDEBUG("updating with hash: %s", hex); |
| 585 #endif | 585 #endif |
| 586 return 0; | 586 return 0; |
| 587 } | 587 } |
| 588 | 588 |
| 589 /* Check the disk block against the leaf hash. */ | 589 /* Check the disk block against the leaf hash. */ |
| 590 static int dm_bht_check_block(struct dm_bht *bht, unsigned int block_index, | 590 static int dm_bht_check_block(struct dm_bht *bht, unsigned int block_index, |
| 591 » » » const void *block, int *entry_state) | 591 » » » const void *block) |
| 592 { | 592 { |
| 593 unsigned int depth = bht->depth; | 593 unsigned int depth = bht->depth; |
| 594 struct dm_bht_entry *parent = dm_bht_get_entry(bht, depth - 1, | 594 struct dm_bht_entry *parent = dm_bht_get_entry(bht, depth - 1, |
| 595 block_index); | 595 block_index); |
| 596 u8 digest[DM_BHT_MAX_DIGEST_SIZE]; | 596 u8 digest[DM_BHT_MAX_DIGEST_SIZE]; |
| 597 u8 *node; | 597 u8 *node; |
| 598 | 598 |
| 599 /* This call is only safe if all nodes along the path | 599 /* This call is only safe if all nodes along the path |
| 600 * are already populated (i.e. READY) via dm_bht_populate. | 600 * are already populated (i.e. READY) via dm_bht_populate. |
| 601 */ | 601 */ |
| 602 » *entry_state = atomic_read(&parent->state); | 602 » BUG_ON(atomic_read(&parent->state) < DM_BHT_ENTRY_READY); |
| 603 » BUG_ON(*entry_state < DM_BHT_ENTRY_READY); | |
| 604 | 603 |
| 605 node = dm_bht_get_node(bht, parent, depth, block_index); | 604 node = dm_bht_get_node(bht, parent, depth, block_index); |
| 606 if (dm_bht_compute_hash(bht, virt_to_page(block), digest) || | 605 if (dm_bht_compute_hash(bht, virt_to_page(block), digest) || |
| 607 dm_bht_compare_hash(bht, digest, node)) { | 606 dm_bht_compare_hash(bht, digest, node)) { |
| 608 DMERR("failed to verify entry's hash against parent " | 607 DMERR("failed to verify entry's hash against parent " |
| 609 "(d=%u,bi=%u)", depth, block_index); | 608 "(d=%u,bi=%u)", depth, block_index); |
| 610 return DM_BHT_ENTRY_ERROR_MISMATCH; | 609 return DM_BHT_ENTRY_ERROR_MISMATCH; |
| 611 } | 610 } |
| 612 return 0; | 611 return 0; |
| 613 } | 612 } |
| (...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1050 * @block: virtual address of the block data in memory | 1049 * @block: virtual address of the block data in memory |
| 1051 * | 1050 * |
| 1052 * Returns 0 on success, 1 on missing data, and a negative error | 1051 * Returns 0 on success, 1 on missing data, and a negative error |
| 1053 * code on verification failure. All supporting functions called | 1052 * code on verification failure. All supporting functions called |
| 1054 * should return similarly. | 1053 * should return similarly. |
| 1055 */ | 1054 */ |
| 1056 int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index, | 1055 int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index, |
| 1057 const void *block) | 1056 const void *block) |
| 1058 { | 1057 { |
| 1059 int unverified = 0; | 1058 int unverified = 0; |
| 1060 int entry_state = 0; | |
| 1061 | 1059 |
| 1062 /* Make sure that the root has been verified */ | 1060 /* Make sure that the root has been verified */ |
| 1063 if (atomic_read(&bht->root_state) != DM_BHT_ENTRY_VERIFIED) { | 1061 if (atomic_read(&bht->root_state) != DM_BHT_ENTRY_VERIFIED) { |
| 1064 unverified = dm_bht_verify_root(bht, dm_bht_compare_hash); | 1062 unverified = dm_bht_verify_root(bht, dm_bht_compare_hash); |
| 1065 if (unverified) { | 1063 if (unverified) { |
| 1066 DMERR_LIMIT("Failed to verify root: %d", unverified); | 1064 DMERR_LIMIT("Failed to verify root: %d", unverified); |
| 1067 return unverified; | 1065 return unverified; |
| 1068 } | 1066 } |
| 1069 } | 1067 } |
| 1070 | 1068 |
| 1071 /* Now check that the digest supplied matches the leaf hash */ | 1069 /* Now check that the digest supplied matches the leaf hash */ |
| 1072 » unverified = dm_bht_check_block(bht, block_index, block, &entry_state); | 1070 » unverified = dm_bht_check_block(bht, block_index, block); |
| 1073 if (unverified) { | 1071 if (unverified) { |
| 1074 DMERR_LIMIT("Block check failed for %u: %d", block_index, | 1072 DMERR_LIMIT("Block check failed for %u: %d", block_index, |
| 1075 unverified); | 1073 unverified); |
| 1076 return unverified; | 1074 return unverified; |
| 1077 } | 1075 } |
| 1078 | 1076 |
| 1079 /* If the entry which contains the block hash is marked verified, then | |
| 1080 * it means that its hash has been check with the parent. In addition, | |
| 1081 * since that is only possible via verify_path, it transitively means | |
| 1082 * it is verified to the root of the tree. If the depth is 1, then it | |
| 1083 * means the entry was verified during root verification. | |
| 1084 */ | |
| 1085 if (entry_state == DM_BHT_ENTRY_VERIFIED || bht->depth == 1) | |
| 1086 return unverified; | |
| 1087 | |
| 1088 /* Now check levels in between */ | 1077 /* Now check levels in between */ |
| 1089 unverified = dm_bht_verify_path(bht, block_index); | 1078 unverified = dm_bht_verify_path(bht, block_index); |
| 1090 if (unverified) | 1079 if (unverified) |
| 1091 DMERR_LIMIT("Failed to verify intermediary nodes for block: %u (
%d)", | 1080 DMERR_LIMIT("Failed to verify intermediary nodes for block: %u (
%d)", |
| 1092 block_index, unverified); | 1081 block_index, unverified); |
| 1093 return unverified; | 1082 return unverified; |
| 1094 } | 1083 } |
| 1095 EXPORT_SYMBOL(dm_bht_verify_block); | 1084 EXPORT_SYMBOL(dm_bht_verify_block); |
| 1096 | 1085 |
| 1097 /** | 1086 /** |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1250 DMERR("no root digest exists to export"); | 1239 DMERR("no root digest exists to export"); |
| 1251 if (available > 0) | 1240 if (available > 0) |
| 1252 *hexdigest = 0; | 1241 *hexdigest = 0; |
| 1253 return -1; | 1242 return -1; |
| 1254 } | 1243 } |
| 1255 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); | 1244 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); |
| 1256 return 0; | 1245 return 0; |
| 1257 } | 1246 } |
| 1258 EXPORT_SYMBOL(dm_bht_root_hexdigest); | 1247 EXPORT_SYMBOL(dm_bht_root_hexdigest); |
| 1259 | 1248 |
| OLD | NEW |