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

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: Fix. 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') | no next file with comments »
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>
11 #include <asm/page.h> 11 #include <asm/page.h>
12 #include <linux/bitops.h> /* for fls() */ 12 #include <linux/bitops.h> /* for fls() */
13 #include <linux/bug.h> 13 #include <linux/bug.h>
14 #include <linux/cpumask.h> /* nr_cpu_ids */ 14 #include <linux/cpumask.h> /* nr_cpu_ids */
15 /* #define CONFIG_DM_DEBUG 1 */ 15 /* #define CONFIG_DM_DEBUG 1 */
16 #include <linux/device-mapper.h> 16 #include <linux/device-mapper.h>
17 #include <linux/err.h> 17 #include <linux/err.h>
18 #include <linux/errno.h> 18 #include <linux/errno.h>
19 #include <linux/gfp.h> 19 #include <linux/gfp.h>
20 #include <linux/dm-bht.h> 20 #include <linux/dm-bht.h>
21 #include <linux/kernel.h> 21 #include <linux/kernel.h>
22 #include <linux/module.h> 22 #include <linux/module.h>
23 #include <linux/mm_types.h>
23 #include <linux/scatterlist.h> 24 #include <linux/scatterlist.h>
24 #include <linux/slab.h> /* k*alloc */ 25 #include <linux/slab.h> /* k*alloc */
25 #include <linux/string.h> /* memset */ 26 #include <linux/string.h> /* memset */
26 27
27 #define DM_MSG_PREFIX "dm bht" 28 #define DM_MSG_PREFIX "dm bht"
28 29
29 /* For sector formatting. */ 30 /* For sector formatting. */
30 #if defined(_LP64) || defined(__LP64__) || __BITS_PER_LONG == 64 31 #if defined(_LP64) || defined(__LP64__) || __BITS_PER_LONG == 64
31 #define __PRIS_PREFIX "z" 32 #define __PRIS_PREFIX "z"
32 #else 33 #else
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 dm_bht_bin_to_hex(computed, computed_hex, bht->digest_size); 89 dm_bht_bin_to_hex(computed, computed_hex, bht->digest_size);
89 DMERR_LIMIT("%s != %s", given_hex, computed_hex); 90 DMERR_LIMIT("%s != %s", given_hex, computed_hex);
90 } 91 }
91 92
92 /* Used for turning verifiers into computers */ 93 /* Used for turning verifiers into computers */
93 typedef int (*dm_bht_compare_cb)(struct dm_bht *, u8 *, u8 *); 94 typedef int (*dm_bht_compare_cb)(struct dm_bht *, u8 *, u8 *);
94 95
95 /** 96 /**
96 * dm_bht_compute_hash: hashes a page of data 97 * dm_bht_compute_hash: hashes a page of data
97 */ 98 */
98 static int dm_bht_compute_hash(struct dm_bht *bht, const void *block, 99 static int dm_bht_compute_hash(struct dm_bht *bht, struct page *pg,
99 » » » u8 *digest) 100 » » » unsigned int offset, u8 *digest)
100 { 101 {
101 struct hash_desc *hash_desc = &bht->hash_desc[smp_processor_id()]; 102 struct hash_desc *hash_desc = &bht->hash_desc[smp_processor_id()];
102 struct scatterlist sg; 103 struct scatterlist sg;
103 104
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); 105 sg_init_table(&sg, 1);
115 » sg_set_buf(&sg, block, PAGE_SIZE); 106 » sg_set_page(&sg, pg, PAGE_SIZE, offset);
116 /* Note, this is synchronous. */ 107 /* Note, this is synchronous. */
117 if (crypto_hash_init(hash_desc)) { 108 if (crypto_hash_init(hash_desc)) {
118 DMCRIT("failed to reinitialize crypto hash (proc:%d)", 109 DMCRIT("failed to reinitialize crypto hash (proc:%d)",
119 smp_processor_id()); 110 smp_processor_id());
120 return -EINVAL; 111 return -EINVAL;
121 } 112 }
122 if (crypto_hash_digest(hash_desc, &sg, PAGE_SIZE, digest)) { 113 if (crypto_hash_digest(hash_desc, &sg, PAGE_SIZE, digest)) {
123 DMCRIT("crypto_hash_digest failed"); 114 DMCRIT("crypto_hash_digest failed");
124 return -EINVAL; 115 return -EINVAL;
125 } 116 }
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 } 637 }
647 /* Could do a cmpxchg, but this should be safe. */ 638 /* Could do a cmpxchg, but this should be safe. */
648 atomic_set(&bht->root_state, DM_BHT_ENTRY_VERIFIED); 639 atomic_set(&bht->root_state, DM_BHT_ENTRY_VERIFIED);
649 return 0; 640 return 0;
650 } 641 }
651 642
652 /* dm_bht_verify_path 643 /* dm_bht_verify_path
653 * Verifies the path. Returns 0 on ok. 644 * Verifies the path. Returns 0 on ok.
654 */ 645 */
655 static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index, 646 static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index,
656 » » » const void *block) 647 » » » struct page *pg, unsigned int offset)
657 { 648 {
658 unsigned int depth = bht->depth; 649 unsigned int depth = bht->depth;
659 struct dm_bht_entry *entry; 650 struct dm_bht_entry *entry;
660 int state; 651 int state;
661 652
662 do { 653 do {
663 u8 digest[DM_BHT_MAX_DIGEST_SIZE]; 654 u8 digest[DM_BHT_MAX_DIGEST_SIZE];
664 u8 *node; 655 u8 *node;
665 656
666 /* Need to check that the hash of the current block is accurate 657 /* Need to check that the hash of the current block is accurate
667 * in its parent. 658 * in its parent.
668 */ 659 */
669 entry = dm_bht_get_entry(bht, depth - 1, block_index); 660 entry = dm_bht_get_entry(bht, depth - 1, block_index);
670 state = atomic_read(&entry->state); 661 state = atomic_read(&entry->state);
671 /* This call is only safe if all nodes along the path 662 /* This call is only safe if all nodes along the path
672 * are already populated (i.e. READY) via dm_bht_populate. 663 * are already populated (i.e. READY) via dm_bht_populate.
673 */ 664 */
674 BUG_ON(state < DM_BHT_ENTRY_READY); 665 BUG_ON(state < DM_BHT_ENTRY_READY);
675 node = dm_bht_get_node(bht, entry, depth, block_index); 666 node = dm_bht_get_node(bht, entry, depth, block_index);
676 667
677 » » if (dm_bht_compute_hash(bht, block, digest) || 668 » » if (dm_bht_compute_hash(bht, pg, offset, digest) ||
678 dm_bht_compare_hash(bht, digest, node)) 669 dm_bht_compare_hash(bht, digest, node))
679 goto mismatch; 670 goto mismatch;
680 671
681 /* Keep the containing block of hashes to be verified in the 672 /* Keep the containing block of hashes to be verified in the
682 * next pass. 673 * next pass.
683 */ 674 */
684 » » block = entry->nodes; 675 » » pg = virt_to_page(entry->nodes);
676 » » offset = 0;
685 } while (--depth > 0 && state != DM_BHT_ENTRY_VERIFIED); 677 } while (--depth > 0 && state != DM_BHT_ENTRY_VERIFIED);
686 678
687 /* Mark path to leaf as verified. */ 679 /* Mark path to leaf as verified. */
688 for (depth++; depth < bht->depth; depth++) { 680 for (depth++; depth < bht->depth; depth++) {
689 entry = dm_bht_get_entry(bht, depth, block_index); 681 entry = dm_bht_get_entry(bht, depth, block_index);
690 /* At this point, entry can only be in VERIFIED or READY state. 682 /* 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. 683 * So it is safe to use atomic_set instead of atomic_cmpxchg.
692 */ 684 */
693 atomic_set(&entry->state, DM_BHT_ENTRY_VERIFIED); 685 atomic_set(&entry->state, DM_BHT_ENTRY_VERIFIED);
694 } 686 }
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
769 atomic_set(&entry->state, DM_BHT_ENTRY_READY); 761 atomic_set(&entry->state, DM_BHT_ENTRY_READY);
770 } else if (state <= DM_BHT_ENTRY_ERROR) { 762 } else if (state <= DM_BHT_ENTRY_ERROR) {
771 DMCRIT("leaf entry for block %u is invalid", 763 DMCRIT("leaf entry for block %u is invalid",
772 block_index); 764 block_index);
773 return state; 765 return state;
774 } else if (state == DM_BHT_ENTRY_PENDING) { 766 } else if (state == DM_BHT_ENTRY_PENDING) {
775 DMERR("leaf data is pending for block %u", block_index); 767 DMERR("leaf data is pending for block %u", block_index);
776 return 1; 768 return 1;
777 } 769 }
778 770
779 » dm_bht_compute_hash(bht, block_data, 771 » dm_bht_compute_hash(bht, virt_to_page(block_data), 0,
780 dm_bht_node(bht, entry, node_index)); 772 dm_bht_node(bht, entry, node_index));
781 return 0; 773 return 0;
782 } 774 }
783 EXPORT_SYMBOL(dm_bht_store_block); 775 EXPORT_SYMBOL(dm_bht_store_block);
784 776
785 /** 777 /**
786 * dm_bht_zeroread_callback - read callback which always returns 0s 778 * dm_bht_zeroread_callback - read callback which always returns 0s
787 * @ctx: ignored 779 * @ctx: ignored
788 * @start: ignored 780 * @start: ignored
789 * @data: buffer to write 0s to 781 * @data: buffer to write 0s to
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 goto out; 831 goto out;
840 } 832 }
841 833
842 for (i = 0; i < level->count; i++, entry++) { 834 for (i = 0; i < level->count; i++, entry++) {
843 unsigned int count = bht->node_count; 835 unsigned int count = bht->node_count;
844 if (i == (level->count - 1)) 836 if (i == (level->count - 1))
845 count = child_level->count % bht->node_count; 837 count = child_level->count % bht->node_count;
846 if (count == 0) 838 if (count == 0)
847 count = bht->node_count; 839 count = bht->node_count;
848 for (j = 0; j < count; j++, child++) { 840 for (j = 0; j < count; j++, child++) {
849 » » » » u8 *block = child->nodes; 841 » » » » struct page *pg = virt_to_page(child->nodes);
850 u8 *digest = dm_bht_node(bht, entry, j); 842 u8 *digest = dm_bht_node(bht, entry, j);
851 843
852 » » » » r = dm_bht_compute_hash(bht, block, digest); 844 » » » » r = dm_bht_compute_hash(bht, pg, 0, digest);
853 if (r) { 845 if (r) {
854 DMERR("Failed to update (d=%u,i=%u)", 846 DMERR("Failed to update (d=%u,i=%u)",
855 depth, i); 847 depth, i);
856 goto out; 848 goto out;
857 } 849 }
858 } 850 }
859 } 851 }
860 } 852 }
861 /* Don't forget the root digest! */ 853 /* Don't forget the root digest! */
862 DMDEBUG("Calling verify_root with update_hash"); 854 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 1011 * @bht: pointer to a dm_bht_create()d bht
1020 * @block_index:specific block data is expected from 1012 * @block_index:specific block data is expected from
1021 * @block: virtual address of the block data in memory 1013 * @block: virtual address of the block data in memory
1022 * (must be aligned to block size) 1014 * (must be aligned to block size)
1023 * 1015 *
1024 * Returns 0 on success, 1 on missing data, and a negative error 1016 * Returns 0 on success, 1 on missing data, and a negative error
1025 * code on verification failure. All supporting functions called 1017 * code on verification failure. All supporting functions called
1026 * should return similarly. 1018 * should return similarly.
1027 */ 1019 */
1028 int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index, 1020 int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index,
1029 » » » const void *block) 1021 » » » struct page *pg, unsigned int offset)
1030 { 1022 {
1031 int r = 0; 1023 int r = 0;
1032 1024
1025 BUG_ON(offset != 0);
1026
1033 /* Make sure that the root has been verified */ 1027 /* Make sure that the root has been verified */
1034 if (atomic_read(&bht->root_state) != DM_BHT_ENTRY_VERIFIED) { 1028 if (atomic_read(&bht->root_state) != DM_BHT_ENTRY_VERIFIED) {
1035 r = dm_bht_verify_root(bht, dm_bht_compare_hash); 1029 r = dm_bht_verify_root(bht, dm_bht_compare_hash);
1036 if (r) { 1030 if (r) {
1037 DMERR_LIMIT("Failed to verify root: %d", r); 1031 DMERR_LIMIT("Failed to verify root: %d", r);
1038 goto out; 1032 goto out;
1039 } 1033 }
1040 } 1034 }
1041 1035
1042 /* Now check levels in between */ 1036 /* Now check levels in between */
1043 » r = dm_bht_verify_path(bht, block_index, block); 1037 » r = dm_bht_verify_path(bht, block_index, pg, offset);
1044 if (r) 1038 if (r)
1045 DMERR_LIMIT("Failed to verify block: %u (%d)", block_index, r); 1039 DMERR_LIMIT("Failed to verify block: %u (%d)", block_index, r);
1046 1040
1047 out: 1041 out:
1048 return r; 1042 return r;
1049 } 1043 }
1050 EXPORT_SYMBOL(dm_bht_verify_block); 1044 EXPORT_SYMBOL(dm_bht_verify_block);
1051 1045
1052 /** 1046 /**
1053 * dm_bht_destroy - cleans up all memory used by @bht 1047 * 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) { 1175 if (!bht->root_digest) {
1182 DMERR("no root digest exists to export"); 1176 DMERR("no root digest exists to export");
1183 if (available > 0) 1177 if (available > 0)
1184 *hexdigest = 0; 1178 *hexdigest = 0;
1185 return -1; 1179 return -1;
1186 } 1180 }
1187 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); 1181 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size);
1188 return 0; 1182 return 0;
1189 } 1183 }
1190 EXPORT_SYMBOL(dm_bht_root_hexdigest); 1184 EXPORT_SYMBOL(dm_bht_root_hexdigest);
OLDNEW
« no previous file with comments | « no previous file | drivers/md/dm-verity.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698