diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 6817ee53ed9e..10214f73ca1e 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -470,6 +470,7 @@ void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos); void ima_policy_stop(struct seq_file *m, void *v); int ima_policy_show(struct seq_file *m, void *v); void ima_measure_loaded_policy(void); +int ima_measure_raw_policy(const char *buf, size_t buf_len); /* Appraise integrity measurements */ #define IMA_APPRAISE_ENFORCE 0x01 diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 92ca4d62c94d..2a0bca554316 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -598,6 +598,7 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, 1, 0); result = -EACCES; } else { + ima_measure_raw_policy(data, datalen); result = ima_parse_add_rule(data); } mutex_unlock(&ima_write_mutex); diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 1cfae4b83dc5..334e21be4075 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -1221,6 +1221,28 @@ int ima_measure_critical_data(const char *event_label, } EXPORT_SYMBOL_GPL(ima_measure_critical_data); +/** + * ima_measure_raw_policy - Measure the raw policy write buffer + * @buf: pointer to the buffer containing the raw policy data + * @buf_len: size of the buffer + * + * Measure the raw policy buffer sent to the IMA policy securityfs file. The + * buffer is written from userspace, and the measurement is performed before + * parsing it. This measurement includes any data written on the policy file + * such as malformed policy rules and comments. + * + * Return 0 on success, a negative value otherwise. + */ +int ima_measure_raw_policy(const char *buf, size_t buf_len) +{ + if (!buf || !buf_len) + return -EINVAL; + + return process_buffer_measurement(&nop_mnt_idmap, NULL, buf, buf_len, + "ima_policy_written", POLICY_CHECK, + 0, NULL, false, NULL, 0); +} + #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS /** diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 09da140de67c..f79d07bb63c6 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -542,6 +542,8 @@ static bool ima_match_rule_data(struct ima_rule_entry *rule, opt_list = rule->label; break; + case POLICY_CHECK: + return true; default: return false; } @@ -588,6 +590,10 @@ static bool ima_match_rules(struct ima_rule_entry *rule, return false; switch (func) { + case POLICY_CHECK: + if (inode) + break; + fallthrough; case KEY_CHECK: case CRITICAL_DATA: return ((rule->func == func) &&