From: Roberto Sassu roberto.sassu@huawei.com
euleros inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I7QZ2M CVE: NA
-------------------------------------------------
ima_write_policy() is being used to load a new policy from user space. This function can be reused to load different types of data.
This patch renames ima_write_policy() to ima_write_data() and executes the appropriate actions depending on the opened file in securityfs.
Also, this patch raises the uploaded data size limit to 64M, to accept files (e.g. digest lists) larger than a policy. The same limit is used for the SELinux policy.
Signed-off-by: Roberto Sassu roberto.sassu@huawei.com Signed-off-by: Tianxing Zhang zhangtianxing3@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Signed-off-by: zhoushuiqing zhoushuiqing2@huawei.com --- security/integrity/ima/ima_fs.c | 54 ++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-)
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 8525aac7d18fe..9f36731b4cc5b 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -360,8 +360,13 @@ static ssize_t ima_read_policy(char *path) return pathlen; }
+#ifdef CONFIG_IMA_DIGEST_LIST +static ssize_t ima_write_data(struct file *file, const char __user *buf, + size_t datalen, loff_t *ppos) +#else static ssize_t ima_write_policy(struct file *file, const char __user *buf, size_t datalen, loff_t *ppos) +#endif { char *data; ssize_t result; @@ -369,19 +374,38 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, struct dentry *dentry = file_dentry(file); #endif
+#ifndef CONFIG_IMA_DIGEST_LIST if (datalen >= PAGE_SIZE) datalen = PAGE_SIZE - 1; +#endif
/* No partial writes. */ result = -EINVAL; if (*ppos != 0) goto out;
+#ifdef CONFIG_IMA_DIGEST_LIST + result = -EFBIG; + if (datalen > 64 * 1024 * 1024 - 1) + goto out; + + result = -ENOMEM; + data = vmalloc(datalen + 1); + if (!data) + goto out; + + result = -EFAULT; + if (copy_from_user(data, buf, datalen) != 0) + goto out_free; + + data[datalen] = '\0'; +#else data = memdup_user_nul(buf, datalen); if (IS_ERR(data)) { result = PTR_ERR(data); goto out; } +#endif
result = mutex_lock_interruptible(&ima_write_mutex); if (result < 0) @@ -390,23 +414,47 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, if (data[0] == '/') { #ifdef CONFIG_IMA_DIGEST_LIST result = ima_read_file(data, dentry); + } else if (dentry == ima_policy) { + if (ima_appraise & IMA_APPRAISE_POLICY) { + pr_err("signed policy file (specified " + "as an absolute pathname) required\n"); + integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, + "policy_update", + "signed policy required", 1, 0); + result = -EACCES; + } else { + result = ima_parse_add_rule(data); + } #else result = ima_read_policy(data); -#endif } else if (ima_appraise & IMA_APPRAISE_POLICY) { pr_err("signed policy file (specified as an absolute pathname) required\n"); integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, "policy_update", "signed policy required", 1, 0); result = -EACCES; +#endif } else { +#ifdef CONFIG_IMA_DIGEST_LIST + pr_err("Unknown data type\n"); + result = -EINVAL; +#else result = ima_parse_add_rule(data); +#endif } mutex_unlock(&ima_write_mutex); out_free: +#ifdef CONFIG_IMA_DIGEST_LIST + vfree(data); +#else kfree(data); +#endif out: +#ifdef CONFIG_IMA_DIGEST_LIST + if (dentry == ima_policy && result < 0) +#else if (result < 0) +#endif valid_policy = 0;
return result; @@ -502,7 +550,11 @@ static int ima_release_policy(struct inode *inode, struct file *file)
static const struct file_operations ima_measure_policy_ops = { .open = ima_open_policy, +#ifdef CONFIG_IMA_DIGEST_LIST + .write = ima_write_data, +#else .write = ima_write_policy, +#endif .read = seq_read, .release = ima_release_policy, .llseek = generic_file_llseek,