From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA
--------------------------------
This reverts commit be54067bbe893e4cd860292c943854e24fdea25e.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Acked-by: Xiu Jianfengxiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/ima.h | 2 - security/integrity/ima/ima.h | 19 ++-- security/integrity/ima/ima_appraise.c | 9 +- security/integrity/ima/ima_fs.c | 121 ++-------------------- security/integrity/ima/ima_init.c | 2 - security/integrity/ima/ima_ns.c | 140 ++++---------------------- security/integrity/ima/ima_policy.c | 40 +++----- 7 files changed, 55 insertions(+), 278 deletions(-)
diff --git a/include/linux/ima.h b/include/linux/ima.h index 1270337c1d99..91c637c943ed 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -235,8 +235,6 @@ struct ima_namespace { struct list_head ns_measurements; atomic_long_t ml_len; /* number of stored measurements in the list */ atomic_long_t violations; - char *x509_path_for_children; - struct ima_policy_setup_data *policy_setup_for_children; } __randomize_layout;
extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index dd43dbdab7b9..fce3fc065027 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -67,7 +67,6 @@ struct ima_policy_setup_data { bool ima_use_appraise_tcb; bool ima_use_appraise_exec_tcb; bool ima_use_appraise_exec_immutable; - bool fail_unverifiable_sigs; };
/* IMA event related data */ @@ -322,10 +321,15 @@ 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);
-int ima_policy_setup(char *str, struct ima_namespace *ima_ns); -int ima_default_measure_policy_setup(char *str, struct ima_namespace *ima_ns); -int ima_default_appraise_policy_setup(char *str, struct ima_namespace *ima_ns); -int ima_default_appraise_setup(char *str, struct ima_namespace *ima_ns); +int ima_policy_setup(char *str, + struct ima_policy_setup_data *policy_setup_data, + bool *fail_unverifiable_sigs); +int ima_default_measure_policy_setup(const char *str, + struct ima_policy_setup_data *setup_data); +int ima_default_appraise_policy_setup(const char *str, + struct ima_policy_setup_data *setup_data); +int ima_default_appraise_setup(const char *str, + struct ima_policy_setup_data *setup_data);
/* Appraise integrity measurements */ #define IMA_APPRAISE_ENFORCE 0x01 @@ -428,11 +432,6 @@ static inline struct ima_namespace *get_current_ns(void)
void ima_delete_ns_rules(struct ima_policy_data *policy_data, bool is_root_ns); - -ssize_t ima_ns_write_x509_for_children(struct ima_namespace *ima_ns, - char *x509_path); -ssize_t ima_ns_write_kcmd_for_children(struct ima_namespace *ima_ns, - char *kcmd); #else static inline int __init ima_init_namespace(void) { diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index c30262468e4c..9d041e3deef2 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -19,12 +19,9 @@
static bool ima_appraise_req_evm __ro_after_init;
-int ima_default_appraise_setup(char *str, - struct ima_namespace *ima_ns) +int ima_default_appraise_setup(const char *str, + struct ima_policy_setup_data *setup_data) { - struct ima_policy_setup_data *setup_data = (ima_ns == &init_ima_ns) ? - &init_policy_setup_data : ima_ns->policy_setup_for_children; - #ifdef CONFIG_IMA_APPRAISE_BOOTPARAM bool sb_state = arch_ima_get_secureboot(); int appraisal_state = setup_data->ima_appraise; @@ -58,7 +55,7 @@ int ima_default_appraise_setup(char *str,
static int __init default_appraise_setup(char *str) { - return ima_default_appraise_setup(str, &init_ima_ns); + return ima_default_appraise_setup(str, &init_policy_setup_data); }
__setup("ima_appraise=", default_appraise_setup); diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 74a4aad02f33..bda35e2bb45c 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -23,8 +23,6 @@ #include <linux/vmalloc.h> #include <linux/file.h> #include <linux/ctype.h> -#include <linux/string.h> -#include <linux/kernel.h>
#include "ima.h" #include "ima_digest_list.h" @@ -41,10 +39,6 @@ static struct dentry *ima_policy; static struct dentry *digests_count; static struct dentry *digest_list_data; static struct dentry *digest_list_data_del; -#ifdef CONFIG_IMA_NS -static struct dentry *x509_for_children; -static struct dentry *kcmd_for_children; -#endif /* CONFIG_IMA_NS */
bool ima_canonical_fmt; static int __init default_canonical_fmt_setup(char *str) @@ -58,16 +52,6 @@ __setup("ima_canonical_fmt", default_canonical_fmt_setup);
static int valid_policy = 1;
-static int ima_open_simple(struct inode *inode, struct file *file) -{ - struct ima_namespace *ima_ns = get_current_ns(); - - if (!ns_capable(ima_ns->user_ns, CAP_SYS_ADMIN)) - return -EPERM; - - return 0; -} - static ssize_t ima_show_htable_value(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { @@ -89,8 +73,18 @@ static ssize_t ima_show_htable_value(struct file *filp, char __user *buf, return simple_read_from_buffer(buf, count, ppos, tmpbuf, len); }
+static int ima_open_htable_value(struct inode *inode, struct file *file) +{ + struct ima_namespace *ima_ns = get_current_ns(); + + if (!ns_capable(ima_ns->user_ns, CAP_SYS_ADMIN)) + return -EPERM; + + return 0; +} + static const struct file_operations ima_htable_value_ops = { - .open = ima_open_simple, + .open = ima_open_htable_value, .read = ima_show_htable_value, .llseek = generic_file_llseek, }; @@ -623,79 +617,6 @@ static const struct file_operations ima_data_upload_ops = { .llseek = generic_file_llseek, };
-#ifdef CONFIG_IMA_NS -static int ima_open_for_children(struct inode *inode, struct file *file) -{ - struct ima_namespace *ima_ns = get_current_ns(); - - /* Allow to set children configuration only after unshare() */ - if (ima_ns == current->nsproxy->ima_ns_for_children) - return -EPERM; - - return ima_open_simple(inode, file); -} - -static ssize_t ima_write_x509_for_children(struct file *file, - const char __user *buf, - size_t count, loff_t *ppos) -{ - ssize_t res; - char *x509_path; - struct ima_namespace *ima_ns = current->nsproxy->ima_ns_for_children; - - /* Only allow < page size writes at the beginning of the file */ - if ((*ppos != 0) || (count >= PAGE_SIZE)) - return -EINVAL; - - x509_path = memdup_user_nul(buf, count); - if (IS_ERR(x509_path)) - return PTR_ERR(x509_path); - - res = ima_ns_write_x509_for_children(ima_ns, x509_path); - if (res) { - kfree(x509_path); - count = res; - } - - return count; -} - -static const struct file_operations ima_x509_for_children_ops = { - .open = ima_open_for_children, - .write = ima_write_x509_for_children, -}; - -static ssize_t ima_write_kcmd_for_children(struct file *file, - const char __user *buf, - size_t count, loff_t *ppos) -{ - ssize_t res; - char *kcmd; - struct ima_namespace *ima_ns = current->nsproxy->ima_ns_for_children; - - /* Only allow < page size writes at the beginning of the file */ - if ((*ppos != 0) || (count >= PAGE_SIZE)) - return -EINVAL; - - kcmd = memdup_user_nul(buf, count); - if (IS_ERR(kcmd)) - return PTR_ERR(kcmd); - - res = ima_ns_write_kcmd_for_children(ima_ns, kcmd); - if (res) - count = res; - - kfree(kcmd); - - return count; -} - -static const struct file_operations ima_kcmd_for_children_ops = { - .open = ima_open_for_children, - .write = ima_write_kcmd_for_children, -}; -#endif /* CONFIG_IMA_NS */ - int __init ima_fs_init(void) { ima_dir = securityfs_create_dir("ima", integrity_dir); @@ -759,22 +680,6 @@ int __init ima_fs_init(void) if (IS_ERR(digest_list_data_del)) goto out; #endif -#ifdef CONFIG_IMA_NS - x509_for_children = securityfs_create_file("x509_for_children", - 0202, - ima_dir, NULL, - &ima_x509_for_children_ops); - if (IS_ERR(x509_for_children)) - goto out; - - kcmd_for_children = securityfs_create_file("kcmd_for_children", - 0202, - ima_dir, NULL, - &ima_kcmd_for_children_ops); - if (IS_ERR(kcmd_for_children)) - goto out; -#endif /* CONFIG_IMA_NS */ - return 0; out: securityfs_remove(digest_list_data_del); @@ -787,9 +692,5 @@ int __init ima_fs_init(void) securityfs_remove(ima_symlink); securityfs_remove(ima_dir); securityfs_remove(ima_policy); -#ifdef CONFIG_IMA_NS - securityfs_remove(x509_for_children); - securityfs_remove(kcmd_for_children); -#endif /* CONFIG_IMA_NS */ return -1; } diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 7a0a640fdf9c..923373a12f5c 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -31,8 +31,6 @@ struct ima_namespace init_ima_ns = { .ns.inum = PROC_IMA_INIT_INO, #ifdef CONFIG_IMA_NS .ns.ops = &imans_operations, - .x509_path_for_children = NULL, - .policy_setup_for_children = NULL, #endif .frozen = true, .policy_data = &init_policy_data, diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 57dc9fedb8fd..ac000920d486 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -27,8 +27,6 @@ #include <linux/workqueue.h> #include <linux/mutex.h> #include <linux/spinlock.h> -#include <linux/string.h> -#include <linux/kernel.h>
#include "ima.h"
@@ -76,17 +74,23 @@ static struct ima_namespace *ima_ns_alloc(void) return NULL; }
-static void ima_set_ns_policy(struct ima_namespace *ima_ns) +static void ima_set_ns_policy(struct ima_namespace *ima_ns, + char *policy_setup_str) { - struct ima_policy_setup_data setup_data = {0}; + struct ima_policy_setup_data setup_data;
- if (!ima_ns->policy_setup_for_children) { #ifdef CONFIG_IMA_APPRAISE - setup_data.ima_appraise = IMA_APPRAISE_ENFORCE; + setup_data.ima_appraise = IMA_APPRAISE_ENFORCE; #endif - ima_init_ns_policy(ima_ns, &setup_data); - } else - ima_init_ns_policy(ima_ns, ima_ns->policy_setup_for_children); + /* Configuring IMA namespace will be implemented in the following + * patches. When it is done, parse configuration string and store result + * in setup_data. Temporarily use init_policy_setup_data. + */ + setup_data = init_policy_setup_data; + ima_ns->policy_data->ima_fail_unverifiable_sigs = + init_ima_ns.policy_data->ima_fail_unverifiable_sigs; + + ima_init_ns_policy(ima_ns, &setup_data); }
static int ima_swap_user_ns(struct ima_namespace *ima_ns, @@ -147,9 +151,6 @@ static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns, rwlock_init(&ns->iint_tree->lock); ns->iint_tree->root = RB_ROOT;
- ns->x509_path_for_children = NULL; - ns->policy_setup_for_children = NULL; - INIT_LIST_HEAD(&ns->ns_measurements); INIT_LIST_HEAD(&ns->policy_data->ima_default_rules); INIT_LIST_HEAD(&ns->policy_data->ima_policy_rules); @@ -217,14 +218,6 @@ static void imans_remove_hash_entries(struct ima_namespace *ima_ns) } }
-static void destroy_child_config(struct ima_namespace *ima_ns) -{ - kfree(ima_ns->x509_path_for_children); - ima_ns->x509_path_for_children = NULL; - kfree(ima_ns->policy_setup_for_children); - ima_ns->policy_setup_for_children = NULL; -} - static void destroy_ima_ns(struct ima_namespace *ns) { bool is_init_ns = (ns == &init_ima_ns); @@ -237,7 +230,6 @@ static void destroy_ima_ns(struct ima_namespace *ns) kfree(ns->iint_tree); ima_delete_ns_rules(ns->policy_data, is_init_ns); kfree(ns->policy_data); - destroy_child_config(ns); kfree(ns); }
@@ -327,31 +319,27 @@ static void imans_put(struct ns_common *ns)
static int imans_activate(struct ima_namespace *ima_ns) { - int res = 0; - if (ima_ns == &init_ima_ns) - return res; + return 0;
if (ima_ns->frozen) - return res; + return 0;
mutex_lock(&frozen_lock); if (ima_ns->frozen) goto out;
- ima_set_ns_policy(ima_ns); + ima_set_ns_policy(ima_ns, NULL);
ima_ns->frozen = true;
down_write(&ima_ns_list_lock); list_add_tail(&ima_ns->list, &ima_ns_list); up_write(&ima_ns_list_lock); - - destroy_child_config(ima_ns); out: mutex_unlock(&frozen_lock);
- return res; + return 0; }
static int imans_install(struct nsset *nsset, struct ns_common *new) @@ -436,97 +424,3 @@ const struct proc_ns_operations imans_for_children_operations = { .owner = imans_owner, };
-struct ima_kernel_param { - const char *name; - int (*set)(char *val, struct ima_namespace *ima_ns); -}; - -/* TODO: add ima_template, ima_template_fmt, ima_hash, ... */ -static const struct ima_kernel_param ima_kernel_params[] = { - {"ima_appraise", ima_default_appraise_setup}, - {"ima_policy", ima_policy_setup}, -}; -static const size_t ima_kernel_params_size = ARRAY_SIZE(ima_kernel_params); - -ssize_t ima_ns_write_x509_for_children(struct ima_namespace *ima_ns, - char *x509_path) -{ - ssize_t retval = 0; - - mutex_lock(&frozen_lock); - if (ima_ns->frozen) { - retval = -EACCES; - goto out; - } - - kfree(ima_ns->x509_path_for_children); - ima_ns->x509_path_for_children = x509_path; -out: - mutex_unlock(&frozen_lock); - - return retval; -} - -ssize_t ima_ns_write_kcmd_for_children(struct ima_namespace *ima_ns, - char *kcmd) -{ - u32 i; - char *param, *val; - ssize_t ret = 0; - - mutex_lock(&frozen_lock); - if (ima_ns->frozen) { - ret = -EACCES; - goto err_unlock; - } - - if (!ima_ns->policy_setup_for_children) { - ima_ns->policy_setup_for_children = - kmalloc(sizeof(struct ima_policy_setup_data), - GFP_KERNEL); - if (!ima_ns->policy_setup_for_children) { - ret = -ENOMEM; - goto err_unlock; - } - } - - memset(ima_ns->policy_setup_for_children, - 0, sizeof(struct ima_policy_setup_data)); - -#ifdef CONFIG_IMA_APPRAISE - ima_ns->policy_setup_for_children->ima_appraise = IMA_APPRAISE_ENFORCE; -#endif - - kcmd = skip_spaces(kcmd); - while (*kcmd) { - kcmd = next_arg(kcmd, ¶m, &val); - if (!val) { - ret = -EINVAL; - goto err_free; - } - - for (i = 0; i < ima_kernel_params_size; i++) { - if (strcmp(param, ima_kernel_params[i].name) == 0) - break; - } - - if (i == ima_kernel_params_size) { - ret = -EINVAL; - goto err_free; - } - - ima_kernel_params[i].set(val, ima_ns); - } - mutex_unlock(&frozen_lock); - - return ret; - -err_free: - kfree(ima_ns->policy_setup_for_children); - ima_ns->policy_setup_for_children = NULL; -err_unlock: - mutex_unlock(&frozen_lock); - - return ret; -} - diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 828793553a0e..0ab91cb31121 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -240,13 +240,9 @@ struct ima_policy_data init_policy_data = { .ima_rules = &init_policy_data.ima_default_rules, };
-int ima_default_measure_policy_setup(char *str, struct ima_namespace *ima_ns) +int ima_default_measure_policy_setup(const char *str, + struct ima_policy_setup_data *setup_data) { - struct ima_policy_setup_data *setup_data; - - setup_data = (ima_ns == &init_ima_ns) ? - &init_policy_setup_data : ima_ns->policy_setup_for_children; - if (setup_data->ima_policy) return 1;
@@ -256,7 +252,7 @@ int ima_default_measure_policy_setup(char *str, struct ima_namespace *ima_ns)
static int __init default_measure_policy_setup(char *str) { - return ima_default_measure_policy_setup(str, &init_ima_ns); + return ima_default_measure_policy_setup(str, &init_policy_setup_data); } __setup("ima_tcb", default_measure_policy_setup);
@@ -265,15 +261,15 @@ static bool ima_fail_unverifiable_sigs __ro_after_init; /** * ima_policy_setup - parse policy configuration string "ima_policy=" * @str: string to be parsed - * @ima_ns: pointer to the ima namespace which policy is being set + * @setup_data: pointer to a structure where parsed data is stored + * @fail_unverifiable_sigs: boolean flag treated separately to preserve + * __ro_after_init */ -int ima_policy_setup(char *str, struct ima_namespace *ima_ns) +int ima_policy_setup(char *str, + struct ima_policy_setup_data *setup_data, + bool *fail_unverifiable_sigs) { char *p; - struct ima_policy_setup_data *setup_data; - - setup_data = (ima_ns == &init_ima_ns) ? - &init_policy_setup_data : ima_ns->policy_setup_for_children;
while ((p = strsep(&str, " |\n")) != NULL) { if (*p == ' ') @@ -291,7 +287,7 @@ int ima_policy_setup(char *str, struct ima_namespace *ima_ns) else if (strcmp(p, "secure_boot") == 0) setup_data->ima_use_secure_boot = true; else if (strcmp(p, "fail_securely") == 0) - setup_data->fail_unverifiable_sigs = true; + *fail_unverifiable_sigs = true; else pr_err("policy "%s" not found", p); } @@ -301,27 +297,21 @@ int ima_policy_setup(char *str, struct ima_namespace *ima_ns)
static int __init policy_setup(char *str) { - ima_policy_setup(str, &init_ima_ns); - ima_fail_unverifiable_sigs = - init_policy_setup_data.fail_unverifiable_sigs; - return 1; + return ima_policy_setup(str, &init_policy_setup_data, + &ima_fail_unverifiable_sigs); } __setup("ima_policy=", policy_setup);
-int ima_default_appraise_policy_setup(char *str, struct ima_namespace *ima_ns) +int ima_default_appraise_policy_setup(const char *str, + struct ima_policy_setup_data *setup_data) { - struct ima_policy_setup_data *setup_data; - - setup_data = (ima_ns == &init_ima_ns) ? - &init_policy_setup_data : ima_ns->policy_setup_for_children; - setup_data->ima_use_appraise_tcb = true; return 1; }
static int __init default_appraise_policy_setup(char *str) { - return ima_default_appraise_policy_setup(str, &init_ima_ns); + return ima_default_appraise_policy_setup(str, &init_policy_setup_data); } __setup("ima_appraise_tcb", default_appraise_policy_setup);