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

Side by Side Diff: drivers/md/dm-bht.c

Issue 6835032: CHROMIUM: verity: don't call page_address on unmapped highmem pages (Closed) Base URL: http://git.chromium.org/git/kernel-next.git@chromeos-2.6.37
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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | drivers/md/dm-verity.c » ('j') | include/linux/dm-bht.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 dm_bht_bin_to_hex(computed, computed_hex, bht->digest_size); 88 dm_bht_bin_to_hex(computed, computed_hex, bht->digest_size);
89 DMERR_LIMIT("%s != %s", given_hex, computed_hex); 89 DMERR_LIMIT("%s != %s", given_hex, computed_hex);
90 } 90 }
91 91
92 /* Used for turning verifiers into computers */ 92 /* Used for turning verifiers into computers */
93 typedef int (*dm_bht_compare_cb)(struct dm_bht *, u8 *, u8 *); 93 typedef int (*dm_bht_compare_cb)(struct dm_bht *, u8 *, u8 *);
94 94
95 /** 95 /**
96 * dm_bht_compute_hash: hashes a page of data 96 * dm_bht_compute_hash: hashes a page of data
97 */ 97 */
98 static int dm_bht_compute_hash(struct dm_bht *bht, const void *block, 98 static int dm_bht_compute_hash(struct dm_bht *bht, struct page *pg,
99 » » » u8 *digest) 99 » » » unsigned int offset, u8 *digest)
100 { 100 {
101 struct hash_desc *hash_desc = &bht->hash_desc[smp_processor_id()]; 101 struct hash_desc *hash_desc = &bht->hash_desc[smp_processor_id()];
102 struct scatterlist sg; 102 struct scatterlist sg;
103 103
104 /* TODO(msb): Once we supporting block_size < PAGE_SIZE, change this to:
105 * offset_into_page + length < page_size
106 * For now just check that block is page-aligned.
107 */
108 /*
109 * TODO(msb): Re-enable once user-space code is modified to use
110 * aligned buffers.
111 * BUG_ON(!IS_ALIGNED((uintptr_t)block, PAGE_SIZE));
112 */
113
114 sg_init_table(&sg, 1); 104 sg_init_table(&sg, 1);
115 » sg_set_buf(&sg, block, PAGE_SIZE); 105 » sg_set_page(&sg, pg, PAGE_SIZE, 0);
Will Drewry 2011/04/13 20:19:30 should 0 be the new offset argument? Then the comm
116 /* Note, this is synchronous. */ 106 /* Note, this is synchronous. */
117 if (crypto_hash_init(hash_desc)) { 107 if (crypto_hash_init(hash_desc)) {
118 DMCRIT("failed to reinitialize crypto hash (proc:%d)", 108 DMCRIT("failed to reinitialize crypto hash (proc:%d)",
119 smp_processor_id()); 109 smp_processor_id());
120 return -EINVAL; 110 return -EINVAL;
121 } 111 }
122 if (crypto_hash_digest(hash_desc, &sg, PAGE_SIZE, digest)) { 112 if (crypto_hash_digest(hash_desc, &sg, PAGE_SIZE, digest)) {
123 DMCRIT("crypto_hash_digest failed"); 113 DMCRIT("crypto_hash_digest failed");
124 return -EINVAL; 114 return -EINVAL;
125 } 115 }
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 } 529 }
540 /* Current entry is claimed for allocation and loading */ 530 /* Current entry is claimed for allocation and loading */
541 node_page = (struct page *) mempool_alloc(bht->entry_pool, 531 node_page = (struct page *) mempool_alloc(bht->entry_pool,
542 GFP_NOIO); 532 GFP_NOIO);
543 if (!node_page) { 533 if (!node_page) {
544 DMCRIT("failed to allocate memory for " 534 DMCRIT("failed to allocate memory for "
545 "entry->nodes from pool"); 535 "entry->nodes from pool");
546 return -ENOMEM; 536 return -ENOMEM;
547 } 537 }
548 /* dm-bht guarantees page-aligned memory for callbacks. */ 538 /* dm-bht guarantees page-aligned memory for callbacks. */
549 entry->nodes = page_address(node_page); 539 entry->nodes = page_address(node_page);
Will Drewry 2011/04/13 20:19:30 Will this call be a problem?
Paul T 2011/04/13 20:47:55 This must assume the page is mapped. If it is not,
Mandeep Singh Baines 2011/04/13 21:11:16 I clarified the description. page_address is OK on
550 /* Let the caller know that not all the data is yet available */ 540 /* Let the caller know that not all the data is yet available */
551 status |= DM_BHT_ENTRY_REQUESTED; 541 status |= DM_BHT_ENTRY_REQUESTED;
552 /* Issue the read callback */ 542 /* Issue the read callback */
553 /* TODO(wad) error check callback here too */ 543 /* TODO(wad) error check callback here too */
554 DMDEBUG("dm_bht_maybe_read_entries(d=%u,ei=%u,count=%u): " 544 DMDEBUG("dm_bht_maybe_read_entries(d=%u,ei=%u,count=%u): "
555 "reading %lu", 545 "reading %lu",
556 depth, index, count, 546 depth, index, count,
557 (unsigned long)(entry - level->entries)); 547 (unsigned long)(entry - level->entries));
558 bht->read_cb(ctx, /* external context */ 548 bht->read_cb(ctx, /* external context */
559 current_sector, /* starting sector */ 549 current_sector, /* starting sector */
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 } 636 }
647 /* Could do a cmpxchg, but this should be safe. */ 637 /* Could do a cmpxchg, but this should be safe. */
648 atomic_set(&bht->root_state, DM_BHT_ENTRY_VERIFIED); 638 atomic_set(&bht->root_state, DM_BHT_ENTRY_VERIFIED);
649 return 0; 639 return 0;
650 } 640 }
651 641
652 /* dm_bht_verify_path 642 /* dm_bht_verify_path
653 * Verifies the path. Returns 0 on ok. 643 * Verifies the path. Returns 0 on ok.
654 */ 644 */
655 static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index, 645 static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index,
656 » » » const void *block) 646 » » » struct page *pg, unsigned int offset)
657 { 647 {
658 unsigned int depth = bht->depth; 648 unsigned int depth = bht->depth;
659 struct dm_bht_entry *entry; 649 struct dm_bht_entry *entry;
660 int state; 650 int state;
661 651
662 do { 652 do {
663 u8 digest[DM_BHT_MAX_DIGEST_SIZE]; 653 u8 digest[DM_BHT_MAX_DIGEST_SIZE];
664 u8 *node; 654 u8 *node;
665 655
666 /* Need to check that the hash of the current block is accurate 656 /* Need to check that the hash of the current block is accurate
667 * in its parent. 657 * in its parent.
668 */ 658 */
669 entry = dm_bht_get_entry(bht, depth - 1, block_index); 659 entry = dm_bht_get_entry(bht, depth - 1, block_index);
670 state = atomic_read(&entry->state); 660 state = atomic_read(&entry->state);
671 /* This call is only safe if all nodes along the path 661 /* This call is only safe if all nodes along the path
672 * are already populated (i.e. READY) via dm_bht_populate. 662 * are already populated (i.e. READY) via dm_bht_populate.
673 */ 663 */
674 BUG_ON(state < DM_BHT_ENTRY_READY); 664 BUG_ON(state < DM_BHT_ENTRY_READY);
675 node = dm_bht_get_node(bht, entry, depth, block_index); 665 node = dm_bht_get_node(bht, entry, depth, block_index);
676 666
677 » » if (dm_bht_compute_hash(bht, block, digest) || 667 » » if (dm_bht_compute_hash(bht, pg, offset, digest) ||
678 dm_bht_compare_hash(bht, digest, node)) 668 dm_bht_compare_hash(bht, digest, node))
679 goto mismatch; 669 goto mismatch;
680 670
681 /* Keep the containing block of hashes to be verified in the 671 /* Keep the containing block of hashes to be verified in the
682 * next pass. 672 * next pass.
683 */ 673 */
684 » » block = entry->nodes; 674 » » pg = virt_to_page(entry->nodes);
Will Drewry 2011/04/13 20:19:30 Hrm should we yet-again convert nodes back to a st
Mandeep Singh Baines 2011/04/13 21:11:16 The virt_to_page here is safe because we did not u
675 » » offset = 0;
685 } while (--depth > 0 && state != DM_BHT_ENTRY_VERIFIED); 676 } while (--depth > 0 && state != DM_BHT_ENTRY_VERIFIED);
686 677
687 /* Mark path to leaf as verified. */ 678 /* Mark path to leaf as verified. */
688 for (depth++; depth < bht->depth; depth++) { 679 for (depth++; depth < bht->depth; depth++) {
689 entry = dm_bht_get_entry(bht, depth, block_index); 680 entry = dm_bht_get_entry(bht, depth, block_index);
690 /* At this point, entry can only be in VERIFIED or READY state. 681 /* At this point, entry can only be in VERIFIED or READY state.
691 * So it is safe to use atomic_set instead of atomic_cmpxchg. 682 * So it is safe to use atomic_set instead of atomic_cmpxchg.
692 */ 683 */
693 atomic_set(&entry->state, DM_BHT_ENTRY_VERIFIED); 684 atomic_set(&entry->state, DM_BHT_ENTRY_VERIFIED);
694 } 685 }
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
769 atomic_set(&entry->state, DM_BHT_ENTRY_READY); 760 atomic_set(&entry->state, DM_BHT_ENTRY_READY);
770 } else if (state <= DM_BHT_ENTRY_ERROR) { 761 } else if (state <= DM_BHT_ENTRY_ERROR) {
771 DMCRIT("leaf entry for block %u is invalid", 762 DMCRIT("leaf entry for block %u is invalid",
772 block_index); 763 block_index);
773 return state; 764 return state;
774 } else if (state == DM_BHT_ENTRY_PENDING) { 765 } else if (state == DM_BHT_ENTRY_PENDING) {
775 DMERR("leaf data is pending for block %u", block_index); 766 DMERR("leaf data is pending for block %u", block_index);
776 return 1; 767 return 1;
777 } 768 }
778 769
779 » dm_bht_compute_hash(bht, block_data, 770 » dm_bht_compute_hash(bht, virt_to_page(block_data), 0,
Olof Johansson 2011/04/13 21:11:57 Currently block_data is guaranteed to be page alig
780 dm_bht_node(bht, entry, node_index)); 771 dm_bht_node(bht, entry, node_index));
781 return 0; 772 return 0;
782 } 773 }
783 EXPORT_SYMBOL(dm_bht_store_block); 774 EXPORT_SYMBOL(dm_bht_store_block);
784 775
785 /** 776 /**
786 * dm_bht_zeroread_callback - read callback which always returns 0s 777 * dm_bht_zeroread_callback - read callback which always returns 0s
787 * @ctx: ignored 778 * @ctx: ignored
788 * @start: ignored 779 * @start: ignored
789 * @data: buffer to write 0s to 780 * @data: buffer to write 0s to
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 goto out; 830 goto out;
840 } 831 }
841 832
842 for (i = 0; i < level->count; i++, entry++) { 833 for (i = 0; i < level->count; i++, entry++) {
843 unsigned int count = bht->node_count; 834 unsigned int count = bht->node_count;
844 if (i == (level->count - 1)) 835 if (i == (level->count - 1))
845 count = child_level->count % bht->node_count; 836 count = child_level->count % bht->node_count;
846 if (count == 0) 837 if (count == 0)
847 count = bht->node_count; 838 count = bht->node_count;
848 for (j = 0; j < count; j++, child++) { 839 for (j = 0; j < count; j++, child++) {
849 » » » » u8 *block = child->nodes; 840 » » » » struct page *pg = virt_to_page(child->nodes);
850 u8 *digest = dm_bht_node(bht, entry, j); 841 u8 *digest = dm_bht_node(bht, entry, j);
851 842
852 » » » » r = dm_bht_compute_hash(bht, block, digest); 843 » » » » r = dm_bht_compute_hash(bht, pg, 0, digest);
Olof Johansson 2011/04/13 21:11:57 Same here, should probably compute offset?
853 if (r) { 844 if (r) {
854 DMERR("Failed to update (d=%u,i=%u)", 845 DMERR("Failed to update (d=%u,i=%u)",
855 depth, i); 846 depth, i);
856 goto out; 847 goto out;
857 } 848 }
858 } 849 }
859 } 850 }
860 } 851 }
861 /* Don't forget the root digest! */ 852 /* Don't forget the root digest! */
862 DMDEBUG("Calling verify_root with update_hash"); 853 DMDEBUG("Calling verify_root with update_hash");
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 * @bht: pointer to a dm_bht_create()d bht 1010 * @bht: pointer to a dm_bht_create()d bht
1020 * @block_index:specific block data is expected from 1011 * @block_index:specific block data is expected from
1021 * @block: virtual address of the block data in memory 1012 * @block: virtual address of the block data in memory
1022 * (must be aligned to block size) 1013 * (must be aligned to block size)
1023 * 1014 *
1024 * Returns 0 on success, 1 on missing data, and a negative error 1015 * Returns 0 on success, 1 on missing data, and a negative error
1025 * code on verification failure. All supporting functions called 1016 * code on verification failure. All supporting functions called
1026 * should return similarly. 1017 * should return similarly.
1027 */ 1018 */
1028 int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index, 1019 int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index,
1029 » » » const void *block) 1020 » » » struct page *pg, unsigned int offset)
1030 { 1021 {
1031 int r = 0; 1022 int r = 0;
1032 1023
1033 /* Make sure that the root has been verified */ 1024 /* Make sure that the root has been verified */
1034 if (atomic_read(&bht->root_state) != DM_BHT_ENTRY_VERIFIED) { 1025 if (atomic_read(&bht->root_state) != DM_BHT_ENTRY_VERIFIED) {
1035 r = dm_bht_verify_root(bht, dm_bht_compare_hash); 1026 r = dm_bht_verify_root(bht, dm_bht_compare_hash);
1036 if (r) { 1027 if (r) {
1037 DMERR_LIMIT("Failed to verify root: %d", r); 1028 DMERR_LIMIT("Failed to verify root: %d", r);
1038 goto out; 1029 goto out;
1039 } 1030 }
1040 } 1031 }
1041 1032
1042 /* Now check levels in between */ 1033 /* Now check levels in between */
1043 » r = dm_bht_verify_path(bht, block_index, block); 1034 » r = dm_bht_verify_path(bht, block_index, pg, offset);
1044 if (r) 1035 if (r)
1045 DMERR_LIMIT("Failed to verify block: %u (%d)", block_index, r); 1036 DMERR_LIMIT("Failed to verify block: %u (%d)", block_index, r);
1046 1037
1047 out: 1038 out:
1048 return r; 1039 return r;
1049 } 1040 }
1050 EXPORT_SYMBOL(dm_bht_verify_block); 1041 EXPORT_SYMBOL(dm_bht_verify_block);
1051 1042
1052 /** 1043 /**
1053 * dm_bht_destroy - cleans up all memory used by @bht 1044 * dm_bht_destroy - cleans up all memory used by @bht
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1181 if (!bht->root_digest) { 1172 if (!bht->root_digest) {
1182 DMERR("no root digest exists to export"); 1173 DMERR("no root digest exists to export");
1183 if (available > 0) 1174 if (available > 0)
1184 *hexdigest = 0; 1175 *hexdigest = 0;
1185 return -1; 1176 return -1;
1186 } 1177 }
1187 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); 1178 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size);
1188 return 0; 1179 return 0;
1189 } 1180 }
1190 EXPORT_SYMBOL(dm_bht_root_hexdigest); 1181 EXPORT_SYMBOL(dm_bht_root_hexdigest);
OLDNEW
« no previous file with comments | « no previous file | drivers/md/dm-verity.c » ('j') | include/linux/dm-bht.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698