summaryrefslogtreecommitdiff
path: root/security/integrity/ima/ima_api.c
diff options
context:
space:
mode:
authorMimi Zohar <zohar@linux.ibm.com>2021-12-23 20:29:56 +0300
committerMimi Zohar <zohar@linux.ibm.com>2022-05-05 18:49:13 +0300
commit54f03916fb892441f9a9b579db9ad7925cdeb395 (patch)
tree0fdee8270399ff57636479db46d5d37044373608 /security/integrity/ima/ima_api.c
parent989dc72511f7b57b94b42eabfcbe79d9070de6e3 (diff)
downloadlinux-54f03916fb892441f9a9b579db9ad7925cdeb395.tar.xz
ima: permit fsverity's file digests in the IMA measurement list
Permit fsverity's file digest (a hash of struct fsverity_descriptor) to be included in the IMA measurement list, based on the new measurement policy rule 'digest_type=verity' option. To differentiate between a regular IMA file hash from an fsverity's file digest, use the new d-ngv2 format field included in the ima-ngv2 template. The following policy rule requires fsverity file digests and specifies the new 'ima-ngv2' template, which contains the new 'd-ngv2' field. The policy rule may be constrained, for example based on a fsuuid or LSM label. measure func=FILE_CHECK digest_type=verity template=ima-ngv2 Acked-by: Stefan Berger <stefanb@linux.ibm.com> Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
Diffstat (limited to 'security/integrity/ima/ima_api.c')
-rw-r--r--security/integrity/ima/ima_api.c47
1 files changed, 44 insertions, 3 deletions
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index c6805af46211..c1e76282b5ee 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -14,6 +14,7 @@
#include <linux/xattr.h>
#include <linux/evm.h>
#include <linux/iversion.h>
+#include <linux/fsverity.h>
#include "ima.h"
@@ -200,6 +201,32 @@ int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
allowed_algos);
}
+static int ima_get_verity_digest(struct integrity_iint_cache *iint,
+ struct ima_max_digest_data *hash)
+{
+ enum hash_algo verity_alg;
+ int ret;
+
+ /*
+ * On failure, 'measure' policy rules will result in a file data
+ * hash containing 0's.
+ */
+ ret = fsverity_get_digest(iint->inode, hash->digest, &verity_alg);
+ if (ret)
+ return ret;
+
+ /*
+ * Unlike in the case of actually calculating the file hash, in
+ * the fsverity case regardless of the hash algorithm, return
+ * the verity digest to be included in the measurement list. A
+ * mismatch between the verity algorithm and the xattr signature
+ * algorithm, if one exists, will be detected later.
+ */
+ hash->hdr.algo = verity_alg;
+ hash->hdr.length = hash_digest_size[verity_alg];
+ return 0;
+}
+
/*
* ima_collect_measurement - collect file measurement
*
@@ -242,16 +269,30 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
*/
i_version = inode_query_iversion(inode);
hash.hdr.algo = algo;
+ hash.hdr.length = hash_digest_size[algo];
/* Initialize hash digest to 0's in case of failure */
memset(&hash.digest, 0, sizeof(hash.digest));
- if (buf)
+ if (iint->flags & IMA_VERITY_REQUIRED) {
+ result = ima_get_verity_digest(iint, &hash);
+ switch (result) {
+ case 0:
+ break;
+ case -ENODATA:
+ audit_cause = "no-verity-digest";
+ break;
+ default:
+ audit_cause = "invalid-verity-digest";
+ break;
+ }
+ } else if (buf) {
result = ima_calc_buffer_hash(buf, size, &hash.hdr);
- else
+ } else {
result = ima_calc_file_hash(file, &hash.hdr);
+ }
- if (result && result != -EBADF && result != -EINVAL)
+ if (result == -ENOMEM)
goto out;
length = sizeof(hash.hdr) + hash.hdr.length;