Message ID | 20211216054323.1707384-2-stefanb@linux.vnet.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | ima: Namespace IMA with audit support in IMA-ns | expand |
On Thu, Dec 16, 2021 at 12:43:10AM -0500, Stefan Berger wrote: > From: Stefan Berger <stefanb@linux.ibm.com> > > Implement an IMA namespace data structure that gets created alongside a > user namespace with CLONE_NEWUSER. This lays down the foundation for > namespacing the different aspects of IMA (eg. IMA-audit, IMA-measurement, > IMA-appraisal). > > Signed-off-by: Stefan Berger <stefanb@linux.ibm.com> > Suggested-by: James Bottomley <James.Bottomley@HansenPartnership.com> > --- > include/linux/ima.h | 33 ++++++++++++ > include/linux/user_namespace.h | 4 ++ > init/Kconfig | 10 ++++ > kernel/user.c | 7 +++ > kernel/user_namespace.c | 8 +++ > security/integrity/ima/Makefile | 3 +- > security/integrity/ima/ima.h | 8 +++ > security/integrity/ima/ima_init.c | 4 ++ > security/integrity/ima/ima_init_ima_ns.c | 28 ++++++++++ > security/integrity/ima/ima_ns.c | 65 ++++++++++++++++++++++++ > 10 files changed, 169 insertions(+), 1 deletion(-) > create mode 100644 security/integrity/ima/ima_init_ima_ns.c > create mode 100644 security/integrity/ima/ima_ns.c > > diff --git a/include/linux/ima.h b/include/linux/ima.h > index b6ab66a546ae..61461ee5b208 100644 > --- a/include/linux/ima.h > +++ b/include/linux/ima.h > @@ -11,6 +11,7 @@ > #include <linux/fs.h> > #include <linux/security.h> > #include <linux/kexec.h> > +#include <linux/user_namespace.h> > #include <crypto/hash_info.h> > struct linux_binprm; > > @@ -210,6 +211,38 @@ static inline int ima_inode_removexattr(struct dentry *dentry, > } > #endif /* CONFIG_IMA_APPRAISE */ > > +extern struct ima_namespace init_ima_ns; > + > +#ifdef CONFIG_IMA_NS > + > +void free_ima_ns(struct user_namespace *ns); > +int create_ima_ns(struct user_namespace *user_ns); > + > +static inline struct ima_namespace *get_current_ns(void) > +{ > + return current_user_ns()->ima_ns; > +} > + > +#else > + > +static inline void free_ima_ns(struct user_namespace *user_ns) > +{ > +} > + > +static inline int create_ima_ns(struct user_namespace *user_ns) > +{ > +#ifdef CONFIG_IMA > + user_ns->ima_ns = &init_ima_ns; > +#endif > + return 0; > +} > + > +static inline struct ima_namespace *get_current_ns(void) > +{ > + return &init_ima_ns; > +} > +#endif /* CONFIG_IMA_NS */ > + > #if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING) > extern bool ima_appraise_signature(enum kernel_read_file_id func); > #else > diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h > index 33a4240e6a6f..5249db04d62b 100644 > --- a/include/linux/user_namespace.h > +++ b/include/linux/user_namespace.h > @@ -36,6 +36,7 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */ > #define USERNS_INIT_FLAGS USERNS_SETGROUPS_ALLOWED > > struct ucounts; > +struct ima_namespace; > > enum ucount_type { > UCOUNT_USER_NAMESPACES, > @@ -99,6 +100,9 @@ struct user_namespace { > #endif > struct ucounts *ucounts; > long ucount_max[UCOUNT_COUNTS]; > +#ifdef CONFIG_IMA > + struct ima_namespace *ima_ns; > +#endif > } __randomize_layout; > > struct ucounts { > diff --git a/init/Kconfig b/init/Kconfig > index 11f8a845f259..27890607e8cb 100644 > --- a/init/Kconfig > +++ b/init/Kconfig > @@ -1242,6 +1242,16 @@ config NET_NS > Allow user space to create what appear to be multiple instances > of the network stack. > > +config IMA_NS > + bool "IMA namespace" > + depends on USER_NS > + depends on IMA > + default y > + help > + Allow the creation of IMA namespaces for each user namespace. > + Namespaced IMA enables having IMA features work separately > + in each IMA namespace. > + > endif # NAMESPACES > > config CHECKPOINT_RESTORE > diff --git a/kernel/user.c b/kernel/user.c > index e2cf8c22b539..287751d89b44 100644 > --- a/kernel/user.c > +++ b/kernel/user.c > @@ -20,6 +20,10 @@ > #include <linux/user_namespace.h> > #include <linux/proc_ns.h> > > +#ifdef CONFIG_IMA > +extern struct ima_namespace init_ima_ns; > +#endif > + > /* > * userns count is 1 for root user, 1 for init_uts_ns, > * and 1 for... ? > @@ -67,6 +71,9 @@ struct user_namespace init_user_ns = { > .keyring_name_list = LIST_HEAD_INIT(init_user_ns.keyring_name_list), > .keyring_sem = __RWSEM_INITIALIZER(init_user_ns.keyring_sem), > #endif > +#ifdef CONFIG_IMA > + .ima_ns = &init_ima_ns, > +#endif > }; > EXPORT_SYMBOL_GPL(init_user_ns); > > diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c > index 6b2e3ca7ee99..6fa01323aac9 100644 > --- a/kernel/user_namespace.c > +++ b/kernel/user_namespace.c > @@ -20,6 +20,7 @@ > #include <linux/fs_struct.h> > #include <linux/bsearch.h> > #include <linux/sort.h> > +#include <linux/ima.h> > > static struct kmem_cache *user_ns_cachep __read_mostly; > static DEFINE_MUTEX(userns_state_mutex); > @@ -141,8 +142,14 @@ int create_user_ns(struct cred *new) > if (!setup_userns_sysctls(ns)) > goto fail_keyring; > > + ret = create_ima_ns(ns); Instead of greedily allocating a new ima namespace for each new user namespace creation and wasting memory that is likely wasted since most containers won't use ima (for a long time at least) have you considered lazily allocating it like I suggested in one of my first reviews? So under the assumption that the only way for a container to get its own ima policy it needs to have mounted a new securityfs instance you can move the ima namespace allocation into fill_super/ima_fs_ns_init(): From 46fd4f19e1360bee167fccb11e793a3a3331ccc2 Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brauner@ubuntu.com> Date: Thu, 16 Dec 2021 14:57:30 +0100 Subject: [PATCH] !!!! HERE BE DRAGONS - COMPLETELY UNTESTED !!!! Lazily initialize ima_ns. This avoids pointlessly wasting memory that is never needed or used which I think will be the case for most containers. --- include/linux/ima.h | 2 +- kernel/user_namespace.c | 6 ------ security/integrity/ima/ima_fs.c | 20 ++++++++++++++++++-- security/integrity/ima/ima_main.c | 5 ++++- security/integrity/ima/ima_ns.c | 7 ++++++- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index a2705aa5242a..cb1b94df11a1 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -230,7 +230,7 @@ int create_ima_ns(struct user_namespace *user_ns); static inline struct ima_namespace *get_current_ns(void) { - return current_user_ns()->ima_ns; + return smp_load_acquire(¤t_user_ns()->ima_ns); } static inline int ima_securityfs_init(struct user_namespace *user_ns, diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 6fa01323aac9..653f8fa83b69 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -142,14 +142,8 @@ int create_user_ns(struct cred *new) if (!setup_userns_sysctls(ns)) goto fail_keyring; - ret = create_ima_ns(ns); - if (ret) - goto fail_sysctls; - set_cred_user_ns(new, ns); return 0; -fail_sysctls: - retire_userns_sysctls(ns); fail_keyring: #ifdef CONFIG_PERSISTENT_KEYRINGS key_put(ns->persistent_keyring_register); diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 3b8001ba62e3..971620a22dab 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -378,7 +378,7 @@ static const struct seq_operations ima_policy_seqops = { static int ima_open_policy(struct inode *inode, struct file *filp) { struct user_namespace *user_ns = ima_user_ns_from_file(filp); - struct ima_namespace *ns = user_ns->ima_ns; + struct ima_namespace *ns = user_ns->ima_ns; /* no need to use acquire semantics it's guaranteed to be initialized */ if (!(filp->f_flags & O_WRONLY)) { #ifndef CONFIG_IMA_READ_POLICY @@ -450,7 +450,8 @@ static const struct file_operations ima_measure_policy_ops = { int ima_fs_ns_init(struct user_namespace *user_ns, struct dentry *root) { - struct ima_namespace *ns = user_ns->ima_ns; + int ret; + struct ima_namespace *ns = user_ns->ima_ns; /* no need to use acquire semantics it's guaranteed to be initialized */ struct dentry *int_dir; struct dentry *ima_dir = NULL; struct dentry *ima_symlink = NULL; @@ -459,6 +460,21 @@ int ima_fs_ns_init(struct user_namespace *user_ns, struct dentry *root) struct dentry *runtime_measurements_count = NULL; struct dentry *violations = NULL; + /* + * While multiple superblocks can exist they are keyed by userns in + * s_fs_info for securityfs. The first time a userns mounts a + * securityfs instance we lazily allocate the ima_namespace for the + * userns since that's the only way a userns can meaningfully use ima. + * The vfs ensure we're the only one to call fill_super() and hence + * ima_fs_ns_init() so we don't need any memory barriers here, i.e. + * user_ns->ima_ns can't change while we're in here. + */ + if (!ns) { + ret = create_ima_ns(user_ns); + if (ret) + return ret; + } + /* FIXME: update when evm and integrity are namespaced */ if (user_ns != &init_user_ns) { int_dir = diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 4c85a8df3c86..a0e71416561d 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -414,7 +414,10 @@ static int process_measurement(struct ima_namespace *ns, int ret = 0; while (user_ns) { - ns = user_ns->ima_ns; + /* the container has not loaded a separate policy (yet) */ + ns = smp_load_acquire(&user_ns->ima_ns); + if (!ns) + continue; ret = __process_measurement(ns, file, cred, secid, buf, size, mask, func); diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index d192a80c927f..5c7177b07344 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -31,7 +31,8 @@ int create_ima_ns(struct user_namespace *user_ns) if (err) goto fail_free; - user_ns->ima_ns = ns; + /* Pairs with smp_load_acquire() in get_current_ns() and process_measurement(). */ + smp_store_release(&user_ns->ima_ns, ns); return 0; @@ -52,6 +53,10 @@ static void destroy_ima_ns(struct ima_namespace *ns) void free_ima_ns(struct user_namespace *user_ns) { + /* No need to use acquire semantics as the userns can't be reached + * anymore from userspace so either ima_ns has been initialized or it + * never has. + */ struct ima_namespace *ns = user_ns->ima_ns; if (WARN_ON(ns == &init_ima_ns))
On Thu, 2021-12-16 at 15:08 +0100, Christian Brauner wrote: > On Thu, Dec 16, 2021 at 12:43:10AM -0500, Stefan Berger wrote: [...] > > diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c > > index 6b2e3ca7ee99..6fa01323aac9 100644 > > --- a/kernel/user_namespace.c > > +++ b/kernel/user_namespace.c > > @@ -20,6 +20,7 @@ > > #include <linux/fs_struct.h> > > #include <linux/bsearch.h> > > #include <linux/sort.h> > > +#include <linux/ima.h> > > > > static struct kmem_cache *user_ns_cachep __read_mostly; > > static DEFINE_MUTEX(userns_state_mutex); > > @@ -141,8 +142,14 @@ int create_user_ns(struct cred *new) > > if (!setup_userns_sysctls(ns)) > > goto fail_keyring; > > > > + ret = create_ima_ns(ns); > > Instead of greedily allocating a new ima namespace for each new user > namespace creation and wasting memory that is likely wasted since > most containers won't use ima (for a long time at least) have you > considered lazily allocating it like I suggested in one of my first > reviews? > > So under the assumption that the only way for a container to get its > own ima policy it needs to have mounted a new securityfs instance you > can move the ima namespace allocation into > fill_super/ima_fs_ns_init(): The current patch set has the ima namespace born with an empty policy, meaning it can never do anything until a new policy is inserted via a write to the securityfs, and therefore the IMA namespace could be lazily allocated. However, that's not quite how the initial IMA namespace behaves because a policy can be passed in on the kernel command line (or built into the kernel). If the ima NS were born with a default policy (say taken from the initial IMA default policy, or simply inherited from the parent at creation time) then we wouldn't be able to do lazy allocation. Before we tie ourselves to never being able to have a default policy for an IMA namespace, perhaps we should discuss if this is the correct behaviour we want to nail into the system. James
On Thu, Dec 16, 2021 at 04:52:47PM -0500, James Bottomley wrote: > On Thu, 2021-12-16 at 15:08 +0100, Christian Brauner wrote: > > On Thu, Dec 16, 2021 at 12:43:10AM -0500, Stefan Berger wrote: > [...] > > > diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c > > > index 6b2e3ca7ee99..6fa01323aac9 100644 > > > --- a/kernel/user_namespace.c > > > +++ b/kernel/user_namespace.c > > > @@ -20,6 +20,7 @@ > > > #include <linux/fs_struct.h> > > > #include <linux/bsearch.h> > > > #include <linux/sort.h> > > > +#include <linux/ima.h> > > > > > > static struct kmem_cache *user_ns_cachep __read_mostly; > > > static DEFINE_MUTEX(userns_state_mutex); > > > @@ -141,8 +142,14 @@ int create_user_ns(struct cred *new) > > > if (!setup_userns_sysctls(ns)) > > > goto fail_keyring; > > > > > > + ret = create_ima_ns(ns); > > > > Instead of greedily allocating a new ima namespace for each new user > > namespace creation and wasting memory that is likely wasted since > > most containers won't use ima (for a long time at least) have you > > considered lazily allocating it like I suggested in one of my first > > reviews? > > > > So under the assumption that the only way for a container to get its > > own ima policy it needs to have mounted a new securityfs instance you > > can move the ima namespace allocation into > > fill_super/ima_fs_ns_init(): > > The current patch set has the ima namespace born with an empty policy, > meaning it can never do anything until a new policy is inserted via a > write to the securityfs, and therefore the IMA namespace could be > lazily allocated. However, that's not quite how the initial IMA > namespace behaves because a policy can be passed in on the kernel > command line (or built into the kernel). If the ima NS were born with > a default policy (say taken from the initial IMA default policy, or > simply inherited from the parent at creation time) then we wouldn't be > able to do lazy allocation. Before we tie ourselves to never being > able to have a default policy for an IMA namespace, perhaps we should > discuss if this is the correct behaviour we want to nail into the > system. If ima in the future decides to do policy inheritance it can simply switch from delayed allocation at mount time to allocation at userns creation time. So we can proceed with lazy allocation without much problem for now. In addition what is happening now is in effect policy inheritance, i.e. each container is bound by the parent ima_ns policy until it decides to setup its own. Aside from that the container manager can and should be responsible for the default ima policy to apply to containers. The default ima policy can be passed through the spec file, configuration file, or - for the hardcore people - compiled into the container manager itself. This is not different from LSMs (e.g. AppArmor, seccomp) where the policy for each container is generated from a fixed template that was built into the container manager binary and then written via /proc/<pid>/attr/current during container setup. During container setup the process that ultimately calls exec to execute the payload does all of the required setup work. The setup process should not be automatically bound by a default policy that gets created when the userns is created. That will just cause problems during container setup. Until the setup process has decided that all preliminary setup steps are done only the ancestor policy should restrict it. This is exactly the same for all LSMs and seccomp. They all are usually setup closely before calling exec. I see no reason for ima to diverge from this model.
diff --git a/include/linux/ima.h b/include/linux/ima.h index b6ab66a546ae..61461ee5b208 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -11,6 +11,7 @@ #include <linux/fs.h> #include <linux/security.h> #include <linux/kexec.h> +#include <linux/user_namespace.h> #include <crypto/hash_info.h> struct linux_binprm; @@ -210,6 +211,38 @@ static inline int ima_inode_removexattr(struct dentry *dentry, } #endif /* CONFIG_IMA_APPRAISE */ +extern struct ima_namespace init_ima_ns; + +#ifdef CONFIG_IMA_NS + +void free_ima_ns(struct user_namespace *ns); +int create_ima_ns(struct user_namespace *user_ns); + +static inline struct ima_namespace *get_current_ns(void) +{ + return current_user_ns()->ima_ns; +} + +#else + +static inline void free_ima_ns(struct user_namespace *user_ns) +{ +} + +static inline int create_ima_ns(struct user_namespace *user_ns) +{ +#ifdef CONFIG_IMA + user_ns->ima_ns = &init_ima_ns; +#endif + return 0; +} + +static inline struct ima_namespace *get_current_ns(void) +{ + return &init_ima_ns; +} +#endif /* CONFIG_IMA_NS */ + #if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING) extern bool ima_appraise_signature(enum kernel_read_file_id func); #else diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 33a4240e6a6f..5249db04d62b 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -36,6 +36,7 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */ #define USERNS_INIT_FLAGS USERNS_SETGROUPS_ALLOWED struct ucounts; +struct ima_namespace; enum ucount_type { UCOUNT_USER_NAMESPACES, @@ -99,6 +100,9 @@ struct user_namespace { #endif struct ucounts *ucounts; long ucount_max[UCOUNT_COUNTS]; +#ifdef CONFIG_IMA + struct ima_namespace *ima_ns; +#endif } __randomize_layout; struct ucounts { diff --git a/init/Kconfig b/init/Kconfig index 11f8a845f259..27890607e8cb 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1242,6 +1242,16 @@ config NET_NS Allow user space to create what appear to be multiple instances of the network stack. +config IMA_NS + bool "IMA namespace" + depends on USER_NS + depends on IMA + default y + help + Allow the creation of IMA namespaces for each user namespace. + Namespaced IMA enables having IMA features work separately + in each IMA namespace. + endif # NAMESPACES config CHECKPOINT_RESTORE diff --git a/kernel/user.c b/kernel/user.c index e2cf8c22b539..287751d89b44 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -20,6 +20,10 @@ #include <linux/user_namespace.h> #include <linux/proc_ns.h> +#ifdef CONFIG_IMA +extern struct ima_namespace init_ima_ns; +#endif + /* * userns count is 1 for root user, 1 for init_uts_ns, * and 1 for... ? @@ -67,6 +71,9 @@ struct user_namespace init_user_ns = { .keyring_name_list = LIST_HEAD_INIT(init_user_ns.keyring_name_list), .keyring_sem = __RWSEM_INITIALIZER(init_user_ns.keyring_sem), #endif +#ifdef CONFIG_IMA + .ima_ns = &init_ima_ns, +#endif }; EXPORT_SYMBOL_GPL(init_user_ns); diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 6b2e3ca7ee99..6fa01323aac9 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -20,6 +20,7 @@ #include <linux/fs_struct.h> #include <linux/bsearch.h> #include <linux/sort.h> +#include <linux/ima.h> static struct kmem_cache *user_ns_cachep __read_mostly; static DEFINE_MUTEX(userns_state_mutex); @@ -141,8 +142,14 @@ int create_user_ns(struct cred *new) if (!setup_userns_sysctls(ns)) goto fail_keyring; + ret = create_ima_ns(ns); + if (ret) + goto fail_sysctls; + set_cred_user_ns(new, ns); return 0; +fail_sysctls: + retire_userns_sysctls(ns); fail_keyring: #ifdef CONFIG_PERSISTENT_KEYRINGS key_put(ns->persistent_keyring_register); @@ -196,6 +203,7 @@ static void free_user_ns(struct work_struct *work) kfree(ns->projid_map.forward); kfree(ns->projid_map.reverse); } + free_ima_ns(ns); retire_userns_sysctls(ns); key_free_user_ns(ns); ns_free_inum(&ns->ns); diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile index 2499f2485c04..b86a35fbed60 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -7,13 +7,14 @@ obj-$(CONFIG_IMA) += ima.o ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ - ima_policy.o ima_template.o ima_template_lib.o + ima_policy.o ima_template.o ima_template_lib.o ima_init_ima_ns.o ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o ima-$(CONFIG_IMA_APPRAISE_MODSIG) += ima_modsig.o ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o ima-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o ima-$(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) += ima_asymmetric_keys.o ima-$(CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS) += ima_queue_keys.o +ima-$(CONFIG_IMA_NS) += ima_ns.o ifeq ($(CONFIG_EFI),y) ima-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT) += ima_efi.o diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index be965a8715e4..4606d3b1493f 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -119,6 +119,10 @@ struct ima_kexec_hdr { u64 count; }; +struct ima_namespace { + int avoid_zero_size; +} __randomize_layout; + extern const int read_idmap[]; #ifdef CONFIG_HAVE_IMA_KEXEC @@ -418,6 +422,10 @@ static inline void ima_free_modsig(struct modsig *modsig) } #endif /* CONFIG_IMA_APPRAISE_MODSIG */ +int ima_ns_init(void); +struct ima_namespace; +int ima_init_namespace(struct ima_namespace *ns); + /* LSM based policy rules require audit */ #ifdef CONFIG_IMA_LSM_RULES diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index b26fa67476b4..f6ae4557a0da 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -120,6 +120,10 @@ int __init ima_init(void) { int rc; + rc = ima_ns_init(); + if (rc) + return rc; + ima_tpm_chip = tpm_default_chip(); if (!ima_tpm_chip) pr_info("No TPM chip found, activating TPM-bypass!\n"); diff --git a/security/integrity/ima/ima_init_ima_ns.c b/security/integrity/ima/ima_init_ima_ns.c new file mode 100644 index 000000000000..46d8cb2113a1 --- /dev/null +++ b/security/integrity/ima/ima_init_ima_ns.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2016-2021 IBM Corporation + * Author: + * Yuqiong Sun <suny@us.ibm.com> + * Stefan Berger <stefanb@linux.vnet.ibm.com> + */ + +#include <linux/export.h> +#include <linux/user_namespace.h> +#include <linux/proc_ns.h> +#include <linux/ima.h> + +#include "ima.h" + +int ima_init_namespace(struct ima_namespace *ns) +{ + return 0; +} + +int __init ima_ns_init(void) +{ + return ima_init_namespace(&init_ima_ns); +} + +struct ima_namespace init_ima_ns = { +}; +EXPORT_SYMBOL(init_ima_ns); diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c new file mode 100644 index 000000000000..bc9a2c11d70a --- /dev/null +++ b/security/integrity/ima/ima_ns.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2016-2021 IBM Corporation + * Author: + * Yuqiong Sun <suny@us.ibm.com> + * Stefan Berger <stefanb@linux.vnet.ibm.com> + */ + +#include <linux/kref.h> +#include <linux/slab.h> +#include <linux/ima.h> +#include <linux/mount.h> +#include <linux/proc_ns.h> +#include <linux/lsm_hooks.h> + +#include "ima.h" + +static struct kmem_cache *imans_cachep; + +int create_ima_ns(struct user_namespace *user_ns) +{ + struct ima_namespace *ns; + int err; + + ns = kmem_cache_zalloc(imans_cachep, GFP_KERNEL); + if (!ns) + return -ENOMEM; + pr_debug("NEW ima_ns: 0x%p\n", ns); + + err = ima_init_namespace(ns); + if (err) + goto fail_free; + + user_ns->ima_ns = ns; + + return 0; + +fail_free: + kmem_cache_free(imans_cachep, ns); + + return err; +} + +static void destroy_ima_ns(struct ima_namespace *ns) +{ + pr_debug("DESTROY ima_ns: 0x%p\n", ns); + kmem_cache_free(imans_cachep, ns); +} + +void free_ima_ns(struct user_namespace *user_ns) +{ + struct ima_namespace *ns = user_ns->ima_ns; + + if (WARN_ON(ns == &init_ima_ns)) + return; + + destroy_ima_ns(ns); +} + +static int __init imans_cache_init(void) +{ + imans_cachep = KMEM_CACHE(ima_namespace, SLAB_PANIC); + return 0; +} +subsys_initcall(imans_cache_init)