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

ima: Load per ima namespace x509 certificate

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

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

If configured, load the x509 certificate when the first process is
born into the new ima namespace. User can set the path to the
certificate by writing to the x509_for_children entry in the ima
securityfs. The certificate may be appraised in the parent ima namespace,
in that case it may need to be signed with the parent ns' key. Appraisal
of the key in the newly created namespace is disabled as for the original
ima.
Signed-off-by: NKrzysztof Struczynski <krzysztof.struczynski@huawei.com>
Reviewed-by: NZhang Tianxing <zhangtianxing3@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 1939da70
......@@ -240,6 +240,7 @@ struct ima_namespace {
#ifdef CONFIG_KEYS
struct key_tag *key_domain;
#endif
struct task_struct *activating_tsk; /* used only for the ns activation */
} __randomize_layout;
extern struct ima_namespace init_ima_ns;
......
......@@ -171,8 +171,8 @@ int __init integrity_init_keyring(const unsigned int id)
return __integrity_init_keyring(id, perm, restriction);
}
int __init integrity_add_key(const unsigned int id, const void *data,
off_t size, key_perm_t perm)
int integrity_add_key(const unsigned int id, const void *data,
off_t size, key_perm_t perm)
{
key_ref_t key;
int rc = 0;
......@@ -196,7 +196,7 @@ int __init integrity_add_key(const unsigned int id, const void *data,
}
int __init integrity_load_x509(const unsigned int id, const char *path)
int integrity_load_x509(const unsigned int id, const char *path)
{
void *data = NULL;
size_t size;
......
......@@ -364,9 +364,12 @@ static int process_ns_measurement(struct file *file, const struct cred *cred,
return 0;
if (ima_ns != current_ima_ns) {
iint = integrity_iint_rb_find(ima_ns->iint_tree, inode);
if (!iint)
return 0;
if (!(ima_ns->activating_tsk && (ima_ns->activating_tsk ==
current))) {
iint = integrity_iint_rb_find(ima_ns->iint_tree, inode);
if (!iint)
return 0;
}
}
/* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action
......@@ -411,7 +414,8 @@ static int process_ns_measurement(struct file *file, const struct cred *cred,
goto out;
if (!action)
goto out;
if (ima_ns != current_ima_ns)
if ((ima_ns != current_ima_ns) &&
!(ima_ns->activating_tsk && (ima_ns->activating_tsk == current)))
goto out;
mutex_lock(&iint->mutex);
......
......@@ -49,6 +49,30 @@ static void dec_ima_namespaces(struct ucounts *ucounts)
return dec_ucount(ucounts, UCOUNT_IMA_NAMESPACES);
}
#ifdef CONFIG_IMA_LOAD_X509
static int ima_ns_load_x509(struct ima_namespace *ima_ns)
{
int res = 0;
int unset_flags =
ima_ns->policy_data->ima_policy_flag & IMA_APPRAISE;
if (!ima_ns->x509_path_for_children)
return res;
ima_ns->policy_data->ima_policy_flag &= ~unset_flags;
res = integrity_load_x509(INTEGRITY_KEYRING_IMA,
ima_ns->x509_path_for_children);
ima_ns->policy_data->ima_policy_flag |= unset_flags;
return res;
}
#else
static inline int ima_ns_load_x509(struct ima_namespace *ima_ns)
{
return 0;
}
#endif
static struct ima_namespace *ima_ns_alloc(void)
{
struct ima_namespace *ima_ns;
......@@ -361,6 +385,22 @@ static int imans_activate(struct ima_namespace *ima_ns)
list_add_tail(&ima_ns->list, &ima_ns_list);
up_write(&ima_ns_list_lock);
/* The x509 certificate has to be measured in the new namespace as
* well as in the parent namespace, therefore it has to be loaded
* after adding the namespace to the list of active namespaces. If
* defined in the policy, the parent IMA ns can also appraise the
* certificate, appraisal is disabled only in the new namespace. If
* loading the certificate fails, print a warning but don't return an
* error - there is no way to handle it well at this point, in
* the worst case, user will end up with a failed appraisal */
ima_ns->activating_tsk = current;
res = ima_ns_load_x509(ima_ns);
ima_ns->activating_tsk = NULL;
if (res < 0) {
pr_err("IMA ns x509 cert. loading failed, appraisal will fail\n");
res = 0;
}
destroy_child_config(ima_ns);
out:
mutex_unlock(&frozen_lock);
......@@ -370,9 +410,10 @@ static int imans_activate(struct ima_namespace *ima_ns)
static int imans_install(struct nsset *nsset, struct ns_common *new)
{
int res;
int res = 0;
struct nsproxy *nsproxy = nsset->nsproxy;
struct ima_namespace *ns = to_ima_ns(new);
struct ima_namespace *old_ns = nsproxy->ima_ns;
if (!current_is_single_threaded())
return -EUSERS;
......@@ -381,19 +422,20 @@ static int imans_install(struct nsset *nsset, struct ns_common *new)
!ns_capable(nsset->cred->user_ns, CAP_SYS_ADMIN))
return -EPERM;
res = imans_activate(ns);
if (res)
return res;
get_ima_ns(ns);
put_ima_ns(nsproxy->ima_ns);
put_ima_ns(old_ns);
nsproxy->ima_ns = ns;
get_ima_ns(ns);
put_ima_ns(nsproxy->ima_ns_for_children);
nsproxy->ima_ns_for_children = ns;
return res;
if (!ns->frozen && (ns->user_ns != nsset->cred->user_ns)) {
res = ima_swap_user_ns(ns, nsset->cred->user_ns);
if (res)
return res;
}
return imans_activate(ns);
}
int imans_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk,
......@@ -401,6 +443,7 @@ int imans_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk,
{
int res;
struct ima_namespace *ima_ns = nsproxy->ima_ns_for_children;
struct ima_namespace *old_ima_ns = nsproxy->ima_ns;
/* create_new_namespaces() already incremented the ref counter */
if (nsproxy->ima_ns == ima_ns)
......@@ -416,15 +459,11 @@ int imans_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk,
return res;
}
res = imans_activate(ima_ns);
if (res)
return res;
get_ima_ns(ima_ns);
put_ima_ns(nsproxy->ima_ns);
put_ima_ns(old_ima_ns);
nsproxy->ima_ns = ima_ns;
return res;
return imans_activate(ima_ns);
}
static struct user_namespace *imans_owner(struct ns_common *ns)
......
......@@ -223,7 +223,7 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
int integrity_modsig_verify(unsigned int id, const struct modsig *modsig);
int __init integrity_init_keyring(const unsigned int id);
int __init integrity_load_x509(const unsigned int id, const char *path);
int integrity_load_x509(const unsigned int id, const char *path);
int __init integrity_load_cert(const unsigned int id, const char *source,
const void *data, size_t len, key_perm_t perm);
#else
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册