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

Signed-off-by: Mimi Zohar <[email protected]>
---
 Documentation/ABI/testing/ima_policy  | 10 ++++++----
 security/integrity/ima/ima.h          |  1 +
 security/integrity/ima/ima_appraise.c |  7 +++++++
 security/integrity/ima/ima_policy.c   | 22 ++++++++++------------
 4 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/Documentation/ABI/testing/ima_policy 
b/Documentation/ABI/testing/ima_policy
index d4b3696a9efb..19258471b7b2 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 0eea02ff04df..69e9bf0b82c6 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 8f182d808b09..de963b9f3634 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 bf2d7ba4c14a..f7f940a76922 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 ");
-- 
2.53.0


Reply via email to