md: dm-default-key: Fix IV with set_dun flag defined

With set_dun flag defined the IV for fscrypt encrypted bios
should be updated while passing through mapped device.

Change-Id: Ib812746663c8cd13cd148239a2a819f5ca3fe005
Signed-off-by: Neeraj Soni <neersoni@codeaurora.org>
This commit is contained in:
Neeraj Soni 2020-12-08 15:47:29 +05:30 committed by Vaibhav Agrawal
parent 322992f598
commit 325a34e669

View File

@ -83,7 +83,8 @@ static void default_key_dtr(struct dm_target *ti)
}
static int default_key_ctr_optional(struct dm_target *ti,
unsigned int argc, char **argv)
unsigned int argc, char **argv,
bool is_legacy)
{
struct default_key_c *dkc = ti->private;
struct dm_arg_set as;
@ -123,7 +124,7 @@ static int default_key_ctr_optional(struct dm_target *ti,
iv_large_sectors = true;
} else if (!strcmp(opt_string, "wrappedkey_v0")) {
dkc->is_hw_wrapped = true;
} else if (!strcmp(opt_string, "set_dun")) {
} else if (!strcmp(opt_string, "set_dun") && is_legacy) {
dkc->set_dun = true;
} else {
ti->error = "Invalid feature arguments";
@ -168,7 +169,7 @@ static void default_key_adjust_sector_size_and_iv(char **argv,
!strcmp((*dkc)->dev->bdev->bd_disk->disk_name, "mmcblk0")))
(*dkc)->sector_size = SECTOR_SIZE;
if (dev->bdev->bd_part)
if (dev->bdev->bd_part && !(*dkc)->set_dun)
(*dkc)->iv_offset += dev->bdev->bd_part->start_sect;
}
}
@ -191,22 +192,31 @@ static int default_key_ctr(struct dm_target *ti, unsigned int argc, char **argv)
unsigned long long tmpll;
char dummy;
int err;
int __argc;
char *_argv[10];
bool is_legacy = false;
if (argc >= 4 && !strcmp(argv[0], "AES-256-XTS")) {
argc = 0;
_argv[argc++] = "aes-xts-plain64";
_argv[argc++] = argv[1];
_argv[argc++] = "0";
_argv[argc++] = argv[2];
_argv[argc++] = argv[3];
_argv[argc++] = "3";
_argv[argc++] = "allow_discards";
_argv[argc++] = "sector_size:4096";
_argv[argc++] = "iv_large_sectors";
_argv[argc] = NULL;
__argc = 0;
_argv[__argc++] = "aes-xts-plain64";
_argv[__argc++] = argv[1];
_argv[__argc++] = "0";
_argv[__argc++] = argv[2];
_argv[__argc++] = argv[3];
if (argc > 4)
_argv[__argc++] = "4";
else
_argv[__argc++] = "3";
_argv[__argc++] = "allow_discards";
_argv[__argc++] = "sector_size:4096";
_argv[__argc++] = "iv_large_sectors";
if (argc > 4)
_argv[__argc++] = argv[5];
_argv[__argc] = NULL;
argv = _argv;
argc = __argc;
is_legacy = true;
}
@ -278,7 +288,8 @@ static int default_key_ctr(struct dm_target *ti, unsigned int argc, char **argv)
/* optional arguments */
dkc->sector_size = SECTOR_SIZE;
if (argc > 5) {
err = default_key_ctr_optional(ti, argc - 5, &argv[5]);
err = default_key_ctr_optional(ti, argc - 5, &argv[5],
is_legacy);
if (err)
goto bad;
}
@ -327,6 +338,13 @@ out:
return err;
}
static void default_key_map_dun(struct bio *bio, u64 *dun)
{
dun[0] += 1;
memcpy(bio->bi_crypt_context->bc_dun, dun,
sizeof(bio->bi_crypt_context->bc_dun));
bio->bi_crypt_context->is_ext4 = false;
}
static int default_key_map(struct dm_target *ti, struct bio *bio)
{
const struct default_key_c *dkc = ti->private;
@ -351,14 +369,15 @@ static int default_key_map(struct dm_target *ti, struct bio *bio)
* file's contents), or if it doesn't have any data (e.g. if it's a
* DISCARD request), there's nothing more to do.
*/
if (bio_should_skip_dm_default_key(bio) || !bio_has_data(bio))
if ((bio_should_skip_dm_default_key(bio) && !dkc->set_dun) ||
!bio_has_data(bio))
return DM_MAPIO_REMAPPED;
/*
* Else, dm-default-key needs to set this bio's encryption context.
* It must not already have one.
*/
if (WARN_ON_ONCE(bio_has_crypt_ctx(bio)))
if (WARN_ON_ONCE(bio_has_crypt_ctx(bio) && !dkc->set_dun))
return DM_MAPIO_KILL;
/* Calculate the DUN and enforce data-unit (crypto sector) alignment. */
@ -374,7 +393,11 @@ static int default_key_map(struct dm_target *ti, struct bio *bio)
if (WARN_ON_ONCE(dun[0] > dkc->max_dun))
return DM_MAPIO_KILL;
bio_crypt_set_ctx(bio, &dkc->key, dun, GFP_NOIO);
if (!bio_has_crypt_ctx(bio))
bio_crypt_set_ctx(bio, &dkc->key, dun, GFP_NOIO);
if (dkc->set_dun)
default_key_map_dun(bio, dun);
return DM_MAPIO_REMAPPED;
}
@ -402,6 +425,8 @@ static void default_key_status(struct dm_target *ti, status_type_t type,
num_feature_args += 2;
if (dkc->is_hw_wrapped)
num_feature_args += 1;
if (dkc->set_dun)
num_feature_args += 1;
if (num_feature_args != 0) {
DMEMIT(" %d", num_feature_args);
if (ti->num_discard_bios)
@ -412,6 +437,8 @@ static void default_key_status(struct dm_target *ti, status_type_t type,
}
if (dkc->is_hw_wrapped)
DMEMIT(" wrappedkey_v0");
if (dkc->set_dun)
DMEMIT(" set_dun");
}
break;
}