ima: Factor xattr_verify() out of ima_appraise_measurement()
authorThiago Jung Bauermann <bauerman@linux.ibm.com>
Fri, 28 Jun 2019 02:19:29 +0000 (23:19 -0300)
committerMimi Zohar <zohar@linux.ibm.com>
Mon, 5 Aug 2019 22:40:22 +0000 (18:40 -0400)
Verify xattr signature in a separate function so that the logic in
ima_appraise_measurement() remains clear when it gains the ability to also
verify an appended module signature.

The code in the switch statement is unchanged except for having to
dereference the status and cause variables (since they're now pointers),
and fixing the style of a block comment to appease checkpatch.

Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
security/integrity/ima/ima_appraise.c

index 89b83194d1dc4813ec57160ab817b24ac84571e3..d3298045737f06dae390d8cb4ce88c4e2f58d10a 100644 (file)
@@ -199,6 +199,83 @@ int ima_read_xattr(struct dentry *dentry,
        return ret;
 }
 
+/*
+ * xattr_verify - verify xattr digest or signature
+ *
+ * Verify whether the hash or signature matches the file contents.
+ *
+ * Return 0 on success, error code otherwise.
+ */
+static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint,
+                       struct evm_ima_xattr_data *xattr_value, int xattr_len,
+                       enum integrity_status *status, const char **cause)
+{
+       int rc = -EINVAL, hash_start = 0;
+
+       switch (xattr_value->type) {
+       case IMA_XATTR_DIGEST_NG:
+               /* first byte contains algorithm id */
+               hash_start = 1;
+               /* fall through */
+       case IMA_XATTR_DIGEST:
+               if (iint->flags & IMA_DIGSIG_REQUIRED) {
+                       *cause = "IMA-signature-required";
+                       *status = INTEGRITY_FAIL;
+                       break;
+               }
+               clear_bit(IMA_DIGSIG, &iint->atomic_flags);
+               if (xattr_len - sizeof(xattr_value->type) - hash_start >=
+                               iint->ima_hash->length)
+                       /*
+                        * xattr length may be longer. md5 hash in previous
+                        * version occupied 20 bytes in xattr, instead of 16
+                        */
+                       rc = memcmp(&xattr_value->data[hash_start],
+                                   iint->ima_hash->digest,
+                                   iint->ima_hash->length);
+               else
+                       rc = -EINVAL;
+               if (rc) {
+                       *cause = "invalid-hash";
+                       *status = INTEGRITY_FAIL;
+                       break;
+               }
+               *status = INTEGRITY_PASS;
+               break;
+       case EVM_IMA_XATTR_DIGSIG:
+               set_bit(IMA_DIGSIG, &iint->atomic_flags);
+               rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
+                                            (const char *)xattr_value,
+                                            xattr_len,
+                                            iint->ima_hash->digest,
+                                            iint->ima_hash->length);
+               if (rc == -EOPNOTSUPP) {
+                       *status = INTEGRITY_UNKNOWN;
+                       break;
+               }
+               if (IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING) && rc &&
+                   func == KEXEC_KERNEL_CHECK)
+                       rc = integrity_digsig_verify(INTEGRITY_KEYRING_PLATFORM,
+                                                    (const char *)xattr_value,
+                                                    xattr_len,
+                                                    iint->ima_hash->digest,
+                                                    iint->ima_hash->length);
+               if (rc) {
+                       *cause = "invalid-signature";
+                       *status = INTEGRITY_FAIL;
+               } else {
+                       *status = INTEGRITY_PASS;
+               }
+               break;
+       default:
+               *status = INTEGRITY_UNKNOWN;
+               *cause = "unknown-ima-data";
+               break;
+       }
+
+       return rc;
+}
+
 /*
  * ima_appraise_measurement - appraise file measurement
  *
@@ -218,7 +295,7 @@ int ima_appraise_measurement(enum ima_hooks func,
        struct dentry *dentry = file_dentry(file);
        struct inode *inode = d_backing_inode(dentry);
        enum integrity_status status = INTEGRITY_UNKNOWN;
-       int rc = xattr_len, hash_start = 0;
+       int rc = xattr_len;
 
        if (!(inode->i_opflags & IOP_XATTR))
                return INTEGRITY_UNKNOWN;
@@ -256,65 +333,9 @@ int ima_appraise_measurement(enum ima_hooks func,
                WARN_ONCE(true, "Unexpected integrity status %d\n", status);
        }
 
-       switch (xattr_value->type) {
-       case IMA_XATTR_DIGEST_NG:
-               /* first byte contains algorithm id */
-               hash_start = 1;
-               /* fall through */
-       case IMA_XATTR_DIGEST:
-               if (iint->flags & IMA_DIGSIG_REQUIRED) {
-                       cause = "IMA-signature-required";
-                       status = INTEGRITY_FAIL;
-                       break;
-               }
-               clear_bit(IMA_DIGSIG, &iint->atomic_flags);
-               if (xattr_len - sizeof(xattr_value->type) - hash_start >=
-                               iint->ima_hash->length)
-                       /* xattr length may be longer. md5 hash in previous
-                          version occupied 20 bytes in xattr, instead of 16
-                        */
-                       rc = memcmp(&xattr_value->data[hash_start],
-                                   iint->ima_hash->digest,
-                                   iint->ima_hash->length);
-               else
-                       rc = -EINVAL;
-               if (rc) {
-                       cause = "invalid-hash";
-                       status = INTEGRITY_FAIL;
-                       break;
-               }
-               status = INTEGRITY_PASS;
-               break;
-       case EVM_IMA_XATTR_DIGSIG:
-               set_bit(IMA_DIGSIG, &iint->atomic_flags);
-               rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
-                                            (const char *)xattr_value,
-                                            xattr_len,
-                                            iint->ima_hash->digest,
-                                            iint->ima_hash->length);
-               if (rc == -EOPNOTSUPP) {
-                       status = INTEGRITY_UNKNOWN;
-                       break;
-               }
-               if (IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING) && rc &&
-                   func == KEXEC_KERNEL_CHECK)
-                       rc = integrity_digsig_verify(INTEGRITY_KEYRING_PLATFORM,
-                                                    (const char *)xattr_value,
-                                                    xattr_len,
-                                                    iint->ima_hash->digest,
-                                                    iint->ima_hash->length);
-               if (rc) {
-                       cause = "invalid-signature";
-                       status = INTEGRITY_FAIL;
-               } else {
-                       status = INTEGRITY_PASS;
-               }
-               break;
-       default:
-               status = INTEGRITY_UNKNOWN;
-               cause = "unknown-ima-data";
-               break;
-       }
+       if (xattr_value)
+               rc = xattr_verify(func, iint, xattr_value, xattr_len, &status,
+                                 &cause);
 
 out:
        /*