Commit a8352473 authored by Krzysztof Struczynski's avatar Krzysztof Struczynski Committed by Zheng Zengkai
Browse files

ima: Introduce ima namespace

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


CVE: NA

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

IMA namespace wraps global ima resources in an abstraction, to enable ima
to work with the containers. Currently, ima namespace contains no useful
data but a dummy interface. IMA resources related to different aspects of
IMA, namely IMA-audit, IMA-measurement, IMA-appraisal will be added in the
following patches.

The way how ima namespace is created is analogous to the time namespace:
unshare(CLONE_NEWIMA) system call creates a new ima namespace but doesn't
assign it to the current process. All children of the process will be born
in the new ima namespace, or a process can use setns() system call to join
the new ima namespace. Call to clone3(CLONE_NEWIMA) system call creates a
new namespace, which the new process joins instantly.

This scheme, allows to configure the new ima namespace before any process
appears in it. If user initially unshares the new ima namespace, ima can
be configured using ima entries in the securityfs. If user calls clone3()
system call directly, the new ima namespace can be configured using clone
arguments. To allow this, new securityfs entries have to be added, and
structures clone_args and kernel_clone_args have to be extended.

Early configuration is crucial. The new ima polices must apply to the
first process in the new namespace, and the appraisal key has to be loaded
beforehand.

Add a new CONFIG_IMA_NS option to the kernel configuration, that enables
one to create a new IMA namespace. IMA namespace functionality is disabled
by default.

Signed-off-by: default avatarKrzysztof Struczynski <krzysztof.struczynski@huawei.com>
Reviewed-by: default avatarZhang Tianxing <zhangtianxing3@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 061052a9
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -37,6 +37,10 @@ static const struct proc_ns_operations *ns_entries[] = {
	&timens_operations,
	&timens_for_children_operations,
#endif
#ifdef CONFIG_IMA_NS
	&imans_operations,
	&imans_for_children_operations,
#endif
};

static const char *proc_ns_get_link(struct dentry *dentry,
+57 −0
Original line number Diff line number Diff line
@@ -13,6 +13,9 @@
#include <linux/kexec.h>
struct linux_binprm;

struct nsproxy;
struct task_struct;

#ifdef CONFIG_IMA
extern int ima_bprm_check(struct linux_binprm *bprm);
extern int ima_file_check(struct file *file, int mask);
@@ -197,4 +200,58 @@ static inline bool ima_appraise_signature(enum kernel_read_file_id func)
	return false;
}
#endif /* CONFIG_IMA_APPRAISE && CONFIG_INTEGRITY_TRUSTED_KEYRING */

struct ima_namespace {
	struct kref kref;
	struct ns_common ns;
	struct ucounts *ucounts;
	struct user_namespace *user_ns;
} __randomize_layout;

extern struct ima_namespace init_ima_ns;

#ifdef CONFIG_IMA_NS
struct ima_namespace *copy_ima_ns(unsigned long flags,
				  struct user_namespace *user_ns,
				  struct ima_namespace *old_ns);

void free_ima_ns(struct kref *kref);

int imans_on_fork(struct nsproxy *nsproxy, struct task_struct *tsk);

static inline struct ima_namespace *get_ima_ns(struct ima_namespace *ns)
{
	if (ns)
		kref_get(&ns->kref);
	return ns;
}
static inline void put_ima_ns(struct ima_namespace *ns)
{
	if (ns)
		kref_put(&ns->kref, free_ima_ns);
}

#else
static inline struct ima_namespace *copy_ima_ns(unsigned long flags,
						struct user_namespace *user_ns,
						struct ima_namespace *old_ns)
{
	return old_ns;
}

static inline int imans_on_fork(struct nsproxy *nsproxy,
				struct task_struct *tsk)
{
	return 0;
}

static inline struct ima_namespace *get_ima_ns(struct ima_namespace *ns)
{
	return ns;
}

static inline void put_ima_ns(struct ima_namespace *ns)
{
}
#endif /* CONFIG_IMA_NS */
#endif /* _LINUX_IMA_H */
+3 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ struct uts_namespace;
struct ipc_namespace;
struct pid_namespace;
struct cgroup_namespace;
struct ima_namespace;
struct fs_struct;

/*
@@ -38,6 +39,8 @@ struct nsproxy {
	struct time_namespace *time_ns;
	struct time_namespace *time_ns_for_children;
	struct cgroup_namespace *cgroup_ns;
	struct ima_namespace *ima_ns;
	struct ima_namespace *ima_ns_for_children;
};
extern struct nsproxy init_nsproxy;

+4 −1
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@ struct inode;
struct proc_ns_operations {
	const char *name;
	const char *real_ns_name;
	int type;
	uint64_t type;
	struct ns_common *(*get)(struct task_struct *task);
	void (*put)(struct ns_common *ns);
	int (*install)(struct nsset *nsset, struct ns_common *ns);
@@ -34,6 +34,8 @@ extern const struct proc_ns_operations mntns_operations;
extern const struct proc_ns_operations cgroupns_operations;
extern const struct proc_ns_operations timens_operations;
extern const struct proc_ns_operations timens_for_children_operations;
extern const struct proc_ns_operations imans_operations;
extern const struct proc_ns_operations imans_for_children_operations;

/*
 * We always define these enumerators
@@ -46,6 +48,7 @@ enum {
	PROC_PID_INIT_INO	= 0xEFFFFFFCU,
	PROC_CGROUP_INIT_INO	= 0xEFFFFFFBU,
	PROC_TIME_INIT_INO	= 0xEFFFFFFAU,
	PROC_IMA_INIT_INO	= 0xEFFFFFF9U,
};

#ifdef CONFIG_PROC_FS
+1 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ enum ucount_type {
	UCOUNT_MNT_NAMESPACES,
	UCOUNT_CGROUP_NAMESPACES,
	UCOUNT_TIME_NAMESPACES,
	UCOUNT_IMA_NAMESPACES,
#ifdef CONFIG_INOTIFY_USER
	UCOUNT_INOTIFY_INSTANCES,
	UCOUNT_INOTIFY_WATCHES,
Loading