From: Mimi Zohar Date: Tue, 10 Mar 2026 13:16:25 +0000 (-0400) Subject: ima: add support to require IMA sigv3 signatures X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=de4c44a7f559ceae19f7a70febf49e87bdfb125c;p=thirdparty%2Fkernel%2Flinux.git ima: add support to require IMA sigv3 signatures Defining a policy rule with the "appraise_type=imasig" option allows either v2 or v3 signatures. Defining an IMA appraise rule with the "appraise_type=sigv3" option requires a file sigv3 signature. Define a new appraise type: IMA_SIGV3_REQUIRED Example: appraise func=BPRM_CHECK appraise_type=sigv3 Tested-by: Stefan Berger Acked-by: Eric Biggers Signed-off-by: Mimi Zohar --- diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy index d4b3696a9efb3..19258471b7b26 100644 --- a/Documentation/ABI/testing/ima_policy +++ b/Documentation/ABI/testing/ima_policy @@ -53,10 +53,7 @@ Description: where 'imasig' is the original or the signature format v2. where 'modsig' is an appended signature, - where 'sigv3' is the signature format v3. (Currently - limited to fsverity digest based signatures - stored in security.ima xattr. Requires - specifying "digest_type=verity" first.) + where 'sigv3' is the signature format v3. appraise_flag:= [check_blacklist] (deprecated) Setting the check_blacklist flag is no longer necessary. @@ -186,6 +183,11 @@ Description: appraise func=BPRM_CHECK digest_type=verity \ appraise_type=sigv3 + Example of a regular IMA file hash 'appraise' rule requiring + signature version 3 format stored in security.ima xattr. + + appraise func=BPRM_CHECK appraise_type=sigv3 + All of these policy rules could, for example, be constrained either based on a filesystem's UUID (fsuuid) or based on LSM labels. diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 0eea02ff04df6..69e9bf0b82c65 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -145,6 +145,7 @@ struct ima_kexec_hdr { #define IMA_DIGSIG_REQUIRED 0x01000000 #define IMA_PERMIT_DIRECTIO 0x02000000 #define IMA_NEW_FILE 0x04000000 +#define IMA_SIGV3_REQUIRED 0x08000000 #define IMA_FAIL_UNVERIFIABLE_SIGS 0x10000000 #define IMA_MODSIG_ALLOWED 0x20000000 #define IMA_CHECK_BLACKLIST 0x40000000 diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 8f182d808b096..de963b9f36344 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -302,6 +302,13 @@ static int xattr_verify(enum ima_hooks func, struct ima_iint_cache *iint, *status = INTEGRITY_FAIL; break; } + + if ((iint->flags & IMA_SIGV3_REQUIRED) && sig->version != 3) { + *cause = "IMA-sigv3-required"; + *status = INTEGRITY_FAIL; + break; + } + rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA, (const char *)xattr_value, xattr_len, diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index bf2d7ba4c14a9..f7f940a769223 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -1298,7 +1298,8 @@ static bool ima_validate_rule(struct ima_rule_entry *entry) IMA_GID | IMA_EGID | IMA_FGROUP | IMA_DIGSIG_REQUIRED | IMA_PERMIT_DIRECTIO | IMA_VALIDATE_ALGOS | - IMA_CHECK_BLACKLIST | IMA_VERITY_REQUIRED)) + IMA_CHECK_BLACKLIST | IMA_VERITY_REQUIRED | + IMA_SIGV3_REQUIRED)) return false; break; @@ -1833,9 +1834,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) break; case Opt_digest_type: ima_log_string(ab, "digest_type", args[0].from); - if (entry->flags & IMA_DIGSIG_REQUIRED) - result = -EINVAL; - else if ((strcmp(args[0].from, "verity")) == 0) + if ((strcmp(args[0].from, "verity")) == 0) entry->flags |= IMA_VERITY_REQUIRED; else result = -EINVAL; @@ -1849,14 +1848,13 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) else entry->flags |= IMA_DIGSIG_REQUIRED | IMA_CHECK_BLACKLIST; } else if (strcmp(args[0].from, "sigv3") == 0) { - /* Only fsverity supports sigv3 for now */ - if (entry->flags & IMA_VERITY_REQUIRED) - entry->flags |= IMA_DIGSIG_REQUIRED | IMA_CHECK_BLACKLIST; - else - result = -EINVAL; + entry->flags |= IMA_SIGV3_REQUIRED | + IMA_DIGSIG_REQUIRED | + IMA_CHECK_BLACKLIST; } else if (IS_ENABLED(CONFIG_IMA_APPRAISE_MODSIG) && strcmp(args[0].from, "imasig|modsig") == 0) { - if (entry->flags & IMA_VERITY_REQUIRED) + if ((entry->flags & IMA_VERITY_REQUIRED) || + (entry->flags & IMA_SIGV3_REQUIRED)) result = -EINVAL; else entry->flags |= IMA_DIGSIG_REQUIRED | @@ -1941,7 +1939,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) /* d-ngv2 template field recommended for unsigned fs-verity digests */ if (!result && entry->action == MEASURE && - entry->flags & IMA_VERITY_REQUIRED) { + (entry->flags & IMA_VERITY_REQUIRED)) { template_desc = entry->template ? entry->template : ima_template_desc_current(); check_template_field(template_desc, "d-ngv2", @@ -2309,7 +2307,7 @@ int ima_policy_show(struct seq_file *m, void *v) if (entry->template) seq_printf(m, "template=%s ", entry->template->name); if (entry->flags & IMA_DIGSIG_REQUIRED) { - if (entry->flags & IMA_VERITY_REQUIRED) + if (entry->flags & IMA_SIGV3_REQUIRED) seq_puts(m, "appraise_type=sigv3 "); else if (entry->flags & IMA_MODSIG_ALLOWED) seq_puts(m, "appraise_type=imasig|modsig ");