summaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-integrity.c
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2017-04-18 16:51:50 -0400
committerMike Snitzer <snitzer@redhat.com>2017-04-24 12:04:32 -0400
commit56b67a4f292f14548f4046979d46d07bcf8ba971 (patch)
tree2b7648bdcbc66160eafe5b93d6445a90afef4998 /drivers/md/dm-integrity.c
parente2460f2a4bc740fae9e23f14d653cf53e90b3f9a (diff)
dm integrity: various small changes and cleanups
Some coding style changes. Fix a bug that the array test_tag has insufficient size if the digest size of internal has is bigger than the tag size. The function __fls is undefined for zero argument, this patch fixes undefined behavior if the user sets zero interleave_sectors. Fix the limit of optional arguments to 8. Don't allocate crypt_data on the stack to avoid a BUG with debug kernel. Rename all optional argument names to have underscores rather than dashes. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-integrity.c')
-rw-r--r--drivers/md/dm-integrity.c116
1 files changed, 62 insertions, 54 deletions
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index e26a079b41ea..95cdffbb206c 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -27,8 +27,8 @@
27#define DEFAULT_JOURNAL_WATERMARK 50 27#define DEFAULT_JOURNAL_WATERMARK 50
28#define DEFAULT_SYNC_MSEC 10000 28#define DEFAULT_SYNC_MSEC 10000
29#define DEFAULT_MAX_JOURNAL_SECTORS 131072 29#define DEFAULT_MAX_JOURNAL_SECTORS 131072
30#define MIN_INTERLEAVE_SECTORS 3 30#define MIN_LOG2_INTERLEAVE_SECTORS 3
31#define MAX_INTERLEAVE_SECTORS 31 31#define MAX_LOG2_INTERLEAVE_SECTORS 31
32#define METADATA_WORKQUEUE_MAX_ACTIVE 16 32#define METADATA_WORKQUEUE_MAX_ACTIVE 16
33 33
34/* 34/*
@@ -414,7 +414,7 @@ static void page_list_location(struct dm_integrity_c *ic, unsigned section, unsi
414{ 414{
415 unsigned sector; 415 unsigned sector;
416 416
417 access_journal_check(ic, section, offset, false, "access_journal"); 417 access_journal_check(ic, section, offset, false, "page_list_location");
418 418
419 sector = section * ic->journal_section_sectors + offset; 419 sector = section * ic->journal_section_sectors + offset;
420 420
@@ -1211,7 +1211,7 @@ static void integrity_metadata(struct work_struct *w)
1211 unsigned digest_size = crypto_shash_digestsize(ic->internal_hash); 1211 unsigned digest_size = crypto_shash_digestsize(ic->internal_hash);
1212 struct bio *bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io)); 1212 struct bio *bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io));
1213 char *checksums; 1213 char *checksums;
1214 unsigned extra_space = digest_size > ic->tag_size ? digest_size - ic->tag_size : 0; 1214 unsigned extra_space = unlikely(digest_size > ic->tag_size) ? digest_size - ic->tag_size : 0;
1215 char checksums_onstack[ic->tag_size + extra_space]; 1215 char checksums_onstack[ic->tag_size + extra_space];
1216 unsigned sectors_to_process = dio->range.n_sectors; 1216 unsigned sectors_to_process = dio->range.n_sectors;
1217 sector_t sector = dio->range.logical_sector; 1217 sector_t sector = dio->range.logical_sector;
@@ -1820,7 +1820,7 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
1820 unlikely(from_replay) && 1820 unlikely(from_replay) &&
1821#endif 1821#endif
1822 ic->internal_hash) { 1822 ic->internal_hash) {
1823 unsigned char test_tag[ic->tag_size]; 1823 char test_tag[max(crypto_shash_digestsize(ic->internal_hash), ic->tag_size)];
1824 1824
1825 integrity_sector_checksum(ic, sec + (l - j), 1825 integrity_sector_checksum(ic, sec + (l - j),
1826 (char *)access_journal_data(ic, i, l), test_tag); 1826 (char *)access_journal_data(ic, i, l), test_tag);
@@ -2135,11 +2135,11 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type,
2135 arg_count += !!ic->journal_mac_alg.alg_string; 2135 arg_count += !!ic->journal_mac_alg.alg_string;
2136 DMEMIT("%s %llu %u %c %u", ic->dev->name, (unsigned long long)ic->start, 2136 DMEMIT("%s %llu %u %c %u", ic->dev->name, (unsigned long long)ic->start,
2137 ic->tag_size, ic->mode, arg_count); 2137 ic->tag_size, ic->mode, arg_count);
2138 DMEMIT(" journal-sectors:%u", ic->initial_sectors - SB_SECTORS); 2138 DMEMIT(" journal_sectors:%u", ic->initial_sectors - SB_SECTORS);
2139 DMEMIT(" interleave-sectors:%u", 1U << ic->sb->log2_interleave_sectors); 2139 DMEMIT(" interleave_sectors:%u", 1U << ic->sb->log2_interleave_sectors);
2140 DMEMIT(" buffer-sectors:%u", 1U << ic->log2_buffer_sectors); 2140 DMEMIT(" buffer_sectors:%u", 1U << ic->log2_buffer_sectors);
2141 DMEMIT(" journal-watermark:%u", (unsigned)watermark_percentage); 2141 DMEMIT(" journal_watermark:%u", (unsigned)watermark_percentage);
2142 DMEMIT(" commit-time:%u", ic->autocommit_msec); 2142 DMEMIT(" commit_time:%u", ic->autocommit_msec);
2143 2143
2144#define EMIT_ALG(a, n) \ 2144#define EMIT_ALG(a, n) \
2145 do { \ 2145 do { \
@@ -2149,9 +2149,9 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type,
2149 DMEMIT(":%s", ic->a.key_string);\ 2149 DMEMIT(":%s", ic->a.key_string);\
2150 } \ 2150 } \
2151 } while (0) 2151 } while (0)
2152 EMIT_ALG(internal_hash_alg, "internal-hash"); 2152 EMIT_ALG(internal_hash_alg, "internal_hash");
2153 EMIT_ALG(journal_crypt_alg, "journal-crypt"); 2153 EMIT_ALG(journal_crypt_alg, "journal_crypt");
2154 EMIT_ALG(journal_mac_alg, "journal-mac"); 2154 EMIT_ALG(journal_mac_alg, "journal_mac");
2155 break; 2155 break;
2156 } 2156 }
2157 } 2157 }
@@ -2213,6 +2213,7 @@ static int initialize_superblock(struct dm_integrity_c *ic, unsigned journal_sec
2213 unsigned journal_sections; 2213 unsigned journal_sections;
2214 int test_bit; 2214 int test_bit;
2215 2215
2216 memset(ic->sb, 0, SB_SECTORS << SECTOR_SHIFT);
2216 memcpy(ic->sb->magic, SB_MAGIC, 8); 2217 memcpy(ic->sb->magic, SB_MAGIC, 8);
2217 ic->sb->version = SB_VERSION; 2218 ic->sb->version = SB_VERSION;
2218 ic->sb->integrity_tag_size = cpu_to_le16(ic->tag_size); 2219 ic->sb->integrity_tag_size = cpu_to_le16(ic->tag_size);
@@ -2225,9 +2226,11 @@ static int initialize_superblock(struct dm_integrity_c *ic, unsigned journal_sec
2225 journal_sections = 1; 2226 journal_sections = 1;
2226 ic->sb->journal_sections = cpu_to_le32(journal_sections); 2227 ic->sb->journal_sections = cpu_to_le32(journal_sections);
2227 2228
2229 if (!interleave_sectors)
2230 interleave_sectors = DEFAULT_INTERLEAVE_SECTORS;
2228 ic->sb->log2_interleave_sectors = __fls(interleave_sectors); 2231 ic->sb->log2_interleave_sectors = __fls(interleave_sectors);
2229 ic->sb->log2_interleave_sectors = max((__u8)MIN_INTERLEAVE_SECTORS, ic->sb->log2_interleave_sectors); 2232 ic->sb->log2_interleave_sectors = max((__u8)MIN_LOG2_INTERLEAVE_SECTORS, ic->sb->log2_interleave_sectors);
2230 ic->sb->log2_interleave_sectors = min((__u8)MAX_INTERLEAVE_SECTORS, ic->sb->log2_interleave_sectors); 2233 ic->sb->log2_interleave_sectors = min((__u8)MAX_LOG2_INTERLEAVE_SECTORS, ic->sb->log2_interleave_sectors);
2231 2234
2232 ic->provided_data_sectors = 0; 2235 ic->provided_data_sectors = 0;
2233 for (test_bit = fls64(ic->device_sectors) - 1; test_bit >= 3; test_bit--) { 2236 for (test_bit = fls64(ic->device_sectors) - 1; test_bit >= 3; test_bit--) {
@@ -2238,7 +2241,7 @@ static int initialize_superblock(struct dm_integrity_c *ic, unsigned journal_sec
2238 ic->provided_data_sectors = prev_data_sectors; 2241 ic->provided_data_sectors = prev_data_sectors;
2239 } 2242 }
2240 2243
2241 if (!le64_to_cpu(ic->provided_data_sectors)) 2244 if (!ic->provided_data_sectors)
2242 return -EINVAL; 2245 return -EINVAL;
2243 2246
2244 ic->sb->provided_data_sectors = cpu_to_le64(ic->provided_data_sectors); 2247 ic->sb->provided_data_sectors = cpu_to_le64(ic->provided_data_sectors);
@@ -2444,6 +2447,12 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
2444 int r = 0; 2447 int r = 0;
2445 unsigned i; 2448 unsigned i;
2446 __u64 journal_pages, journal_desc_size, journal_tree_size; 2449 __u64 journal_pages, journal_desc_size, journal_tree_size;
2450 unsigned char *crypt_data = NULL;
2451
2452 ic->commit_ids[0] = cpu_to_le64(0x1111111111111111ULL);
2453 ic->commit_ids[1] = cpu_to_le64(0x2222222222222222ULL);
2454 ic->commit_ids[2] = cpu_to_le64(0x3333333333333333ULL);
2455 ic->commit_ids[3] = cpu_to_le64(0x4444444444444444ULL);
2447 2456
2448 journal_pages = roundup((__u64)ic->journal_sections * ic->journal_section_sectors, 2457 journal_pages = roundup((__u64)ic->journal_sections * ic->journal_section_sectors,
2449 PAGE_SIZE >> SECTOR_SHIFT) >> (PAGE_SHIFT - SECTOR_SHIFT); 2458 PAGE_SIZE >> SECTOR_SHIFT) >> (PAGE_SHIFT - SECTOR_SHIFT);
@@ -2541,7 +2550,13 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
2541 SKCIPHER_REQUEST_ON_STACK(req, ic->journal_crypt); 2550 SKCIPHER_REQUEST_ON_STACK(req, ic->journal_crypt);
2542 unsigned char iv[ivsize]; 2551 unsigned char iv[ivsize];
2543 unsigned crypt_len = roundup(ivsize, blocksize); 2552 unsigned crypt_len = roundup(ivsize, blocksize);
2544 unsigned char crypt_data[crypt_len]; 2553
2554 crypt_data = kmalloc(crypt_len, GFP_KERNEL);
2555 if (!crypt_data) {
2556 *error = "Unable to allocate crypt data";
2557 r = -ENOMEM;
2558 goto bad;
2559 }
2545 2560
2546 skcipher_request_set_tfm(req, ic->journal_crypt); 2561 skcipher_request_set_tfm(req, ic->journal_crypt);
2547 2562
@@ -2630,38 +2645,38 @@ retest_commit_id:
2630 r = -ENOMEM; 2645 r = -ENOMEM;
2631 } 2646 }
2632bad: 2647bad:
2648 kfree(crypt_data);
2633 return r; 2649 return r;
2634} 2650}
2635 2651
2636/* 2652/*
2637 * Construct a integrity mapping: <dev_path> <offset> <tag_size> 2653 * Construct a integrity mapping
2638 * 2654 *
2639 * Arguments: 2655 * Arguments:
2640 * device 2656 * device
2641 * offset from the start of the device 2657 * offset from the start of the device
2642 * tag size 2658 * tag size
2643 * D - direct writes, J - journal writes 2659 * D - direct writes, J - journal writes, R - recovery mode
2644 * number of optional arguments 2660 * number of optional arguments
2645 * optional arguments: 2661 * optional arguments:
2646 * journal-sectors 2662 * journal_sectors
2647 * interleave-sectors 2663 * interleave_sectors
2648 * buffer-sectors 2664 * buffer_sectors
2649 * journal-watermark 2665 * journal_watermark
2650 * commit-time 2666 * commit_time
2651 * internal-hash 2667 * internal_hash
2652 * journal-crypt 2668 * journal_crypt
2653 * journal-mac 2669 * journal_mac
2654 */ 2670 */
2655static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv) 2671static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
2656{ 2672{
2657 struct dm_integrity_c *ic; 2673 struct dm_integrity_c *ic;
2658 char dummy; 2674 char dummy;
2659 int r; 2675 int r;
2660 unsigned i;
2661 unsigned extra_args; 2676 unsigned extra_args;
2662 struct dm_arg_set as; 2677 struct dm_arg_set as;
2663 static struct dm_arg _args[] = { 2678 static struct dm_arg _args[] = {
2664 {0, 7, "Invalid number of feature args"}, 2679 {0, 8, "Invalid number of feature args"},
2665 }; 2680 };
2666 unsigned journal_sectors, interleave_sectors, buffer_sectors, journal_watermark, sync_msec; 2681 unsigned journal_sectors, interleave_sectors, buffer_sectors, journal_watermark, sync_msec;
2667 bool should_write_sb; 2682 bool should_write_sb;
@@ -2683,11 +2698,6 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
2683 ti->private = ic; 2698 ti->private = ic;
2684 ti->per_io_data_size = sizeof(struct dm_integrity_io); 2699 ti->per_io_data_size = sizeof(struct dm_integrity_io);
2685 2700
2686 ic->commit_ids[0] = cpu_to_le64(0x1111111111111111ULL);
2687 ic->commit_ids[1] = cpu_to_le64(0x2222222222222222ULL);
2688 ic->commit_ids[2] = cpu_to_le64(0x3333333333333333ULL);
2689 ic->commit_ids[3] = cpu_to_le64(0x4444444444444444ULL);
2690
2691 ic->in_progress = RB_ROOT; 2701 ic->in_progress = RB_ROOT;
2692 init_waitqueue_head(&ic->endio_wait); 2702 init_waitqueue_head(&ic->endio_wait);
2693 bio_list_init(&ic->flush_bio_list); 2703 bio_list_init(&ic->flush_bio_list);
@@ -2718,7 +2728,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
2718 if (!strcmp(argv[3], "J") || !strcmp(argv[3], "D") || !strcmp(argv[3], "R")) 2728 if (!strcmp(argv[3], "J") || !strcmp(argv[3], "D") || !strcmp(argv[3], "R"))
2719 ic->mode = argv[3][0]; 2729 ic->mode = argv[3][0];
2720 else { 2730 else {
2721 ti->error = "Invalid mode (expecting J or D)"; 2731 ti->error = "Invalid mode (expecting J, D, R)";
2722 r = -EINVAL; 2732 r = -EINVAL;
2723 goto bad; 2733 goto bad;
2724 } 2734 }
@@ -2746,29 +2756,29 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
2746 ti->error = "Not enough feature arguments"; 2756 ti->error = "Not enough feature arguments";
2747 goto bad; 2757 goto bad;
2748 } 2758 }
2749 if (sscanf(opt_string, "journal-sectors:%u%c", &val, &dummy) == 1) 2759 if (sscanf(opt_string, "journal_sectors:%u%c", &val, &dummy) == 1)
2750 journal_sectors = val; 2760 journal_sectors = val;
2751 else if (sscanf(opt_string, "interleave-sectors:%u%c", &val, &dummy) == 1) 2761 else if (sscanf(opt_string, "interleave_sectors:%u%c", &val, &dummy) == 1)
2752 interleave_sectors = val; 2762 interleave_sectors = val;
2753 else if (sscanf(opt_string, "buffer-sectors:%u%c", &val, &dummy) == 1) 2763 else if (sscanf(opt_string, "buffer_sectors:%u%c", &val, &dummy) == 1)
2754 buffer_sectors = val; 2764 buffer_sectors = val;
2755 else if (sscanf(opt_string, "journal-watermark:%u%c", &val, &dummy) == 1 && val <= 100) 2765 else if (sscanf(opt_string, "journal_watermark:%u%c", &val, &dummy) == 1 && val <= 100)
2756 journal_watermark = val; 2766 journal_watermark = val;
2757 else if (sscanf(opt_string, "commit-time:%u%c", &val, &dummy) == 1) 2767 else if (sscanf(opt_string, "commit_time:%u%c", &val, &dummy) == 1)
2758 sync_msec = val; 2768 sync_msec = val;
2759 else if (!memcmp(opt_string, "internal-hash:", strlen("internal-hash:"))) { 2769 else if (!memcmp(opt_string, "internal_hash:", strlen("internal_hash:"))) {
2760 r = get_alg_and_key(opt_string, &ic->internal_hash_alg, &ti->error, 2770 r = get_alg_and_key(opt_string, &ic->internal_hash_alg, &ti->error,
2761 "Invalid internal-hash argument"); 2771 "Invalid internal_hash argument");
2762 if (r) 2772 if (r)
2763 goto bad; 2773 goto bad;
2764 } else if (!memcmp(opt_string, "journal-crypt:", strlen("journal-crypt:"))) { 2774 } else if (!memcmp(opt_string, "journal_crypt:", strlen("journal_crypt:"))) {
2765 r = get_alg_and_key(opt_string, &ic->journal_crypt_alg, &ti->error, 2775 r = get_alg_and_key(opt_string, &ic->journal_crypt_alg, &ti->error,
2766 "Invalid journal-crypt argument"); 2776 "Invalid journal_crypt argument");
2767 if (r) 2777 if (r)
2768 goto bad; 2778 goto bad;
2769 } else if (!memcmp(opt_string, "journal-mac:", strlen("journal-mac:"))) { 2779 } else if (!memcmp(opt_string, "journal_mac:", strlen("journal_mac:"))) {
2770 r = get_alg_and_key(opt_string, &ic->journal_mac_alg, &ti->error, 2780 r = get_alg_and_key(opt_string, &ic->journal_mac_alg, &ti->error,
2771 "Invalid journal-mac argument"); 2781 "Invalid journal_mac argument");
2772 if (r) 2782 if (r)
2773 goto bad; 2783 goto bad;
2774 } else { 2784 } else {
@@ -2877,12 +2887,10 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
2877 should_write_sb = false; 2887 should_write_sb = false;
2878 if (memcmp(ic->sb->magic, SB_MAGIC, 8)) { 2888 if (memcmp(ic->sb->magic, SB_MAGIC, 8)) {
2879 if (ic->mode != 'R') { 2889 if (ic->mode != 'R') {
2880 for (i = 0; i < 512; i += 8) { 2890 if (memchr_inv(ic->sb, 0, SB_SECTORS << SECTOR_SHIFT)) {
2881 if (*(__u64 *)((__u8 *)ic->sb + i)) { 2891 r = -EINVAL;
2882 r = -EINVAL; 2892 ti->error = "The device is not initialized";
2883 ti->error = "The device is not initialized"; 2893 goto bad;
2884 goto bad;
2885 }
2886 } 2894 }
2887 } 2895 }
2888 2896
@@ -2906,8 +2914,8 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
2906 goto bad; 2914 goto bad;
2907 } 2915 }
2908 /* make sure that ti->max_io_len doesn't overflow */ 2916 /* make sure that ti->max_io_len doesn't overflow */
2909 if (ic->sb->log2_interleave_sectors < MIN_INTERLEAVE_SECTORS || 2917 if (ic->sb->log2_interleave_sectors < MIN_LOG2_INTERLEAVE_SECTORS ||
2910 ic->sb->log2_interleave_sectors > MAX_INTERLEAVE_SECTORS) { 2918 ic->sb->log2_interleave_sectors > MAX_LOG2_INTERLEAVE_SECTORS) {
2911 r = -EINVAL; 2919 r = -EINVAL;
2912 ti->error = "Invalid interleave_sectors in the superblock"; 2920 ti->error = "Invalid interleave_sectors in the superblock";
2913 goto bad; 2921 goto bad;