提交 be54067b 编写于 作者: K Krzysztof Struczynski 提交者: Zheng Zengkai

ima: Configure the new ima namespace from securityfs

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I49KW1
CVE: NA

--------------------------------

Add ima securityfs entries to configure per ima namespace:
- path to the x509 certificate
- ima kernel boot parameters

The x509 certificate will be parsed and loaded when the first process is
born into the new ima namespace, paths are not validated when written.

Kernel boot parameters are pre-parsed and applied when the first process
is born into the
new namespace.
Signed-off-by: NKrzysztof Struczynski <krzysztof.struczynski@huawei.com>
Reviewed-by: NZhang Tianxing <zhangtianxing3@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 2098d7b5
......@@ -235,6 +235,8 @@ 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;
......
......@@ -67,6 +67,7 @@ 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 */
......@@ -321,15 +322,10 @@ 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_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);
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);
/* Appraise integrity measurements */
#define IMA_APPRAISE_ENFORCE 0x01
......@@ -432,6 +428,11 @@ 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)
{
......
......@@ -19,9 +19,12 @@
static bool ima_appraise_req_evm __ro_after_init;
int ima_default_appraise_setup(const char *str,
struct ima_policy_setup_data *setup_data)
int ima_default_appraise_setup(char *str,
struct ima_namespace *ima_ns)
{
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;
......@@ -55,7 +58,7 @@ int ima_default_appraise_setup(const char *str,
static int __init default_appraise_setup(char *str)
{
return ima_default_appraise_setup(str, &init_policy_setup_data);
return ima_default_appraise_setup(str, &init_ima_ns);
}
__setup("ima_appraise=", default_appraise_setup);
......
......@@ -23,6 +23,8 @@
#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"
......@@ -39,6 +41,10 @@ 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)
......@@ -52,6 +58,16 @@ __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)
{
......@@ -73,18 +89,8 @@ 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_htable_value,
.open = ima_open_simple,
.read = ima_show_htable_value,
.llseek = generic_file_llseek,
};
......@@ -613,6 +619,79 @@ 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);
......@@ -676,6 +755,22 @@ 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);
......@@ -688,5 +783,9 @@ 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;
}
......@@ -31,6 +31,8 @@ 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,
......
......@@ -27,6 +27,8 @@
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include "ima.h"
......@@ -74,23 +76,17 @@ static struct ima_namespace *ima_ns_alloc(void)
return NULL;
}
static void ima_set_ns_policy(struct ima_namespace *ima_ns,
char *policy_setup_str)
static void ima_set_ns_policy(struct ima_namespace *ima_ns)
{
struct ima_policy_setup_data setup_data;
struct ima_policy_setup_data setup_data = {0};
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
/* 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);
ima_init_ns_policy(ima_ns, &setup_data);
} else
ima_init_ns_policy(ima_ns, ima_ns->policy_setup_for_children);
}
static int ima_swap_user_ns(struct ima_namespace *ima_ns,
......@@ -151,6 +147,9 @@ 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);
......@@ -218,6 +217,14 @@ 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);
......@@ -230,6 +237,7 @@ 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);
}
......@@ -319,27 +327,31 @@ 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 0;
return res;
if (ima_ns->frozen)
return 0;
return res;
mutex_lock(&frozen_lock);
if (ima_ns->frozen)
goto out;
ima_set_ns_policy(ima_ns, NULL);
ima_set_ns_policy(ima_ns);
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 0;
return res;
}
static int imans_install(struct nsset *nsset, struct ns_common *new)
......@@ -424,3 +436,97 @@ 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, &param, &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;
}
......@@ -240,9 +240,13 @@ struct ima_policy_data init_policy_data = {
.ima_rules = &init_policy_data.ima_default_rules,
};
int ima_default_measure_policy_setup(const char *str,
struct ima_policy_setup_data *setup_data)
int ima_default_measure_policy_setup(char *str, struct ima_namespace *ima_ns)
{
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;
......@@ -252,7 +256,7 @@ int ima_default_measure_policy_setup(const char *str,
static int __init default_measure_policy_setup(char *str)
{
return ima_default_measure_policy_setup(str, &init_policy_setup_data);
return ima_default_measure_policy_setup(str, &init_ima_ns);
}
__setup("ima_tcb", default_measure_policy_setup);
......@@ -261,15 +265,15 @@ static bool ima_fail_unverifiable_sigs __ro_after_init;
/**
* ima_policy_setup - parse policy configuration string "ima_policy="
* @str: string to be parsed
* @setup_data: pointer to a structure where parsed data is stored
* @fail_unverifiable_sigs: boolean flag treated separately to preserve
* __ro_after_init
* @ima_ns: pointer to the ima namespace which policy is being set
*/
int ima_policy_setup(char *str,
struct ima_policy_setup_data *setup_data,
bool *fail_unverifiable_sigs)
int ima_policy_setup(char *str, struct ima_namespace *ima_ns)
{
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 == ' ')
......@@ -287,7 +291,7 @@ int ima_policy_setup(char *str,
else if (strcmp(p, "secure_boot") == 0)
setup_data->ima_use_secure_boot = true;
else if (strcmp(p, "fail_securely") == 0)
*fail_unverifiable_sigs = true;
setup_data->fail_unverifiable_sigs = true;
else
pr_err("policy \"%s\" not found", p);
}
......@@ -297,21 +301,27 @@ int ima_policy_setup(char *str,
static int __init policy_setup(char *str)
{
return ima_policy_setup(str, &init_policy_setup_data,
&ima_fail_unverifiable_sigs);
ima_policy_setup(str, &init_ima_ns);
ima_fail_unverifiable_sigs =
init_policy_setup_data.fail_unverifiable_sigs;
return 1;
}
__setup("ima_policy=", policy_setup);
int ima_default_appraise_policy_setup(const char *str,
struct ima_policy_setup_data *setup_data)
int ima_default_appraise_policy_setup(char *str, struct ima_namespace *ima_ns)
{
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_policy_setup_data);
return ima_default_appraise_policy_setup(str, &init_ima_ns);
}
__setup("ima_appraise_tcb", default_appraise_policy_setup);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册