aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity/ima/ima_appraise.c
diff options
context:
space:
mode:
authorMimi Zohar <zohar@linux.ibm.com>2021-08-18 10:18:29 -0400
committerMimi Zohar <zohar@linux.ibm.com>2021-08-18 10:18:29 -0400
commitd07eeeb8745973389e1d772b3b654f5860441589 (patch)
treeaa22f9b920ee39cf366404b4f7468c5b8860a176 /security/integrity/ima/ima_appraise.c
parentMerge branch 'ima-buffer-measurement-changes-v4' into next-integrity (diff)
parentIMA: prevent SETXATTR_CHECK policy rules with unavailable algorithms (diff)
downloadlinux-dev-d07eeeb8745973389e1d772b3b654f5860441589.tar.xz
linux-dev-d07eeeb8745973389e1d772b3b654f5860441589.zip
Merge branch 'restrict-digest-alg-v8' into next-integrity
Taken from the cover letter "IMA: restrict the accepted digest algorithms for the security.ima xattr": Provide users the ability to restrict the algorithms accepted by their system, both when writing/updating xattrs, and when appraising files, while retaining a permissive behavior by default to preserve backward compatibility. To provide these features, alter the behavior of setxattr to only accept hashes built in the kernel, instead of any hash listed in the kernel (complete list crypto/hash_info.c). In addition, the user can define in his IMA policy the list of digest algorithms allowed for writing to the security.ima xattr. In that case, only algorithms present in that list are accepted for writing. In addition, users may opt-in to allowlist hash algorithms for appraising thanks to the new 'appraise_algos' IMA policy option. By default IMA will keep accepting any hash algorithm, but specifying that option will make appraisal of files hashed with another algorithm fail. Link: https://lore.kernel.org/linux-integrity/20210816081056.24530-1-Simon.THOBY@viveris.fr/
Diffstat (limited to 'security/integrity/ima/ima_appraise.c')
-rw-r--r--security/integrity/ima/ima_appraise.c73
1 files changed, 68 insertions, 5 deletions
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 63bec42c353f..8f1eb7ef041e 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -77,8 +77,9 @@ int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
return 0;
security_task_getsecid_subj(current, &secid);
- return ima_match_policy(mnt_userns, inode, current_cred(), secid, func,
- mask, IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL);
+ return ima_match_policy(mnt_userns, inode, current_cred(), secid,
+ func, mask, IMA_APPRAISE | IMA_HASH, NULL,
+ NULL, NULL, NULL);
}
static int ima_fix_xattr(struct dentry *dentry,
@@ -171,7 +172,7 @@ static void ima_cache_flags(struct integrity_iint_cache *iint,
}
}
-enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
+enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value,
int xattr_len)
{
struct signature_v2_hdr *sig;
@@ -575,6 +576,66 @@ static void ima_reset_appraise_flags(struct inode *inode, int digsig)
clear_bit(IMA_DIGSIG, &iint->atomic_flags);
}
+/**
+ * validate_hash_algo() - Block setxattr with unsupported hash algorithms
+ * @dentry: object of the setxattr()
+ * @xattr_value: userland supplied xattr value
+ * @xattr_value_len: length of xattr_value
+ *
+ * The xattr value is mapped to its hash algorithm, and this algorithm
+ * must be built in the kernel for the setxattr to be allowed.
+ *
+ * Emit an audit message when the algorithm is invalid.
+ *
+ * Return: 0 on success, else an error.
+ */
+static int validate_hash_algo(struct dentry *dentry,
+ const struct evm_ima_xattr_data *xattr_value,
+ size_t xattr_value_len)
+{
+ char *path = NULL, *pathbuf = NULL;
+ enum hash_algo xattr_hash_algo;
+ const char *errmsg = "unavailable-hash-algorithm";
+ unsigned int allowed_hashes;
+
+ xattr_hash_algo = ima_get_hash_algo(xattr_value, xattr_value_len);
+
+ allowed_hashes = atomic_read(&ima_setxattr_allowed_hash_algorithms);
+
+ if (allowed_hashes) {
+ /* success if the algorithm is allowed in the ima policy */
+ if (allowed_hashes & (1U << xattr_hash_algo))
+ return 0;
+
+ /*
+ * We use a different audit message when the hash algorithm
+ * is denied by a policy rule, instead of not being built
+ * in the kernel image
+ */
+ errmsg = "denied-hash-algorithm";
+ } else {
+ if (likely(xattr_hash_algo == ima_hash_algo))
+ return 0;
+
+ /* allow any xattr using an algorithm built in the kernel */
+ if (crypto_has_alg(hash_algo_name[xattr_hash_algo], 0, 0))
+ return 0;
+ }
+
+ pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!pathbuf)
+ return -EACCES;
+
+ path = dentry_path(dentry, pathbuf, PATH_MAX);
+
+ integrity_audit_msg(AUDIT_INTEGRITY_DATA, d_inode(dentry), path,
+ "set_data", errmsg, -EACCES, 0);
+
+ kfree(pathbuf);
+
+ return -EACCES;
+}
+
int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
const void *xattr_value, size_t xattr_value_len)
{
@@ -592,9 +653,11 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
digsig = (xvalue->type == EVM_XATTR_PORTABLE_DIGSIG);
}
if (result == 1 || evm_revalidate_status(xattr_name)) {
+ result = validate_hash_algo(dentry, xvalue, xattr_value_len);
+ if (result)
+ return result;
+
ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
- if (result == 1)
- result = 0;
}
return result;
}