forked from Minki/linux
dm verity: allow optional args to alter primary args handling
The previous commit ("dm verity: Add optional "try_verify_in_tasklet" feature") imposed that CRYPTO_ALG_ASYNC mask be used even if the optional "try_verify_in_tasklet" feature was not specified. This was because verity_parse_opt_args() was called after handling the primary args (due to it having data dependencies on having first parsed all primary args). Enhance verity_ctr() so that simple optional args, that don't have a data dependency on primary args parsing, can alter how the primary args are handled. In practice this means verity_parse_opt_args() gets called twice. First with the new 'only_modifier_opts' arg set to true, then again with it set to false _after_ parsing all primary args. This allows the v->use_tasklet flag to be properly set and then used when verity_ctr() parses the primary args and then calls crypto_alloc_ahash() with CRYPTO_ALG_ASYNC conditionally set. Signed-off-by: Mike Snitzer <snitzer@kernel.org>
This commit is contained in:
parent
5721d4e5a9
commit
df326e7a06
@ -1027,7 +1027,8 @@ static int verity_parse_verity_mode(struct dm_verity *v, const char *arg_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
|
static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
|
||||||
struct dm_verity_sig_opts *verify_args)
|
struct dm_verity_sig_opts *verify_args,
|
||||||
|
bool only_modifier_opts)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
unsigned argc;
|
unsigned argc;
|
||||||
@ -1050,6 +1051,8 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
|
|||||||
argc--;
|
argc--;
|
||||||
|
|
||||||
if (verity_is_verity_mode(arg_name)) {
|
if (verity_is_verity_mode(arg_name)) {
|
||||||
|
if (only_modifier_opts)
|
||||||
|
continue;
|
||||||
r = verity_parse_verity_mode(v, arg_name);
|
r = verity_parse_verity_mode(v, arg_name);
|
||||||
if (r) {
|
if (r) {
|
||||||
ti->error = "Conflicting error handling parameters";
|
ti->error = "Conflicting error handling parameters";
|
||||||
@ -1058,6 +1061,8 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else if (!strcasecmp(arg_name, DM_VERITY_OPT_IGN_ZEROES)) {
|
} else if (!strcasecmp(arg_name, DM_VERITY_OPT_IGN_ZEROES)) {
|
||||||
|
if (only_modifier_opts)
|
||||||
|
continue;
|
||||||
r = verity_alloc_zero_digest(v);
|
r = verity_alloc_zero_digest(v);
|
||||||
if (r) {
|
if (r) {
|
||||||
ti->error = "Cannot allocate zero digest";
|
ti->error = "Cannot allocate zero digest";
|
||||||
@ -1066,6 +1071,8 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else if (!strcasecmp(arg_name, DM_VERITY_OPT_AT_MOST_ONCE)) {
|
} else if (!strcasecmp(arg_name, DM_VERITY_OPT_AT_MOST_ONCE)) {
|
||||||
|
if (only_modifier_opts)
|
||||||
|
continue;
|
||||||
r = verity_alloc_most_once(v);
|
r = verity_alloc_most_once(v);
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
@ -1076,12 +1083,16 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else if (verity_is_fec_opt_arg(arg_name)) {
|
} else if (verity_is_fec_opt_arg(arg_name)) {
|
||||||
|
if (only_modifier_opts)
|
||||||
|
continue;
|
||||||
r = verity_fec_parse_opt_args(as, v, &argc, arg_name);
|
r = verity_fec_parse_opt_args(as, v, &argc, arg_name);
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else if (verity_verify_is_sig_opt_arg(arg_name)) {
|
} else if (verity_verify_is_sig_opt_arg(arg_name)) {
|
||||||
|
if (only_modifier_opts)
|
||||||
|
continue;
|
||||||
r = verity_verify_sig_parse_opt_args(as, v,
|
r = verity_verify_sig_parse_opt_args(as, v,
|
||||||
verify_args,
|
verify_args,
|
||||||
&argc, arg_name);
|
&argc, arg_name);
|
||||||
@ -1148,6 +1159,15 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse optional parameters that modify primary args */
|
||||||
|
if (argc > 10) {
|
||||||
|
as.argc = argc - 10;
|
||||||
|
as.argv = argv + 10;
|
||||||
|
r = verity_parse_opt_args(&as, v, &verify_args, true);
|
||||||
|
if (r < 0)
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
if (sscanf(argv[0], "%u%c", &num, &dummy) != 1 ||
|
if (sscanf(argv[0], "%u%c", &num, &dummy) != 1 ||
|
||||||
num > 1) {
|
num > 1) {
|
||||||
ti->error = "Invalid version";
|
ti->error = "Invalid version";
|
||||||
@ -1219,11 +1239,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
v->tfm = crypto_alloc_ahash(v->alg_name, 0,
|
||||||
* FIXME: CRYPTO_ALG_ASYNC should be conditional on v->use_tasklet
|
v->use_tasklet ? CRYPTO_ALG_ASYNC : 0);
|
||||||
* but verity_parse_opt_args() happens below and has data dep on tfm.
|
|
||||||
*/
|
|
||||||
v->tfm = crypto_alloc_ahash(v->alg_name, 0, CRYPTO_ALG_ASYNC);
|
|
||||||
if (IS_ERR(v->tfm)) {
|
if (IS_ERR(v->tfm)) {
|
||||||
ti->error = "Cannot initialize hash function";
|
ti->error = "Cannot initialize hash function";
|
||||||
r = PTR_ERR(v->tfm);
|
r = PTR_ERR(v->tfm);
|
||||||
@ -1285,8 +1302,7 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
|
|||||||
if (argc) {
|
if (argc) {
|
||||||
as.argc = argc;
|
as.argc = argc;
|
||||||
as.argv = argv;
|
as.argv = argv;
|
||||||
|
r = verity_parse_opt_args(&as, v, &verify_args, false);
|
||||||
r = verity_parse_opt_args(&as, v, &verify_args);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user