aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity/ima/ima_policy.c
diff options
context:
space:
mode:
authorTHOBY Simon <Simon.THOBY@viveris.fr>2021-08-16 08:11:01 +0000
committerMimi Zohar <zohar@linux.ibm.com>2021-08-16 17:35:35 -0400
commit4f2946aa0c45c78b4f4ef101bab9694e38c68db0 (patch)
tree0dd88bc80160aa79584e4050e0e03b40d2502298 /security/integrity/ima/ima_policy.c
parentIMA: add a policy option to restrict xattr hash algorithms on appraisal (diff)
downloadlinux-dev-4f2946aa0c45c78b4f4ef101bab9694e38c68db0.tar.xz
linux-dev-4f2946aa0c45c78b4f4ef101bab9694e38c68db0.zip
IMA: introduce a new policy option func=SETXATTR_CHECK
While users can restrict the accepted hash algorithms for the security.ima xattr file signature when appraising said file, users cannot restrict the algorithms that can be set on that attribute: any algorithm built in the kernel is accepted on a write. Define a new value for the ima policy option 'func' that restricts globally the hash algorithms accepted when writing the security.ima xattr. When a policy contains a rule of the form appraise func=SETXATTR_CHECK appraise_algos=sha256,sha384,sha512 only values corresponding to one of these three digest algorithms will be accepted for writing the security.ima xattr. Attempting to write the attribute using another algorithm (or "free-form" data) will be denied with an audit log message. In the absence of such a policy rule, the default is still to only accept hash algorithms built in the kernel (with all the limitations that entails). Signed-off-by: THOBY Simon <Simon.THOBY@viveris.fr> Reviewed-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com> Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
Diffstat (limited to '')
-rw-r--r--security/integrity/ima/ima_policy.c76
1 files changed, 66 insertions, 10 deletions
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index cb86da0e562b..9eaa509f487a 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -53,6 +53,8 @@ int ima_policy_flag;
static int temp_ima_appraise;
static int build_ima_appraise __ro_after_init;
+atomic_t ima_setxattr_allowed_hash_algorithms;
+
#define MAX_LSM_RULES 6
enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
@@ -720,24 +722,57 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
return action;
}
-/*
- * Initialize the ima_policy_flag variable based on the currently
- * loaded policy. Based on this flag, the decision to short circuit
- * out of a function or not call the function in the first place
- * can be made earlier.
+/**
+ * ima_update_policy_flags() - Update global IMA variables
+ *
+ * Update ima_policy_flag and ima_setxattr_allowed_hash_algorithms
+ * based on the currently loaded policy.
+ *
+ * With ima_policy_flag, the decision to short circuit out of a function
+ * or not call the function in the first place can be made earlier.
+ *
+ * With ima_setxattr_allowed_hash_algorithms, the policy can restrict the
+ * set of hash algorithms accepted when updating the security.ima xattr of
+ * a file.
+ *
+ * Context: called after a policy update and at system initialization.
*/
-void ima_update_policy_flag(void)
+void ima_update_policy_flags(void)
{
struct ima_rule_entry *entry;
+ int new_policy_flag = 0;
+ rcu_read_lock();
list_for_each_entry(entry, ima_rules, list) {
+ /*
+ * SETXATTR_CHECK rules do not implement a full policy check
+ * because rule checking would probably have an important
+ * performance impact on setxattr(). As a consequence, only one
+ * SETXATTR_CHECK can be active at a given time.
+ * Because we want to preserve that property, we set out to use
+ * atomic_cmpxchg. Either:
+ * - the atomic was non-zero: a setxattr hash policy is
+ * already enforced, we do nothing
+ * - the atomic was zero: no setxattr policy was set, enable
+ * the setxattr hash policy
+ */
+ if (entry->func == SETXATTR_CHECK) {
+ atomic_cmpxchg(&ima_setxattr_allowed_hash_algorithms,
+ 0, entry->allowed_algos);
+ /* SETXATTR_CHECK doesn't impact ima_policy_flag */
+ continue;
+ }
+
if (entry->action & IMA_DO_MASK)
- ima_policy_flag |= entry->action;
+ new_policy_flag |= entry->action;
}
+ rcu_read_unlock();
ima_appraise |= (build_ima_appraise | temp_ima_appraise);
if (!ima_appraise)
- ima_policy_flag &= ~IMA_APPRAISE;
+ new_policy_flag &= ~IMA_APPRAISE;
+
+ ima_policy_flag = new_policy_flag;
}
static int ima_appraise_flag(enum ima_hooks func)
@@ -903,7 +938,9 @@ void __init ima_init_policy(void)
ARRAY_SIZE(critical_data_rules),
IMA_DEFAULT_POLICY);
- ima_update_policy_flag();
+ atomic_set(&ima_setxattr_allowed_hash_algorithms, 0);
+
+ ima_update_policy_flags();
}
/* Make sure we have a valid policy, at least containing some rules. */
@@ -943,7 +980,7 @@ void ima_update_policy(void)
*/
kfree(arch_policy_entry);
}
- ima_update_policy_flag();
+ ima_update_policy_flags();
/* Custom IMA policy has been loaded */
ima_process_queued_keys();
@@ -1177,6 +1214,23 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
return false;
break;
+ case SETXATTR_CHECK:
+ /* any action other than APPRAISE is unsupported */
+ if (entry->action != APPRAISE)
+ return false;
+
+ /* SETXATTR_CHECK requires an appraise_algos parameter */
+ if (!(entry->flags & IMA_VALIDATE_ALGOS))
+ return false;
+
+ /*
+ * full policies are not supported, they would have too
+ * much of a performance impact
+ */
+ if (entry->flags & ~(IMA_FUNC | IMA_VALIDATE_ALGOS))
+ return false;
+
+ break;
default:
return false;
}
@@ -1332,6 +1386,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
entry->func = KEY_CHECK;
else if (strcmp(args[0].from, "CRITICAL_DATA") == 0)
entry->func = CRITICAL_DATA;
+ else if (strcmp(args[0].from, "SETXATTR_CHECK") == 0)
+ entry->func = SETXATTR_CHECK;
else
result = -EINVAL;
if (!result)