diff mbox series

[v12,03/26] ima: Define ima_namespace struct and start moving variables into it

Message ID 20220420140633.753772-4-stefanb@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series ima: Namespace IMA with audit support in IMA-ns | expand

Commit Message

Stefan Berger April 20, 2022, 2:06 p.m. UTC
Define the ima_namespace structure and the ima_namespace variable
init_ima_ns for the host's IMA namespace. Implement the basic functions
ima_ns_init() and ima_init_namespace() for namespacing support.

Move variables related to the IMA policy into the ima_namespace. This way
the IMA policy of an IMA namespace can be set and displayed using a
front-end like securityfs.

In preparation for IMA namespacing, update the existing functions to
pass the ima_namespace struct. For now, use &init_ima_ns as the current
ima_namespace when a function that is related to a policy rule is called.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Acked-by: Christian Brauner <brauner@kernel.org>
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>

---

v11:
 - Updated commit text
 - Added comments to some fields in the ima_namespace struct

v9:
 - squashed patched 2 and 3 of v8
 - ima_post_read_file: only access ima_appraise in case of init_ima_ns
---
 security/integrity/ima/Makefile              |   2 +-
 security/integrity/ima/ima.h                 |  53 ++++---
 security/integrity/ima/ima_api.c             |   8 +-
 security/integrity/ima/ima_appraise.c        |  28 ++--
 security/integrity/ima/ima_asymmetric_keys.c |   4 +-
 security/integrity/ima/ima_fs.c              |  16 ++-
 security/integrity/ima/ima_init.c            |  12 +-
 security/integrity/ima/ima_init_ima_ns.c     |  29 ++++
 security/integrity/ima/ima_main.c            |  88 +++++++-----
 security/integrity/ima/ima_policy.c          | 142 ++++++++++---------
 security/integrity/ima/ima_queue_keys.c      |  11 +-
 11 files changed, 248 insertions(+), 145 deletions(-)
 create mode 100644 security/integrity/ima/ima_init_ima_ns.c

Comments

Serge Hallyn May 21, 2022, 2:33 a.m. UTC | #1
On Wed, Apr 20, 2022 at 10:06:10AM -0400, Stefan Berger wrote:
> Define the ima_namespace structure and the ima_namespace variable
> init_ima_ns for the host's IMA namespace. Implement the basic functions
> ima_ns_init() and ima_init_namespace() for namespacing support.
> 
> Move variables related to the IMA policy into the ima_namespace. This way
> the IMA policy of an IMA namespace can be set and displayed using a
> front-end like securityfs.
> 
> In preparation for IMA namespacing, update the existing functions to
> pass the ima_namespace struct. For now, use &init_ima_ns as the current
> ima_namespace when a function that is related to a policy rule is called.
> 
> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
> Acked-by: Christian Brauner <brauner@kernel.org>
> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
> 
> ---
> 
> v11:
>  - Updated commit text
>  - Added comments to some fields in the ima_namespace struct
> 
> v9:
>  - squashed patched 2 and 3 of v8
>  - ima_post_read_file: only access ima_appraise in case of init_ima_ns
> ---
>  security/integrity/ima/Makefile              |   2 +-
>  security/integrity/ima/ima.h                 |  53 ++++---
>  security/integrity/ima/ima_api.c             |   8 +-
>  security/integrity/ima/ima_appraise.c        |  28 ++--
>  security/integrity/ima/ima_asymmetric_keys.c |   4 +-
>  security/integrity/ima/ima_fs.c              |  16 ++-
>  security/integrity/ima/ima_init.c            |  12 +-
>  security/integrity/ima/ima_init_ima_ns.c     |  29 ++++
>  security/integrity/ima/ima_main.c            |  88 +++++++-----
>  security/integrity/ima/ima_policy.c          | 142 ++++++++++---------
>  security/integrity/ima/ima_queue_keys.c      |  11 +-
>  11 files changed, 248 insertions(+), 145 deletions(-)
>  create mode 100644 security/integrity/ima/ima_init_ima_ns.c
> 
> diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
> index 2499f2485c04..f8a5e5f3975d 100644
> --- a/security/integrity/ima/Makefile
> +++ b/security/integrity/ima/Makefile
> @@ -7,7 +7,7 @@
>  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
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index be965a8715e4..9bcde1a24e74 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -20,6 +20,7 @@
>  #include <linux/hash.h>
>  #include <linux/tpm.h>
>  #include <linux/audit.h>
> +#include <linux/user_namespace.h>
>  #include <crypto/hash_info.h>
>  
>  #include "../integrity.h"
> @@ -43,9 +44,6 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 };
>  
>  #define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0)
>  
> -/* current content of the policy */
> -extern int ima_policy_flag;
> -
>  /* bitset of digests algorithms allowed in the setxattr hook */
>  extern atomic_t ima_setxattr_allowed_hash_algorithms;
>  
> @@ -119,6 +117,17 @@ struct ima_kexec_hdr {
>  	u64 count;
>  };
>  
> +struct ima_namespace {
> +	/* policy rules */
> +	struct list_head ima_default_rules; /* Kconfig, builtin & arch rules */
> +	struct list_head ima_policy_rules;  /* arch & custom rules */
> +	struct list_head ima_temp_rules;
> +
> +	struct list_head __rcu *ima_rules;  /* Pointer to the current policy */
> +	int ima_policy_flag;
> +} __randomize_layout;
> +extern struct ima_namespace init_ima_ns;
> +
>  extern const int read_idmap[];
>  
>  #ifdef CONFIG_HAVE_IMA_KEXEC
> @@ -136,6 +145,7 @@ extern bool ima_canonical_fmt;
>  /* Internal IMA function definitions */
>  int ima_init(void);
>  int ima_fs_init(void);
> +int ima_ns_init(void);
>  int ima_add_template_entry(struct ima_template_entry *entry, int violation,
>  			   const char *op, struct inode *inode,
>  			   const unsigned char *filename);
> @@ -243,18 +253,19 @@ void ima_init_key_queue(void);
>  bool ima_should_queue_key(void);
>  bool ima_queue_key(struct key *keyring, const void *payload,
>  		   size_t payload_len);
> -void ima_process_queued_keys(void);
> +void ima_process_queued_keys(struct ima_namespace *ns);
>  #else
>  static inline void ima_init_key_queue(void) {}
>  static inline bool ima_should_queue_key(void) { return false; }
>  static inline bool ima_queue_key(struct key *keyring,
>  				 const void *payload,
>  				 size_t payload_len) { return false; }
> -static inline void ima_process_queued_keys(void) {}
> +static inline void ima_process_queued_keys(struct ima_namespace *ns) {}
>  #endif /* CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS */
>  
>  /* LIM API function definitions */
> -int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
> +int ima_get_action(struct ima_namespace *ns,
> +		   struct user_namespace *mnt_userns, struct inode *inode,
>  		   const struct cred *cred, u32 secid, int mask,
>  		   enum ima_hooks func, int *pcr,
>  		   struct ima_template_desc **template_desc,
> @@ -268,7 +279,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
>  			   struct evm_ima_xattr_data *xattr_value,
>  			   int xattr_len, const struct modsig *modsig, int pcr,
>  			   struct ima_template_desc *template_desc);
> -int process_buffer_measurement(struct user_namespace *mnt_userns,
> +int process_buffer_measurement(struct ima_namespace *ns,
> +			       struct user_namespace *mnt_userns,
>  			       struct inode *inode, const void *buf, int size,
>  			       const char *eventname, enum ima_hooks func,
>  			       int pcr, const char *func_data,
> @@ -285,17 +297,18 @@ void ima_free_template_entry(struct ima_template_entry *entry);
>  const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
>  
>  /* IMA policy related functions */
> -int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
> +int ima_match_policy(struct ima_namespace *ns,
> +		     struct user_namespace *mnt_userns, struct inode *inode,
>  		     const struct cred *cred, u32 secid, enum ima_hooks func,
>  		     int mask, int flags, int *pcr,
>  		     struct ima_template_desc **template_desc,
>  		     const char *func_data, unsigned int *allowed_algos);
> -void ima_init_policy(void);
> -void ima_update_policy(void);
> -void ima_update_policy_flags(void);
> -ssize_t ima_parse_add_rule(char *);
> -void ima_delete_rules(void);
> -int ima_check_policy(void);
> +void ima_init_policy(struct ima_namespace *ns);
> +void ima_update_policy(struct ima_namespace *ns);
> +void ima_update_policy_flags(struct ima_namespace *ns);
> +ssize_t ima_parse_add_rule(struct ima_namespace *ns, char *rule);
> +void ima_delete_rules(struct ima_namespace *ns);
> +int ima_check_policy(struct ima_namespace *ns);
>  void *ima_policy_start(struct seq_file *m, loff_t *pos);
>  void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos);
>  void ima_policy_stop(struct seq_file *m, void *v);
> @@ -311,14 +324,16 @@ int ima_policy_show(struct seq_file *m, void *v);
>  #define IMA_APPRAISE_KEXEC	0x40
>  
>  #ifdef CONFIG_IMA_APPRAISE
> -int ima_check_blacklist(struct integrity_iint_cache *iint,
> +int ima_check_blacklist(struct ima_namespace *ns,
> +			struct integrity_iint_cache *iint,
>  			const struct modsig *modsig, int pcr);
>  int ima_appraise_measurement(enum ima_hooks func,
>  			     struct integrity_iint_cache *iint,
>  			     struct file *file, const unsigned char *filename,
>  			     struct evm_ima_xattr_data *xattr_value,
>  			     int xattr_len, const struct modsig *modsig);
> -int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
> +int ima_must_appraise(struct ima_namespace *ns,
> +		      struct user_namespace *mnt_userns, struct inode *inode,
>  		      int mask, enum ima_hooks func);
>  void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
>  enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
> @@ -329,7 +344,8 @@ int ima_read_xattr(struct dentry *dentry,
>  		   struct evm_ima_xattr_data **xattr_value);
>  
>  #else
> -static inline int ima_check_blacklist(struct integrity_iint_cache *iint,
> +static inline int ima_check_blacklist(struct ima_namespace *ns,
> +				      struct integrity_iint_cache *iint,
>  				      const struct modsig *modsig, int pcr)
>  {
>  	return 0;
> @@ -346,7 +362,8 @@ static inline int ima_appraise_measurement(enum ima_hooks func,
>  	return INTEGRITY_UNKNOWN;
>  }
>  
> -static inline int ima_must_appraise(struct user_namespace *mnt_userns,
> +static inline int ima_must_appraise(struct ima_namespace *ns,
> +				    struct user_namespace *mnt_userns,
>  				    struct inode *inode, int mask,
>  				    enum ima_hooks func)
>  {
> diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
> index c6805af46211..90ef246a9f43 100644
> --- a/security/integrity/ima/ima_api.c
> +++ b/security/integrity/ima/ima_api.c
> @@ -162,6 +162,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
>  
>  /**
>   * ima_get_action - appraise & measure decision based on policy.
> + * @ns: IMA namespace that has the policy
>   * @mnt_userns:	user namespace of the mount the inode was found from
>   * @inode: pointer to the inode associated with the object being validated
>   * @cred: pointer to credentials structure to validate
> @@ -185,7 +186,8 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
>   * Returns IMA_MEASURE, IMA_APPRAISE mask.
>   *
>   */
> -int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
> +int ima_get_action(struct ima_namespace *ns,
> +		   struct user_namespace *mnt_userns, struct inode *inode,
>  		   const struct cred *cred, u32 secid, int mask,
>  		   enum ima_hooks func, int *pcr,
>  		   struct ima_template_desc **template_desc,
> @@ -193,9 +195,9 @@ int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
>  {
>  	int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
>  
> -	flags &= ima_policy_flag;
> +	flags &= ns->ima_policy_flag;
>  
> -	return ima_match_policy(mnt_userns, inode, cred, secid, func, mask,
> +	return ima_match_policy(ns, mnt_userns, inode, cred, secid, func, mask,
>  				flags, pcr, template_desc, func_data,
>  				allowed_algos);
>  }
> diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
> index 17232bbfb9f9..f1b99b895c68 100644
> --- a/security/integrity/ima/ima_appraise.c
> +++ b/security/integrity/ima/ima_appraise.c
> @@ -68,7 +68,8 @@ bool is_ima_appraise_enabled(void)
>   *
>   * Return 1 to appraise or hash
>   */
> -int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
> +int ima_must_appraise(struct ima_namespace *ns,
> +		      struct user_namespace *mnt_userns, struct inode *inode,
>  		      int mask, enum ima_hooks func)
>  {
>  	u32 secid;
> @@ -77,7 +78,7 @@ int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
>  		return 0;
>  
>  	security_current_getsecid_subj(&secid);
> -	return ima_match_policy(mnt_userns, inode, current_cred(), secid,
> +	return ima_match_policy(ns, mnt_userns, inode, current_cred(), secid,
>  				func, mask, IMA_APPRAISE | IMA_HASH, NULL,
>  				NULL, NULL, NULL);
>  }
> @@ -341,7 +342,8 @@ static int modsig_verify(enum ima_hooks func, const struct modsig *modsig,
>   *
>   * Returns -EPERM if the hash is blacklisted.
>   */
> -int ima_check_blacklist(struct integrity_iint_cache *iint,
> +int ima_check_blacklist(struct ima_namespace *ns,
> +			struct integrity_iint_cache *iint,
>  			const struct modsig *modsig, int pcr)
>  {
>  	enum hash_algo hash_algo;
> @@ -357,7 +359,8 @@ int ima_check_blacklist(struct integrity_iint_cache *iint,
>  
>  		rc = is_binary_blacklisted(digest, digestsize);
>  		if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
> -			process_buffer_measurement(&init_user_ns, NULL, digest, digestsize,
> +			process_buffer_measurement(ns, &init_user_ns, NULL,
> +						   digest, digestsize,
>  						   "blacklisted-hash", NONE,
>  						   pcr, NULL, false, NULL, 0);
>  	}
> @@ -527,14 +530,16 @@ void ima_inode_post_setattr(struct user_namespace *mnt_userns,
>  			    struct dentry *dentry)
>  {
>  	struct inode *inode = d_backing_inode(dentry);
> +	struct ima_namespace *ns = &init_ima_ns;
>  	struct integrity_iint_cache *iint;
>  	int action;
>  
> -	if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
> +	if (!(ns->ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
>  	    || !(inode->i_opflags & IOP_XATTR))
>  		return;
>  
> -	action = ima_must_appraise(mnt_userns, inode, MAY_ACCESS, POST_SETATTR);
> +	action = ima_must_appraise(ns, mnt_userns, inode, MAY_ACCESS,
> +				   POST_SETATTR);
>  	iint = integrity_iint_find(inode);
>  	if (iint) {
>  		set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags);
> @@ -559,11 +564,12 @@ static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name,
>  	return 0;
>  }
>  
> -static void ima_reset_appraise_flags(struct inode *inode, int digsig)
> +static void ima_reset_appraise_flags(struct ima_namespace *ns,
> +				     struct inode *inode, int digsig)
>  {
>  	struct integrity_iint_cache *iint;
>  
> -	if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode))
> +	if (!(ns->ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode))
>  		return;
>  
>  	iint = integrity_iint_find(inode);
> @@ -641,6 +647,7 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
>  		       const void *xattr_value, size_t xattr_value_len)
>  {
>  	const struct evm_ima_xattr_data *xvalue = xattr_value;
> +	struct ima_namespace *ns = &init_ima_ns;
>  	int digsig = 0;
>  	int result;
>  
> @@ -658,18 +665,19 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
>  		if (result)
>  			return result;
>  
> -		ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
> +		ima_reset_appraise_flags(ns, d_backing_inode(dentry), digsig);
>  	}
>  	return result;
>  }
>  
>  int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	int result;
>  
>  	result = ima_protect_xattr(dentry, xattr_name, NULL, 0);
>  	if (result == 1 || evm_revalidate_status(xattr_name)) {
> -		ima_reset_appraise_flags(d_backing_inode(dentry), 0);
> +		ima_reset_appraise_flags(ns, d_backing_inode(dentry), 0);
>  		if (result == 1)
>  			result = 0;
>  	}
> diff --git a/security/integrity/ima/ima_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c
> index f6aa0b47a772..70d87df26068 100644
> --- a/security/integrity/ima/ima_asymmetric_keys.c
> +++ b/security/integrity/ima/ima_asymmetric_keys.c
> @@ -30,6 +30,7 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
>  				   const void *payload, size_t payload_len,
>  				   unsigned long flags, bool create)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	bool queued = false;
>  
>  	/* Only asymmetric keys are handled by this hook. */
> @@ -60,7 +61,8 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
>  	 * if the IMA policy is configured to measure a key linked
>  	 * to the given keyring.
>  	 */
> -	process_buffer_measurement(&init_user_ns, NULL, payload, payload_len,
> +	process_buffer_measurement(ns, &init_user_ns, NULL,
> +				   payload, payload_len,
>  				   keyring->description, KEY_CHECK, 0,
>  				   keyring->description, false, NULL, 0);
>  }
> diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
> index cd1683dad3bf..f7ad93a56982 100644
> --- a/security/integrity/ima/ima_fs.c
> +++ b/security/integrity/ima/ima_fs.c
> @@ -271,7 +271,7 @@ static const struct file_operations ima_ascii_measurements_ops = {
>  	.release = seq_release,
>  };
>  
> -static ssize_t ima_read_policy(char *path)
> +static ssize_t ima_read_policy(struct ima_namespace *ns, char *path)
>  {
>  	void *data = NULL;
>  	char *datap;
> @@ -296,7 +296,7 @@ static ssize_t ima_read_policy(char *path)
>  	datap = data;
>  	while (size > 0 && (p = strsep(&datap, "\n"))) {
>  		pr_debug("rule: %s\n", p);
> -		rc = ima_parse_add_rule(p);
> +		rc = ima_parse_add_rule(ns, p);
>  		if (rc < 0)
>  			break;
>  		size -= rc;
> @@ -314,6 +314,7 @@ static ssize_t ima_read_policy(char *path)
>  static ssize_t ima_write_policy(struct file *file, const char __user *buf,
>  				size_t datalen, loff_t *ppos)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	char *data;
>  	ssize_t result;
>  
> @@ -336,7 +337,7 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf,
>  		goto out_free;
>  
>  	if (data[0] == '/') {
> -		result = ima_read_policy(data);
> +		result = ima_read_policy(ns, data);
>  	} else if (ima_appraise & IMA_APPRAISE_POLICY) {
>  		pr_err("signed policy file (specified as an absolute pathname) required\n");
>  		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
> @@ -344,7 +345,7 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf,
>  				    1, 0);
>  		result = -EACCES;
>  	} else {
> -		result = ima_parse_add_rule(data);
> +		result = ima_parse_add_rule(ns, data);
>  	}
>  	mutex_unlock(&ima_write_mutex);
>  out_free:
> @@ -410,11 +411,12 @@ static int ima_open_policy(struct inode *inode, struct file *filp)
>  static int ima_release_policy(struct inode *inode, struct file *file)
>  {
>  	const char *cause = valid_policy ? "completed" : "failed";
> +	struct ima_namespace *ns = &init_ima_ns;
>  
>  	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
>  		return seq_release(inode, file);
>  
> -	if (valid_policy && ima_check_policy() < 0) {
> +	if (valid_policy && ima_check_policy(ns) < 0) {
>  		cause = "failed";
>  		valid_policy = 0;
>  	}
> @@ -424,13 +426,13 @@ static int ima_release_policy(struct inode *inode, struct file *file)
>  			    "policy_update", cause, !valid_policy, 0);
>  
>  	if (!valid_policy) {
> -		ima_delete_rules();
> +		ima_delete_rules(ns);
>  		valid_policy = 1;
>  		clear_bit(IMA_FS_BUSY, &ima_fs_flags);
>  		return 0;
>  	}
>  
> -	ima_update_policy();
> +	ima_update_policy(ns);
>  #if !defined(CONFIG_IMA_WRITE_POLICY) && !defined(CONFIG_IMA_READ_POLICY)
>  	securityfs_remove(ima_policy);
>  	ima_policy = NULL;
> diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
> index 63979aefc95f..7e5b4187035d 100644
> --- a/security/integrity/ima/ima_init.c
> +++ b/security/integrity/ima/ima_init.c
> @@ -101,15 +101,15 @@ static int __init ima_add_boot_aggregate(void)
>  #ifdef CONFIG_IMA_LOAD_X509
>  void __init ima_load_x509(void)
>  {
> -	int unset_flags = ima_policy_flag & IMA_APPRAISE;
> +	int unset_flags = init_ima_ns.ima_policy_flag & IMA_APPRAISE;
>  
> -	ima_policy_flag &= ~unset_flags;
> +	init_ima_ns.ima_policy_flag &= ~unset_flags;
>  	integrity_load_x509(INTEGRITY_KEYRING_IMA, CONFIG_IMA_X509_PATH);
>  
>  	/* load also EVM key to avoid appraisal */
>  	evm_load_x509();
>  
> -	ima_policy_flag |= unset_flags;
> +	init_ima_ns.ima_policy_flag |= unset_flags;
>  }
>  #endif
>  
> @@ -117,6 +117,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");
> @@ -142,7 +146,7 @@ int __init ima_init(void)
>  	if (rc != 0)
>  		return rc;
>  
> -	ima_init_policy();
> +	ima_init_policy(&init_ima_ns);
>  
>  	rc = ima_fs_init();
>  	if (rc != 0)
> 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..c919a456b525
> --- /dev/null
> +++ b/security/integrity/ima/ima_init_ima_ns.c
> @@ -0,0 +1,29 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2016-2022 IBM Corporation
> + * Author:
> + *   Yuqiong Sun <suny@us.ibm.com>
> + *   Stefan Berger <stefanb@linux.vnet.ibm.com>
> + */
> +
> +#include "ima.h"
> +
> +static int ima_init_namespace(struct ima_namespace *ns)
> +{
> +	INIT_LIST_HEAD(&ns->ima_default_rules);
> +	INIT_LIST_HEAD(&ns->ima_policy_rules);
> +	INIT_LIST_HEAD(&ns->ima_temp_rules);
> +	ns->ima_rules = (struct list_head __rcu *)(&ns->ima_default_rules);
> +	ns->ima_policy_flag = 0;
> +
> +	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_main.c b/security/integrity/ima/ima_main.c
> index 3d3f8c5c502b..400865c521dd 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -185,10 +185,11 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint,
>   */
>  void ima_file_free(struct file *file)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	struct inode *inode = file_inode(file);
>  	struct integrity_iint_cache *iint;
>  
> -	if (!ima_policy_flag || !S_ISREG(inode->i_mode))
> +	if (!ns->ima_policy_flag || !S_ISREG(inode->i_mode))
>  		return;
>  
>  	iint = integrity_iint_find(inode);
> @@ -198,7 +199,8 @@ void ima_file_free(struct file *file)
>  	ima_check_last_writer(iint, inode, file);
>  }
>  
> -static int process_measurement(struct file *file, const struct cred *cred,
> +static int process_measurement(struct ima_namespace *ns,
> +			       struct file *file, const struct cred *cred,
>  			       u32 secid, char *buf, loff_t size, int mask,
>  			       enum ima_hooks func)
>  {
> @@ -217,18 +219,18 @@ static int process_measurement(struct file *file, const struct cred *cred,
>  	enum hash_algo hash_algo;
>  	unsigned int allowed_algos = 0;
>  
> -	if (!ima_policy_flag || !S_ISREG(inode->i_mode))
> +	if (!ns->ima_policy_flag || !S_ISREG(inode->i_mode))
>  		return 0;
>  
>  	/* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action
>  	 * bitmask based on the appraise/audit/measurement policy.
>  	 * Included is the appraise submask.
>  	 */
> -	action = ima_get_action(file_mnt_user_ns(file), inode, cred, secid,
> +	action = ima_get_action(ns, file_mnt_user_ns(file), inode, cred, secid,
>  				mask, func, &pcr, &template_desc, NULL,
>  				&allowed_algos);
>  	violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
> -			   (ima_policy_flag & IMA_MEASURE));
> +			   (ns->ima_policy_flag & IMA_MEASURE));
>  	if (!action && !violation_check)
>  		return 0;
>  
> @@ -346,7 +348,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
>  				      xattr_value, xattr_len, modsig, pcr,
>  				      template_desc);
>  	if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) {
> -		rc = ima_check_blacklist(iint, modsig, pcr);
> +		rc = ima_check_blacklist(ns, iint, modsig, pcr);
>  		if (rc != -EPERM) {
>  			inode_lock(inode);
>  			rc = ima_appraise_measurement(func, iint, file,
> @@ -405,12 +407,13 @@ static int process_measurement(struct file *file, const struct cred *cred,
>   */
>  int ima_file_mmap(struct file *file, unsigned long prot)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	u32 secid;
>  
>  	if (file && (prot & PROT_EXEC)) {
>  		security_current_getsecid_subj(&secid);
> -		return process_measurement(file, current_cred(), secid, NULL,
> -					   0, MAY_EXEC, MMAP_CHECK);
> +		return process_measurement(ns, file, current_cred(), secid,
> +					   NULL, 0, MAY_EXEC, MMAP_CHECK);
>  	}
>  
>  	return 0;
> @@ -431,6 +434,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
>   */
>  int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	struct ima_template_desc *template = NULL;
>  	struct file *file = vma->vm_file;
>  	char filename[NAME_MAX];
> @@ -443,13 +447,13 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
>  	int pcr;
>  
>  	/* Is mprotect making an mmap'ed file executable? */
> -	if (!(ima_policy_flag & IMA_APPRAISE) || !vma->vm_file ||
> +	if (!(ns->ima_policy_flag & IMA_APPRAISE) || !vma->vm_file ||
>  	    !(prot & PROT_EXEC) || (vma->vm_flags & VM_EXEC))
>  		return 0;
>  
>  	security_current_getsecid_subj(&secid);
>  	inode = file_inode(vma->vm_file);
> -	action = ima_get_action(file_mnt_user_ns(vma->vm_file), inode,
> +	action = ima_get_action(ns, file_mnt_user_ns(vma->vm_file), inode,
>  				current_cred(), secid, MAY_EXEC, MMAP_CHECK,
>  				&pcr, &template, NULL, NULL);
>  
> @@ -485,17 +489,18 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
>   */
>  int ima_bprm_check(struct linux_binprm *bprm)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	int ret;
>  	u32 secid;
>  
>  	security_current_getsecid_subj(&secid);
> -	ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0,
> -				  MAY_EXEC, BPRM_CHECK);
> +	ret = process_measurement(ns, bprm->file, current_cred(), secid, NULL,
> +				  0, MAY_EXEC, BPRM_CHECK);
>  	if (ret)
>  		return ret;
>  
>  	security_cred_getsecid(bprm->cred, &secid);
> -	return process_measurement(bprm->file, bprm->cred, secid, NULL, 0,
> +	return process_measurement(ns, bprm->file, bprm->cred, secid, NULL, 0,
>  				   MAY_EXEC, CREDS_CHECK);
>  }
>  
> @@ -511,22 +516,23 @@ int ima_bprm_check(struct linux_binprm *bprm)
>   */
>  int ima_file_check(struct file *file, int mask)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	u32 secid;
>  
>  	security_current_getsecid_subj(&secid);
> -	return process_measurement(file, current_cred(), secid, NULL, 0,
> +	return process_measurement(ns, file, current_cred(), secid, NULL, 0,
>  				   mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
>  					   MAY_APPEND), FILE_CHECK);
>  }
>  EXPORT_SYMBOL_GPL(ima_file_check);
>  
> -static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf,
> -			    size_t buf_size)
> +static int __ima_inode_hash(struct ima_namespace *ns, struct inode *inode,
> +			    struct file *file, char *buf, size_t buf_size)
>  {
>  	struct integrity_iint_cache *iint = NULL, tmp_iint;
>  	int rc, hash_algo;
>  
> -	if (ima_policy_flag) {
> +	if (ns->ima_policy_flag) {
>  		iint = integrity_iint_find(inode);
>  		if (iint)
>  			mutex_lock(&iint->mutex);
> @@ -595,10 +601,12 @@ static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf,
>   */
>  int ima_file_hash(struct file *file, char *buf, size_t buf_size)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
> +
>  	if (!file)
>  		return -EINVAL;
>  
> -	return __ima_inode_hash(file_inode(file), file, buf, buf_size);
> +	return __ima_inode_hash(ns, file_inode(file), file, buf, buf_size);
>  }
>  EXPORT_SYMBOL_GPL(ima_file_hash);
>  
> @@ -622,10 +630,12 @@ EXPORT_SYMBOL_GPL(ima_file_hash);
>   */
>  int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
> +
>  	if (!inode)
>  		return -EINVAL;
>  
> -	return __ima_inode_hash(inode, NULL, buf, buf_size);
> +	return __ima_inode_hash(ns, inode, NULL, buf, buf_size);
>  }
>  EXPORT_SYMBOL_GPL(ima_inode_hash);
>  
> @@ -641,13 +651,14 @@ EXPORT_SYMBOL_GPL(ima_inode_hash);
>  void ima_post_create_tmpfile(struct user_namespace *mnt_userns,
>  			     struct inode *inode)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	struct integrity_iint_cache *iint;
>  	int must_appraise;
>  
> -	if (!ima_policy_flag || !S_ISREG(inode->i_mode))
> +	if (!ns->ima_policy_flag || !S_ISREG(inode->i_mode))
>  		return;
>  
> -	must_appraise = ima_must_appraise(mnt_userns, inode, MAY_ACCESS,
> +	must_appraise = ima_must_appraise(ns, mnt_userns, inode, MAY_ACCESS,
>  					  FILE_CHECK);
>  	if (!must_appraise)
>  		return;
> @@ -673,14 +684,15 @@ void ima_post_create_tmpfile(struct user_namespace *mnt_userns,
>  void ima_post_path_mknod(struct user_namespace *mnt_userns,
>  			 struct dentry *dentry)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	struct integrity_iint_cache *iint;
>  	struct inode *inode = dentry->d_inode;
>  	int must_appraise;
>  
> -	if (!ima_policy_flag || !S_ISREG(inode->i_mode))
> +	if (!ns->ima_policy_flag || !S_ISREG(inode->i_mode))
>  		return;
>  
> -	must_appraise = ima_must_appraise(mnt_userns, inode, MAY_ACCESS,
> +	must_appraise = ima_must_appraise(ns, mnt_userns, inode, MAY_ACCESS,
>  					  FILE_CHECK);
>  	if (!must_appraise)
>  		return;
> @@ -709,6 +721,7 @@ void ima_post_path_mknod(struct user_namespace *mnt_userns,
>  int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
>  		  bool contents)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	enum ima_hooks func;
>  	u32 secid;
>  
> @@ -731,7 +744,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
>  	/* Read entire file for all partial reads. */
>  	func = read_idmap[read_id] ?: FILE_CHECK;
>  	security_current_getsecid_subj(&secid);
> -	return process_measurement(file, current_cred(), secid, NULL,
> +	return process_measurement(ns, file, current_cred(), secid, NULL,
>  				   0, MAY_READ, func);
>  }
>  
> @@ -759,6 +772,7 @@ const int read_idmap[READING_MAX_ID] = {
>  int ima_post_read_file(struct file *file, void *buf, loff_t size,
>  		       enum kernel_read_file_id read_id)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	enum ima_hooks func;
>  	u32 secid;
>  
> @@ -767,14 +781,15 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
>  		return 0;
>  
>  	if (!file || !buf || size == 0) { /* should never happen */
> -		if (ima_appraise & IMA_APPRAISE_ENFORCE)
> +		if (ns == &init_ima_ns &&
> +		    (ima_appraise & IMA_APPRAISE_ENFORCE))
>  			return -EACCES;
>  		return 0;
>  	}
>  
>  	func = read_idmap[read_id] ?: FILE_CHECK;
>  	security_current_getsecid_subj(&secid);
> -	return process_measurement(file, current_cred(), secid, buf, size,
> +	return process_measurement(ns, file, current_cred(), secid, buf, size,
>  				   MAY_READ, func);
>  }
>  
> @@ -862,6 +877,7 @@ int ima_post_load_data(char *buf, loff_t size,
>  
>  /**
>   * process_buffer_measurement - Measure the buffer or the buffer data hash
> + * @ns: IMA namespace that has the policy
>   * @mnt_userns:	user namespace of the mount the inode was found from
>   * @inode: inode associated with the object being measured (NULL for KEY_CHECK)
>   * @buf: pointer to the buffer that needs to be added to the log.
> @@ -880,7 +896,8 @@ int ima_post_load_data(char *buf, loff_t size,
>   * has been written to the passed location but not added to a measurement entry,
>   * a negative value otherwise.
>   */
> -int process_buffer_measurement(struct user_namespace *mnt_userns,
> +int process_buffer_measurement(struct ima_namespace *ns,
> +			       struct user_namespace *mnt_userns,
>  			       struct inode *inode, const void *buf, int size,
>  			       const char *eventname, enum ima_hooks func,
>  			       int pcr, const char *func_data,
> @@ -905,7 +922,7 @@ int process_buffer_measurement(struct user_namespace *mnt_userns,
>  	if (digest && digest_len < digest_hash_len)
>  		return -EINVAL;
>  
> -	if (!ima_policy_flag && !digest)
> +	if (!ns->ima_policy_flag && !digest)
>  		return -ENOENT;
>  
>  	template = ima_template_desc_buf();
> @@ -924,7 +941,7 @@ int process_buffer_measurement(struct user_namespace *mnt_userns,
>  	 */
>  	if (func) {
>  		security_current_getsecid_subj(&secid);
> -		action = ima_get_action(mnt_userns, inode, current_cred(),
> +		action = ima_get_action(ns, mnt_userns, inode, current_cred(),
>  					secid, 0, func, &pcr, &template,
>  					func_data, NULL);
>  		if (!(action & IMA_MEASURE) && !digest)
> @@ -961,7 +978,7 @@ int process_buffer_measurement(struct user_namespace *mnt_userns,
>  	if (digest)
>  		memcpy(digest, iint.ima_hash->digest, digest_hash_len);
>  
> -	if (!ima_policy_flag || (func && !(action & IMA_MEASURE)))
> +	if (!ns->ima_policy_flag || (func && !(action & IMA_MEASURE)))
>  		return 1;
>  
>  	ret = ima_alloc_init_template(&event_data, &entry, template);
> @@ -995,6 +1012,7 @@ int process_buffer_measurement(struct user_namespace *mnt_userns,
>   */
>  void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	struct fd f;
>  
>  	if (!buf || !size)
> @@ -1004,7 +1022,8 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
>  	if (!f.file)
>  		return;
>  
> -	process_buffer_measurement(file_mnt_user_ns(f.file), file_inode(f.file),
> +	process_buffer_measurement(ns,
> +				   file_mnt_user_ns(f.file), file_inode(f.file),
>  				   buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0,
>  				   NULL, false, NULL, 0);
>  	fdput(f);
> @@ -1034,10 +1053,12 @@ int ima_measure_critical_data(const char *event_label,
>  			      const void *buf, size_t buf_len,
>  			      bool hash, u8 *digest, size_t digest_len)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
> +
>  	if (!event_name || !event_label || !buf || !buf_len)
>  		return -ENOPARAM;
>  
> -	return process_buffer_measurement(&init_user_ns, NULL, buf, buf_len,
> +	return process_buffer_measurement(ns, &init_user_ns, NULL, buf, buf_len,
>  					  event_name, CRITICAL_DATA, 0,
>  					  event_label, hash, digest,
>  					  digest_len);
> @@ -1046,6 +1067,7 @@ EXPORT_SYMBOL_GPL(ima_measure_critical_data);
>  
>  static int __init init_ima(void)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	int error;
>  
>  	ima_appraise_parse_cmdline();
> @@ -1070,7 +1092,7 @@ static int __init init_ima(void)
>  		pr_warn("Couldn't register LSM notifier, error %d\n", error);
>  
>  	if (!error)
> -		ima_update_policy_flags();
> +		ima_update_policy_flags(ns);
>  
>  	return error;
>  }
> diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
> index eea6e92500b8..69b19f4d5fee 100644
> --- a/security/integrity/ima/ima_policy.c
> +++ b/security/integrity/ima/ima_policy.c
> @@ -51,7 +51,6 @@
>  #define INVALID_PCR(a) (((a) < 0) || \
>  	(a) >= (sizeof_field(struct integrity_iint_cache, measured_pcrs) * 8))
>  
> -int ima_policy_flag;
>  static int temp_ima_appraise;
>  static int build_ima_appraise __ro_after_init;
>  
> @@ -232,11 +231,6 @@ static struct ima_rule_entry critical_data_rules[] __ro_after_init = {
>  /* An array of architecture specific rules */
>  static struct ima_rule_entry *arch_policy_entry __ro_after_init;
>  
> -static LIST_HEAD(ima_default_rules);
> -static LIST_HEAD(ima_policy_rules);
> -static LIST_HEAD(ima_temp_rules);
> -static struct list_head __rcu *ima_rules = (struct list_head __rcu *)(&ima_default_rules);
> -
>  static int ima_policy __initdata;
>  
>  static int __init default_measure_policy_setup(char *str)
> @@ -453,12 +447,12 @@ static bool ima_rule_contains_lsm_cond(struct ima_rule_entry *entry)
>   * to the old, stale LSM policy.  Update the IMA LSM based rules to reflect
>   * the reloaded LSM policy.
>   */
> -static void ima_lsm_update_rules(void)
> +static void ima_lsm_update_rules(struct ima_namespace *ns)
>  {
>  	struct ima_rule_entry *entry, *e;
>  	int result;
>  
> -	list_for_each_entry_safe(entry, e, &ima_policy_rules, list) {
> +	list_for_each_entry_safe(entry, e, &ns->ima_policy_rules, list) {
>  		if (!ima_rule_contains_lsm_cond(entry))
>  			continue;
>  
> @@ -473,10 +467,12 @@ static void ima_lsm_update_rules(void)
>  int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
>  			  void *lsm_data)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
> +
>  	if (event != LSM_POLICY_CHANGE)
>  		return NOTIFY_DONE;
>  
> -	ima_lsm_update_rules();
> +	ima_lsm_update_rules(ns);
>  	return NOTIFY_OK;
>  }
>  
> @@ -668,6 +664,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
>  
>  /**
>   * ima_match_policy - decision based on LSM and other conditions
> + * @ns: IMA namespace that has the policy
>   * @mnt_userns:	user namespace of the mount the inode was found from
>   * @inode: pointer to an inode for which the policy decision is being made
>   * @cred: pointer to a credentials structure for which the policy decision is
> @@ -687,7 +684,8 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
>   * list when walking it.  Reads are many orders of magnitude more numerous
>   * than writes so ima_match_policy() is classical RCU candidate.
>   */
> -int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
> +int ima_match_policy(struct ima_namespace *ns,
> +		     struct user_namespace *mnt_userns, struct inode *inode,
>  		     const struct cred *cred, u32 secid, enum ima_hooks func,
>  		     int mask, int flags, int *pcr,
>  		     struct ima_template_desc **template_desc,
> @@ -701,7 +699,7 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
>  		*template_desc = ima_template_desc_current();
>  
>  	rcu_read_lock();
> -	ima_rules_tmp = rcu_dereference(ima_rules);
> +	ima_rules_tmp = rcu_dereference(ns->ima_rules);
>  	list_for_each_entry_rcu(entry, ima_rules_tmp, list) {
>  
>  		if (!(entry->action & actmask))
> @@ -745,8 +743,8 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
>  }
>  
>  /**
> - * ima_update_policy_flags() - Update global IMA variables
> - *
> + * ima_update_policy_flags() - Update namespaced IMA variables
> + * @ns: IMA namespace that has the policy
>   * Update ima_policy_flag and ima_setxattr_allowed_hash_algorithms
>   * based on the currently loaded policy.
>   *
> @@ -759,14 +757,14 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
>   *
>   * Context: called after a policy update and at system initialization.
>   */
> -void ima_update_policy_flags(void)
> +void ima_update_policy_flags(struct ima_namespace *ns)
>  {
>  	struct ima_rule_entry *entry;
>  	int new_policy_flag = 0;
>  	struct list_head *ima_rules_tmp;
>  
>  	rcu_read_lock();
> -	ima_rules_tmp = rcu_dereference(ima_rules);
> +	ima_rules_tmp = rcu_dereference(ns->ima_rules);
>  	list_for_each_entry_rcu(entry, ima_rules_tmp, list) {
>  		/*
>  		 * SETXATTR_CHECK rules do not implement a full policy check
> @@ -796,7 +794,7 @@ void ima_update_policy_flags(void)
>  	if (!ima_appraise)
>  		new_policy_flag &= ~IMA_APPRAISE;
>  
> -	ima_policy_flag = new_policy_flag;
> +	ns->ima_policy_flag = new_policy_flag;
>  }
>  
>  static int ima_appraise_flag(enum ima_hooks func)
> @@ -812,7 +810,8 @@ static int ima_appraise_flag(enum ima_hooks func)
>  	return 0;
>  }
>  
> -static void add_rules(struct ima_rule_entry *entries, int count,
> +static void add_rules(struct ima_namespace *ns,
> +		      struct ima_rule_entry *entries, int count,
>  		      enum policy_rule_list policy_rule)
>  {
>  	int i = 0;
> @@ -821,7 +820,7 @@ static void add_rules(struct ima_rule_entry *entries, int count,
>  		struct ima_rule_entry *entry;
>  
>  		if (policy_rule & IMA_DEFAULT_POLICY)
> -			list_add_tail(&entries[i].list, &ima_default_rules);
> +			list_add_tail(&entries[i].list, &ns->ima_default_rules);
>  
>  		if (policy_rule & IMA_CUSTOM_POLICY) {
>  			entry = kmemdup(&entries[i], sizeof(*entry),
> @@ -829,7 +828,7 @@ static void add_rules(struct ima_rule_entry *entries, int count,
>  			if (!entry)
>  				continue;
>  
> -			list_add_tail(&entry->list, &ima_policy_rules);
> +			list_add_tail(&entry->list, &ns->ima_policy_rules);
>  		}
>  		if (entries[i].action == APPRAISE) {
>  			if (entries != build_appraise_rules)
> @@ -842,9 +841,10 @@ static void add_rules(struct ima_rule_entry *entries, int count,
>  	}
>  }
>  
> -static int ima_parse_rule(char *rule, struct ima_rule_entry *entry);
> +static int ima_parse_rule(struct ima_namespace *ns,
> +			  char *rule, struct ima_rule_entry *entry);
>  
> -static int __init ima_init_arch_policy(void)
> +static int __init ima_init_arch_policy(struct ima_namespace *ns)
>  {
>  	const char * const *arch_rules;
>  	const char * const *rules;
> @@ -872,7 +872,7 @@ static int __init ima_init_arch_policy(void)
>  		result = strscpy(rule, *rules, sizeof(rule));
>  
>  		INIT_LIST_HEAD(&arch_policy_entry[i].list);
> -		result = ima_parse_rule(rule, &arch_policy_entry[i]);
> +		result = ima_parse_rule(ns, rule, &arch_policy_entry[i]);
>  		if (result) {
>  			pr_warn("Skipping unknown architecture policy rule: %s\n",
>  				rule);
> @@ -887,26 +887,27 @@ static int __init ima_init_arch_policy(void)
>  
>  /**
>   * ima_init_policy - initialize the default measure rules.
> - *
> + * @ns: IMA namespace to which the policy belongs to
>   * ima_rules points to either the ima_default_rules or the new ima_policy_rules.
>   */
> -void __init ima_init_policy(void)
> +void __init ima_init_policy(struct ima_namespace *ns)
>  {
>  	int build_appraise_entries, arch_entries;
>  
>  	/* if !ima_policy, we load NO default rules */
>  	if (ima_policy)
> -		add_rules(dont_measure_rules, ARRAY_SIZE(dont_measure_rules),
> +		add_rules(ns, dont_measure_rules,
> +			  ARRAY_SIZE(dont_measure_rules),
>  			  IMA_DEFAULT_POLICY);
>  
>  	switch (ima_policy) {
>  	case ORIGINAL_TCB:
> -		add_rules(original_measurement_rules,
> +		add_rules(ns, original_measurement_rules,
>  			  ARRAY_SIZE(original_measurement_rules),
>  			  IMA_DEFAULT_POLICY);
>  		break;
>  	case DEFAULT_TCB:
> -		add_rules(default_measurement_rules,
> +		add_rules(ns, default_measurement_rules,
>  			  ARRAY_SIZE(default_measurement_rules),
>  			  IMA_DEFAULT_POLICY);
>  		break;
> @@ -920,11 +921,11 @@ void __init ima_init_policy(void)
>  	 * and custom policies, prior to other appraise rules.
>  	 * (Highest priority)
>  	 */
> -	arch_entries = ima_init_arch_policy();
> +	arch_entries = ima_init_arch_policy(ns);
>  	if (!arch_entries)
>  		pr_info("No architecture policies found\n");
>  	else
> -		add_rules(arch_policy_entry, arch_entries,
> +		add_rules(ns, arch_policy_entry, arch_entries,
>  			  IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY);
>  
>  	/*
> @@ -932,7 +933,7 @@ void __init ima_init_policy(void)
>  	 * signatures, prior to other appraise rules.
>  	 */
>  	if (ima_use_secure_boot)
> -		add_rules(secure_boot_rules, ARRAY_SIZE(secure_boot_rules),
> +		add_rules(ns, secure_boot_rules, ARRAY_SIZE(secure_boot_rules),
>  			  IMA_DEFAULT_POLICY);
>  
>  	/*
> @@ -944,39 +945,41 @@ void __init ima_init_policy(void)
>  	build_appraise_entries = ARRAY_SIZE(build_appraise_rules);
>  	if (build_appraise_entries) {
>  		if (ima_use_secure_boot)
> -			add_rules(build_appraise_rules, build_appraise_entries,
> +			add_rules(ns, build_appraise_rules,
> +				  build_appraise_entries,
>  				  IMA_CUSTOM_POLICY);
>  		else
> -			add_rules(build_appraise_rules, build_appraise_entries,
> +			add_rules(ns, build_appraise_rules,
> +				  build_appraise_entries,
>  				  IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY);
>  	}
>  
>  	if (ima_use_appraise_tcb)
> -		add_rules(default_appraise_rules,
> +		add_rules(ns, default_appraise_rules,
>  			  ARRAY_SIZE(default_appraise_rules),
>  			  IMA_DEFAULT_POLICY);
>  
>  	if (ima_use_critical_data)
> -		add_rules(critical_data_rules,
> +		add_rules(ns, critical_data_rules,
>  			  ARRAY_SIZE(critical_data_rules),
>  			  IMA_DEFAULT_POLICY);
>  
>  	atomic_set(&ima_setxattr_allowed_hash_algorithms, 0);
>  
> -	ima_update_policy_flags();
> +	ima_update_policy_flags(ns);
>  }
>  
>  /* Make sure we have a valid policy, at least containing some rules. */
> -int ima_check_policy(void)
> +int ima_check_policy(struct ima_namespace *ns)
>  {
> -	if (list_empty(&ima_temp_rules))
> +	if (list_empty(&ns->ima_temp_rules))
>  		return -EINVAL;
>  	return 0;
>  }
>  
>  /**
>   * ima_update_policy - update default_rules with new measure rules
> - *
> + * @ns: IMA namespace that has the policy
>   * Called on file .release to update the default rules with a complete new
>   * policy.  What we do here is to splice ima_policy_rules and ima_temp_rules so
>   * they make a queue.  The policy may be updated multiple times and this is the
> @@ -985,16 +988,17 @@ int ima_check_policy(void)
>   * Policy rules are never deleted so ima_policy_flag gets zeroed only once when
>   * we switch from the default policy to user defined.
>   */
> -void ima_update_policy(void)
> +void ima_update_policy(struct ima_namespace *ns)
>  {
> -	struct list_head *policy = &ima_policy_rules;
> +	struct list_head *policy = &ns->ima_policy_rules;
>  
> -	list_splice_tail_init_rcu(&ima_temp_rules, policy, synchronize_rcu);
> +	list_splice_tail_init_rcu(&ns->ima_temp_rules, policy,
> +				  synchronize_rcu);
>  
> -	if (ima_rules != (struct list_head __rcu *)policy) {
> -		ima_policy_flag = 0;
> +	if (ns->ima_rules != (struct list_head __rcu *)policy) {
> +		ns->ima_policy_flag = 0;
>  
> -		rcu_assign_pointer(ima_rules, policy);
> +		rcu_assign_pointer(ns->ima_rules, policy);
>  		/*
>  		 * IMA architecture specific policy rules are specified
>  		 * as strings and converted to an array of ima_entry_rules
> @@ -1003,10 +1007,10 @@ void ima_update_policy(void)
>  		 */
>  		kfree(arch_policy_entry);
>  	}
> -	ima_update_policy_flags();
> +	ima_update_policy_flags(ns);
>  
>  	/* Custom IMA policy has been loaded */
> -	ima_process_queued_keys();
> +	ima_process_queued_keys(ns);
>  }
>  
>  /* Keep the enumeration in sync with the policy_tokens! */
> @@ -1076,7 +1080,8 @@ static const match_table_t policy_tokens = {
>  	{Opt_err, NULL}
>  };
>  
> -static int ima_lsm_rule_init(struct ima_rule_entry *entry,
> +static int ima_lsm_rule_init(struct ima_namespace *ns,
> +			     struct ima_rule_entry *entry,
>  			     substring_t *args, int lsm_rule, int audit_type)
>  {
>  	int result;
> @@ -1096,7 +1101,8 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry,
>  		pr_warn("rule for LSM \'%s\' is undefined\n",
>  			entry->lsm[lsm_rule].args_p);
>  
> -		if (ima_rules == (struct list_head __rcu *)(&ima_default_rules)) {
> +		if (ns->ima_rules ==
> +			(struct list_head __rcu *)&ns->ima_default_rules) {
>  			kfree(entry->lsm[lsm_rule].args_p);
>  			entry->lsm[lsm_rule].args_p = NULL;
>  			result = -EINVAL;
> @@ -1323,7 +1329,8 @@ static unsigned int ima_parse_appraise_algos(char *arg)
>  	return res;
>  }
>  
> -static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
> +static int ima_parse_rule(struct ima_namespace *ns,
> +			  char *rule, struct ima_rule_entry *entry)
>  {
>  	struct audit_buffer *ab;
>  	char *from;
> @@ -1673,37 +1680,37 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
>  			break;
>  		case Opt_obj_user:
>  			ima_log_string(ab, "obj_user", args[0].from);
> -			result = ima_lsm_rule_init(entry, args,
> +			result = ima_lsm_rule_init(ns, entry, args,
>  						   LSM_OBJ_USER,
>  						   AUDIT_OBJ_USER);
>  			break;
>  		case Opt_obj_role:
>  			ima_log_string(ab, "obj_role", args[0].from);
> -			result = ima_lsm_rule_init(entry, args,
> +			result = ima_lsm_rule_init(ns, entry, args,
>  						   LSM_OBJ_ROLE,
>  						   AUDIT_OBJ_ROLE);
>  			break;
>  		case Opt_obj_type:
>  			ima_log_string(ab, "obj_type", args[0].from);
> -			result = ima_lsm_rule_init(entry, args,
> +			result = ima_lsm_rule_init(ns, entry, args,
>  						   LSM_OBJ_TYPE,
>  						   AUDIT_OBJ_TYPE);
>  			break;
>  		case Opt_subj_user:
>  			ima_log_string(ab, "subj_user", args[0].from);
> -			result = ima_lsm_rule_init(entry, args,
> +			result = ima_lsm_rule_init(ns, entry, args,
>  						   LSM_SUBJ_USER,
>  						   AUDIT_SUBJ_USER);
>  			break;
>  		case Opt_subj_role:
>  			ima_log_string(ab, "subj_role", args[0].from);
> -			result = ima_lsm_rule_init(entry, args,
> +			result = ima_lsm_rule_init(ns, entry, args,
>  						   LSM_SUBJ_ROLE,
>  						   AUDIT_SUBJ_ROLE);
>  			break;
>  		case Opt_subj_type:
>  			ima_log_string(ab, "subj_type", args[0].from);
> -			result = ima_lsm_rule_init(entry, args,
> +			result = ima_lsm_rule_init(ns, entry, args,
>  						   LSM_SUBJ_TYPE,
>  						   AUDIT_SUBJ_TYPE);
>  			break;
> @@ -1804,12 +1811,13 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
>  
>  /**
>   * ima_parse_add_rule - add a rule to ima_policy_rules
> + * @ns: IMA namespace that has the policy
>   * @rule - ima measurement policy rule
>   *
>   * Avoid locking by allowing just one writer at a time in ima_write_policy()
>   * Returns the length of the rule parsed, an error code on failure
>   */
> -ssize_t ima_parse_add_rule(char *rule)
> +ssize_t ima_parse_add_rule(struct ima_namespace *ns, char *rule)
>  {
>  	static const char op[] = "update_policy";
>  	char *p;
> @@ -1833,7 +1841,7 @@ ssize_t ima_parse_add_rule(char *rule)
>  
>  	INIT_LIST_HEAD(&entry->list);
>  
> -	result = ima_parse_rule(p, entry);
> +	result = ima_parse_rule(ns, p, entry);
>  	if (result) {
>  		ima_free_rule(entry);
>  		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
> @@ -1842,23 +1850,24 @@ ssize_t ima_parse_add_rule(char *rule)
>  		return result;
>  	}
>  
> -	list_add_tail(&entry->list, &ima_temp_rules);
> +	list_add_tail(&entry->list, &ns->ima_temp_rules);
>  
>  	return len;
>  }
>  
>  /**
> - * ima_delete_rules() called to cleanup invalid in-flight policy.
> + * ima_delete_rules - called to cleanup invalid in-flight policy.
> + * @ns: IMA namespace that has the policy
>   * We don't need locking as we operate on the temp list, which is
>   * different from the active one.  There is also only one user of
>   * ima_delete_rules() at a time.
>   */
> -void ima_delete_rules(void)
> +void ima_delete_rules(struct ima_namespace *ns)
>  {
>  	struct ima_rule_entry *entry, *tmp;
>  
>  	temp_ima_appraise = 0;
> -	list_for_each_entry_safe(entry, tmp, &ima_temp_rules, list) {
> +	list_for_each_entry_safe(entry, tmp, &ns->ima_temp_rules, list) {
>  		list_del(&entry->list);
>  		ima_free_rule(entry);
>  	}
> @@ -1884,12 +1893,13 @@ static const char *const mask_tokens[] = {
>  
>  void *ima_policy_start(struct seq_file *m, loff_t *pos)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	loff_t l = *pos;
>  	struct ima_rule_entry *entry;
>  	struct list_head *ima_rules_tmp;
>  
>  	rcu_read_lock();
> -	ima_rules_tmp = rcu_dereference(ima_rules);
> +	ima_rules_tmp = rcu_dereference(ns->ima_rules);
>  	list_for_each_entry_rcu(entry, ima_rules_tmp, list) {
>  		if (!l--) {
>  			rcu_read_unlock();
> @@ -1902,6 +1912,7 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos)
>  
>  void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	struct ima_rule_entry *entry = v;
>  
>  	rcu_read_lock();
> @@ -1909,8 +1920,8 @@ void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos)
>  	rcu_read_unlock();
>  	(*pos)++;
>  
> -	return (&entry->list == &ima_default_rules ||
> -		&entry->list == &ima_policy_rules) ? NULL : entry;
> +	return (&entry->list == &ns->ima_default_rules ||
> +		&entry->list == &ns->ima_policy_rules) ? NULL : entry;
>  }
>  
>  void ima_policy_stop(struct seq_file *m, void *v)
> @@ -2173,6 +2184,7 @@ int ima_policy_show(struct seq_file *m, void *v)
>   */
>  bool ima_appraise_signature(enum kernel_read_file_id id)
>  {
> +	struct ima_namespace *ns = &init_ima_ns;
>  	struct ima_rule_entry *entry;
>  	bool found = false;
>  	enum ima_hooks func;
> @@ -2184,7 +2196,7 @@ bool ima_appraise_signature(enum kernel_read_file_id id)
>  	func = read_idmap[id] ?: FILE_CHECK;
>  
>  	rcu_read_lock();
> -	ima_rules_tmp = rcu_dereference(ima_rules);
> +	ima_rules_tmp = rcu_dereference(ns->ima_rules);
>  	list_for_each_entry_rcu(entry, ima_rules_tmp, list) {
>  		if (entry->action != APPRAISE)
>  			continue;
> diff --git a/security/integrity/ima/ima_queue_keys.c b/security/integrity/ima/ima_queue_keys.c
> index 93056c03bf5a..e366a21dd8be 100644
> --- a/security/integrity/ima/ima_queue_keys.c
> +++ b/security/integrity/ima/ima_queue_keys.c
> @@ -10,6 +10,7 @@
>  
>  #include <linux/user_namespace.h>
>  #include <linux/workqueue.h>
> +#include <linux/ima.h>
>  #include <keys/asymmetric-type.h>
>  #include "ima.h"
>  
> @@ -42,7 +43,7 @@ static bool timer_expired;
>  static void ima_keys_handler(struct work_struct *work)
>  {
>  	timer_expired = true;
> -	ima_process_queued_keys();
> +	ima_process_queued_keys(&init_ima_ns);
>  }
>  
>  /*
> @@ -130,11 +131,15 @@ bool ima_queue_key(struct key *keyring, const void *payload,
>   * This function sets ima_process_keys to true and processes queued keys.
>   * From here on keys will be processed right away (not queued).
>   */
> -void ima_process_queued_keys(void)
> +void ima_process_queued_keys(struct ima_namespace *ns)
>  {
>  	struct ima_key_entry *entry, *tmp;
>  	bool process = false;
>  
> +	/* only applies to init_ima_ns */

Hm, yes, it seems to, but it should be unreachable with
ns != &init_ima_ns, ever, right?

So it seems better to either not have this hunk at all, (both
here and at ima_keys_handler()) or to actually have a BUG_ON.

Or am I completely misreading the situation?

> +	if (ns != &init_ima_ns)
> +		return;
> +
>  	if (ima_process_keys)
>  		return;
>  
> @@ -159,7 +164,7 @@ void ima_process_queued_keys(void)
>  
>  	list_for_each_entry_safe(entry, tmp, &ima_keys, list) {
>  		if (!timer_expired)
> -			process_buffer_measurement(&init_user_ns, NULL,
> +			process_buffer_measurement(ns, &init_user_ns, NULL,
>  						   entry->payload,
>  						   entry->payload_len,
>  						   entry->keyring_name,
> -- 
> 2.34.1
Stefan Berger May 24, 2022, 2:57 p.m. UTC | #2
On 5/20/22 22:33, Serge E. Hallyn wrote:

>> diff --git a/security/integrity/ima/ima_queue_keys.c b/security/integrity/ima/ima_queue_keys.c
>> index 93056c03bf5a..e366a21dd8be 100644
>> --- a/security/integrity/ima/ima_queue_keys.c
>> +++ b/security/integrity/ima/ima_queue_keys.c
>> @@ -10,6 +10,7 @@
>>   
>>   #include <linux/user_namespace.h>
>>   #include <linux/workqueue.h>
>> +#include <linux/ima.h>
>>   #include <keys/asymmetric-type.h>
>>   #include "ima.h"
>>   
>> @@ -42,7 +43,7 @@ static bool timer_expired;
>>   static void ima_keys_handler(struct work_struct *work)
>>   {
>>   	timer_expired = true;
>> -	ima_process_queued_keys();
>> +	ima_process_queued_keys(&init_ima_ns);
>>   }
>>   
>>   /*
>> @@ -130,11 +131,15 @@ bool ima_queue_key(struct key *keyring, const void *payload,
>>    * This function sets ima_process_keys to true and processes queued keys.
>>    * From here on keys will be processed right away (not queued).
>>    */
>> -void ima_process_queued_keys(void)
>> +void ima_process_queued_keys(struct ima_namespace *ns)
>>   {
>>   	struct ima_key_entry *entry, *tmp;
>>   	bool process = false;
>>   
>> +	/* only applies to init_ima_ns */
> 
> Hm, yes, it seems to, but it should be unreachable with
> ns != &init_ima_ns, ever, right?
> 
> So it seems better to either not have this hunk at all, (both
> here and at ima_keys_handler()) or to actually have a BUG_ON.
> 
> Or am I completely misreading the situation?

No, you are right. This function is only calledwith ns = &init_ima_ns at 
the moment. How about changing it to this here?

if (WARN_ON(ns != &init_ima_ns))
         return;



> 
>> +	if (ns != &init_ima_ns)
>> +		return;
>> +
>>   	if (ima_process_keys)
>>   		return;
>>   
>> @@ -159,7 +164,7 @@ void ima_process_queued_keys(void)
>>   
>>   	list_for_each_entry_safe(entry, tmp, &ima_keys, list) {
>>   		if (!timer_expired)
>> -			process_buffer_measurement(&init_user_ns, NULL,
>> +			process_buffer_measurement(ns, &init_user_ns, NULL,
>>   						   entry->payload,
>>   						   entry->payload_len,
>>   						   entry->keyring_name,
>> -- 
>> 2.34.1
Serge Hallyn May 24, 2022, 3:05 p.m. UTC | #3
On Tue, May 24, 2022 at 10:57:13AM -0400, Stefan Berger wrote:
> 
> 
> On 5/20/22 22:33, Serge E. Hallyn wrote:
> 
> > > diff --git a/security/integrity/ima/ima_queue_keys.c b/security/integrity/ima/ima_queue_keys.c
> > > index 93056c03bf5a..e366a21dd8be 100644
> > > --- a/security/integrity/ima/ima_queue_keys.c
> > > +++ b/security/integrity/ima/ima_queue_keys.c
> > > @@ -10,6 +10,7 @@
> > >   #include <linux/user_namespace.h>
> > >   #include <linux/workqueue.h>
> > > +#include <linux/ima.h>
> > >   #include <keys/asymmetric-type.h>
> > >   #include "ima.h"
> > > @@ -42,7 +43,7 @@ static bool timer_expired;
> > >   static void ima_keys_handler(struct work_struct *work)
> > >   {
> > >   	timer_expired = true;
> > > -	ima_process_queued_keys();
> > > +	ima_process_queued_keys(&init_ima_ns);
> > >   }
> > >   /*
> > > @@ -130,11 +131,15 @@ bool ima_queue_key(struct key *keyring, const void *payload,
> > >    * This function sets ima_process_keys to true and processes queued keys.
> > >    * From here on keys will be processed right away (not queued).
> > >    */
> > > -void ima_process_queued_keys(void)
> > > +void ima_process_queued_keys(struct ima_namespace *ns)
> > >   {
> > >   	struct ima_key_entry *entry, *tmp;
> > >   	bool process = false;
> > > +	/* only applies to init_ima_ns */
> > 
> > Hm, yes, it seems to, but it should be unreachable with
> > ns != &init_ima_ns, ever, right?
> > 
> > So it seems better to either not have this hunk at all, (both
> > here and at ima_keys_handler()) or to actually have a BUG_ON.
> > 
> > Or am I completely misreading the situation?
> 
> No, you are right. This function is only calledwith ns = &init_ima_ns at the
> moment. How about changing it to this here?
> 
> if (WARN_ON(ns != &init_ima_ns))
>         return;

Sounds good, thanks.
Stefan Berger May 24, 2022, 4:18 p.m. UTC | #4
On 5/20/22 22:33, Serge E. Hallyn wrote:

>>    * they make a queue.  The policy may be updated multiple times and this is the
>> @@ -985,16 +988,17 @@ int ima_check_policy(void)
>>    * Policy rules are never deleted so ima_policy_flag gets zeroed only once when
>>    * we switch from the default policy to user defined.
>>    */
>> -void ima_update_policy(void)
>> +void ima_update_policy(struct ima_namespace *ns)
>>   {
>> -	struct list_head *policy = &ima_policy_rules;
>> +	struct list_head *policy = &ns->ima_policy_rules;
>>   
>> -	list_splice_tail_init_rcu(&ima_temp_rules, policy, synchronize_rcu);
>> +	list_splice_tail_init_rcu(&ns->ima_temp_rules, policy,
>> +				  synchronize_rcu);
>>   
>> -	if (ima_rules != (struct list_head __rcu *)policy) {
>> -		ima_policy_flag = 0;
>> +	if (ns->ima_rules != (struct list_head __rcu *)policy) {
>> +		ns->ima_policy_flag = 0;
>>   
>> -		rcu_assign_pointer(ima_rules, policy);
>> +		rcu_assign_pointer(ns->ima_rules, policy);
>>   		/*
>>   		 * IMA architecture specific policy rules are specified
>>   		 * as strings and converted to an array of ima_entry_rules
>> @@ -1003,10 +1007,10 @@ void ima_update_policy(void)
>>   		 */
>>   		kfree(arch_policy_entry);
>>   	}
>> -	ima_update_policy_flags();
>> +	ima_update_policy_flags(ns);
>>   
>>   	/* Custom IMA policy has been loaded */
>> -	ima_process_queued_keys();
>> +	ima_process_queued_keys(ns);
>>   }
>>   

So this is a caller that may enter that function with ns != init_ima_ns 
and in that case that function should do nothing. So, also the WARN_ON() 
is not appropriate then.

    Stefan
diff mbox series

Patch

diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
index 2499f2485c04..f8a5e5f3975d 100644
--- a/security/integrity/ima/Makefile
+++ b/security/integrity/ima/Makefile
@@ -7,7 +7,7 @@ 
 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
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index be965a8715e4..9bcde1a24e74 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -20,6 +20,7 @@ 
 #include <linux/hash.h>
 #include <linux/tpm.h>
 #include <linux/audit.h>
+#include <linux/user_namespace.h>
 #include <crypto/hash_info.h>
 
 #include "../integrity.h"
@@ -43,9 +44,6 @@  enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 };
 
 #define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0)
 
-/* current content of the policy */
-extern int ima_policy_flag;
-
 /* bitset of digests algorithms allowed in the setxattr hook */
 extern atomic_t ima_setxattr_allowed_hash_algorithms;
 
@@ -119,6 +117,17 @@  struct ima_kexec_hdr {
 	u64 count;
 };
 
+struct ima_namespace {
+	/* policy rules */
+	struct list_head ima_default_rules; /* Kconfig, builtin & arch rules */
+	struct list_head ima_policy_rules;  /* arch & custom rules */
+	struct list_head ima_temp_rules;
+
+	struct list_head __rcu *ima_rules;  /* Pointer to the current policy */
+	int ima_policy_flag;
+} __randomize_layout;
+extern struct ima_namespace init_ima_ns;
+
 extern const int read_idmap[];
 
 #ifdef CONFIG_HAVE_IMA_KEXEC
@@ -136,6 +145,7 @@  extern bool ima_canonical_fmt;
 /* Internal IMA function definitions */
 int ima_init(void);
 int ima_fs_init(void);
+int ima_ns_init(void);
 int ima_add_template_entry(struct ima_template_entry *entry, int violation,
 			   const char *op, struct inode *inode,
 			   const unsigned char *filename);
@@ -243,18 +253,19 @@  void ima_init_key_queue(void);
 bool ima_should_queue_key(void);
 bool ima_queue_key(struct key *keyring, const void *payload,
 		   size_t payload_len);
-void ima_process_queued_keys(void);
+void ima_process_queued_keys(struct ima_namespace *ns);
 #else
 static inline void ima_init_key_queue(void) {}
 static inline bool ima_should_queue_key(void) { return false; }
 static inline bool ima_queue_key(struct key *keyring,
 				 const void *payload,
 				 size_t payload_len) { return false; }
-static inline void ima_process_queued_keys(void) {}
+static inline void ima_process_queued_keys(struct ima_namespace *ns) {}
 #endif /* CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS */
 
 /* LIM API function definitions */
-int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
+int ima_get_action(struct ima_namespace *ns,
+		   struct user_namespace *mnt_userns, struct inode *inode,
 		   const struct cred *cred, u32 secid, int mask,
 		   enum ima_hooks func, int *pcr,
 		   struct ima_template_desc **template_desc,
@@ -268,7 +279,8 @@  void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
 			   struct evm_ima_xattr_data *xattr_value,
 			   int xattr_len, const struct modsig *modsig, int pcr,
 			   struct ima_template_desc *template_desc);
-int process_buffer_measurement(struct user_namespace *mnt_userns,
+int process_buffer_measurement(struct ima_namespace *ns,
+			       struct user_namespace *mnt_userns,
 			       struct inode *inode, const void *buf, int size,
 			       const char *eventname, enum ima_hooks func,
 			       int pcr, const char *func_data,
@@ -285,17 +297,18 @@  void ima_free_template_entry(struct ima_template_entry *entry);
 const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
 
 /* IMA policy related functions */
-int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
+int ima_match_policy(struct ima_namespace *ns,
+		     struct user_namespace *mnt_userns, struct inode *inode,
 		     const struct cred *cred, u32 secid, enum ima_hooks func,
 		     int mask, int flags, int *pcr,
 		     struct ima_template_desc **template_desc,
 		     const char *func_data, unsigned int *allowed_algos);
-void ima_init_policy(void);
-void ima_update_policy(void);
-void ima_update_policy_flags(void);
-ssize_t ima_parse_add_rule(char *);
-void ima_delete_rules(void);
-int ima_check_policy(void);
+void ima_init_policy(struct ima_namespace *ns);
+void ima_update_policy(struct ima_namespace *ns);
+void ima_update_policy_flags(struct ima_namespace *ns);
+ssize_t ima_parse_add_rule(struct ima_namespace *ns, char *rule);
+void ima_delete_rules(struct ima_namespace *ns);
+int ima_check_policy(struct ima_namespace *ns);
 void *ima_policy_start(struct seq_file *m, loff_t *pos);
 void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos);
 void ima_policy_stop(struct seq_file *m, void *v);
@@ -311,14 +324,16 @@  int ima_policy_show(struct seq_file *m, void *v);
 #define IMA_APPRAISE_KEXEC	0x40
 
 #ifdef CONFIG_IMA_APPRAISE
-int ima_check_blacklist(struct integrity_iint_cache *iint,
+int ima_check_blacklist(struct ima_namespace *ns,
+			struct integrity_iint_cache *iint,
 			const struct modsig *modsig, int pcr);
 int ima_appraise_measurement(enum ima_hooks func,
 			     struct integrity_iint_cache *iint,
 			     struct file *file, const unsigned char *filename,
 			     struct evm_ima_xattr_data *xattr_value,
 			     int xattr_len, const struct modsig *modsig);
-int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
+int ima_must_appraise(struct ima_namespace *ns,
+		      struct user_namespace *mnt_userns, struct inode *inode,
 		      int mask, enum ima_hooks func);
 void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
 enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
@@ -329,7 +344,8 @@  int ima_read_xattr(struct dentry *dentry,
 		   struct evm_ima_xattr_data **xattr_value);
 
 #else
-static inline int ima_check_blacklist(struct integrity_iint_cache *iint,
+static inline int ima_check_blacklist(struct ima_namespace *ns,
+				      struct integrity_iint_cache *iint,
 				      const struct modsig *modsig, int pcr)
 {
 	return 0;
@@ -346,7 +362,8 @@  static inline int ima_appraise_measurement(enum ima_hooks func,
 	return INTEGRITY_UNKNOWN;
 }
 
-static inline int ima_must_appraise(struct user_namespace *mnt_userns,
+static inline int ima_must_appraise(struct ima_namespace *ns,
+				    struct user_namespace *mnt_userns,
 				    struct inode *inode, int mask,
 				    enum ima_hooks func)
 {
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index c6805af46211..90ef246a9f43 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -162,6 +162,7 @@  void ima_add_violation(struct file *file, const unsigned char *filename,
 
 /**
  * ima_get_action - appraise & measure decision based on policy.
+ * @ns: IMA namespace that has the policy
  * @mnt_userns:	user namespace of the mount the inode was found from
  * @inode: pointer to the inode associated with the object being validated
  * @cred: pointer to credentials structure to validate
@@ -185,7 +186,8 @@  void ima_add_violation(struct file *file, const unsigned char *filename,
  * Returns IMA_MEASURE, IMA_APPRAISE mask.
  *
  */
-int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
+int ima_get_action(struct ima_namespace *ns,
+		   struct user_namespace *mnt_userns, struct inode *inode,
 		   const struct cred *cred, u32 secid, int mask,
 		   enum ima_hooks func, int *pcr,
 		   struct ima_template_desc **template_desc,
@@ -193,9 +195,9 @@  int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
 {
 	int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
 
-	flags &= ima_policy_flag;
+	flags &= ns->ima_policy_flag;
 
-	return ima_match_policy(mnt_userns, inode, cred, secid, func, mask,
+	return ima_match_policy(ns, mnt_userns, inode, cred, secid, func, mask,
 				flags, pcr, template_desc, func_data,
 				allowed_algos);
 }
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 17232bbfb9f9..f1b99b895c68 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -68,7 +68,8 @@  bool is_ima_appraise_enabled(void)
  *
  * Return 1 to appraise or hash
  */
-int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
+int ima_must_appraise(struct ima_namespace *ns,
+		      struct user_namespace *mnt_userns, struct inode *inode,
 		      int mask, enum ima_hooks func)
 {
 	u32 secid;
@@ -77,7 +78,7 @@  int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
 		return 0;
 
 	security_current_getsecid_subj(&secid);
-	return ima_match_policy(mnt_userns, inode, current_cred(), secid,
+	return ima_match_policy(ns, mnt_userns, inode, current_cred(), secid,
 				func, mask, IMA_APPRAISE | IMA_HASH, NULL,
 				NULL, NULL, NULL);
 }
@@ -341,7 +342,8 @@  static int modsig_verify(enum ima_hooks func, const struct modsig *modsig,
  *
  * Returns -EPERM if the hash is blacklisted.
  */
-int ima_check_blacklist(struct integrity_iint_cache *iint,
+int ima_check_blacklist(struct ima_namespace *ns,
+			struct integrity_iint_cache *iint,
 			const struct modsig *modsig, int pcr)
 {
 	enum hash_algo hash_algo;
@@ -357,7 +359,8 @@  int ima_check_blacklist(struct integrity_iint_cache *iint,
 
 		rc = is_binary_blacklisted(digest, digestsize);
 		if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
-			process_buffer_measurement(&init_user_ns, NULL, digest, digestsize,
+			process_buffer_measurement(ns, &init_user_ns, NULL,
+						   digest, digestsize,
 						   "blacklisted-hash", NONE,
 						   pcr, NULL, false, NULL, 0);
 	}
@@ -527,14 +530,16 @@  void ima_inode_post_setattr(struct user_namespace *mnt_userns,
 			    struct dentry *dentry)
 {
 	struct inode *inode = d_backing_inode(dentry);
+	struct ima_namespace *ns = &init_ima_ns;
 	struct integrity_iint_cache *iint;
 	int action;
 
-	if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
+	if (!(ns->ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
 	    || !(inode->i_opflags & IOP_XATTR))
 		return;
 
-	action = ima_must_appraise(mnt_userns, inode, MAY_ACCESS, POST_SETATTR);
+	action = ima_must_appraise(ns, mnt_userns, inode, MAY_ACCESS,
+				   POST_SETATTR);
 	iint = integrity_iint_find(inode);
 	if (iint) {
 		set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags);
@@ -559,11 +564,12 @@  static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name,
 	return 0;
 }
 
-static void ima_reset_appraise_flags(struct inode *inode, int digsig)
+static void ima_reset_appraise_flags(struct ima_namespace *ns,
+				     struct inode *inode, int digsig)
 {
 	struct integrity_iint_cache *iint;
 
-	if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode))
+	if (!(ns->ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode))
 		return;
 
 	iint = integrity_iint_find(inode);
@@ -641,6 +647,7 @@  int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
 		       const void *xattr_value, size_t xattr_value_len)
 {
 	const struct evm_ima_xattr_data *xvalue = xattr_value;
+	struct ima_namespace *ns = &init_ima_ns;
 	int digsig = 0;
 	int result;
 
@@ -658,18 +665,19 @@  int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
 		if (result)
 			return result;
 
-		ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
+		ima_reset_appraise_flags(ns, d_backing_inode(dentry), digsig);
 	}
 	return result;
 }
 
 int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	int result;
 
 	result = ima_protect_xattr(dentry, xattr_name, NULL, 0);
 	if (result == 1 || evm_revalidate_status(xattr_name)) {
-		ima_reset_appraise_flags(d_backing_inode(dentry), 0);
+		ima_reset_appraise_flags(ns, d_backing_inode(dentry), 0);
 		if (result == 1)
 			result = 0;
 	}
diff --git a/security/integrity/ima/ima_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c
index f6aa0b47a772..70d87df26068 100644
--- a/security/integrity/ima/ima_asymmetric_keys.c
+++ b/security/integrity/ima/ima_asymmetric_keys.c
@@ -30,6 +30,7 @@  void ima_post_key_create_or_update(struct key *keyring, struct key *key,
 				   const void *payload, size_t payload_len,
 				   unsigned long flags, bool create)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	bool queued = false;
 
 	/* Only asymmetric keys are handled by this hook. */
@@ -60,7 +61,8 @@  void ima_post_key_create_or_update(struct key *keyring, struct key *key,
 	 * if the IMA policy is configured to measure a key linked
 	 * to the given keyring.
 	 */
-	process_buffer_measurement(&init_user_ns, NULL, payload, payload_len,
+	process_buffer_measurement(ns, &init_user_ns, NULL,
+				   payload, payload_len,
 				   keyring->description, KEY_CHECK, 0,
 				   keyring->description, false, NULL, 0);
 }
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index cd1683dad3bf..f7ad93a56982 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -271,7 +271,7 @@  static const struct file_operations ima_ascii_measurements_ops = {
 	.release = seq_release,
 };
 
-static ssize_t ima_read_policy(char *path)
+static ssize_t ima_read_policy(struct ima_namespace *ns, char *path)
 {
 	void *data = NULL;
 	char *datap;
@@ -296,7 +296,7 @@  static ssize_t ima_read_policy(char *path)
 	datap = data;
 	while (size > 0 && (p = strsep(&datap, "\n"))) {
 		pr_debug("rule: %s\n", p);
-		rc = ima_parse_add_rule(p);
+		rc = ima_parse_add_rule(ns, p);
 		if (rc < 0)
 			break;
 		size -= rc;
@@ -314,6 +314,7 @@  static ssize_t ima_read_policy(char *path)
 static ssize_t ima_write_policy(struct file *file, const char __user *buf,
 				size_t datalen, loff_t *ppos)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	char *data;
 	ssize_t result;
 
@@ -336,7 +337,7 @@  static ssize_t ima_write_policy(struct file *file, const char __user *buf,
 		goto out_free;
 
 	if (data[0] == '/') {
-		result = ima_read_policy(data);
+		result = ima_read_policy(ns, data);
 	} else if (ima_appraise & IMA_APPRAISE_POLICY) {
 		pr_err("signed policy file (specified as an absolute pathname) required\n");
 		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
@@ -344,7 +345,7 @@  static ssize_t ima_write_policy(struct file *file, const char __user *buf,
 				    1, 0);
 		result = -EACCES;
 	} else {
-		result = ima_parse_add_rule(data);
+		result = ima_parse_add_rule(ns, data);
 	}
 	mutex_unlock(&ima_write_mutex);
 out_free:
@@ -410,11 +411,12 @@  static int ima_open_policy(struct inode *inode, struct file *filp)
 static int ima_release_policy(struct inode *inode, struct file *file)
 {
 	const char *cause = valid_policy ? "completed" : "failed";
+	struct ima_namespace *ns = &init_ima_ns;
 
 	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
 		return seq_release(inode, file);
 
-	if (valid_policy && ima_check_policy() < 0) {
+	if (valid_policy && ima_check_policy(ns) < 0) {
 		cause = "failed";
 		valid_policy = 0;
 	}
@@ -424,13 +426,13 @@  static int ima_release_policy(struct inode *inode, struct file *file)
 			    "policy_update", cause, !valid_policy, 0);
 
 	if (!valid_policy) {
-		ima_delete_rules();
+		ima_delete_rules(ns);
 		valid_policy = 1;
 		clear_bit(IMA_FS_BUSY, &ima_fs_flags);
 		return 0;
 	}
 
-	ima_update_policy();
+	ima_update_policy(ns);
 #if !defined(CONFIG_IMA_WRITE_POLICY) && !defined(CONFIG_IMA_READ_POLICY)
 	securityfs_remove(ima_policy);
 	ima_policy = NULL;
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index 63979aefc95f..7e5b4187035d 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -101,15 +101,15 @@  static int __init ima_add_boot_aggregate(void)
 #ifdef CONFIG_IMA_LOAD_X509
 void __init ima_load_x509(void)
 {
-	int unset_flags = ima_policy_flag & IMA_APPRAISE;
+	int unset_flags = init_ima_ns.ima_policy_flag & IMA_APPRAISE;
 
-	ima_policy_flag &= ~unset_flags;
+	init_ima_ns.ima_policy_flag &= ~unset_flags;
 	integrity_load_x509(INTEGRITY_KEYRING_IMA, CONFIG_IMA_X509_PATH);
 
 	/* load also EVM key to avoid appraisal */
 	evm_load_x509();
 
-	ima_policy_flag |= unset_flags;
+	init_ima_ns.ima_policy_flag |= unset_flags;
 }
 #endif
 
@@ -117,6 +117,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");
@@ -142,7 +146,7 @@  int __init ima_init(void)
 	if (rc != 0)
 		return rc;
 
-	ima_init_policy();
+	ima_init_policy(&init_ima_ns);
 
 	rc = ima_fs_init();
 	if (rc != 0)
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..c919a456b525
--- /dev/null
+++ b/security/integrity/ima/ima_init_ima_ns.c
@@ -0,0 +1,29 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2016-2022 IBM Corporation
+ * Author:
+ *   Yuqiong Sun <suny@us.ibm.com>
+ *   Stefan Berger <stefanb@linux.vnet.ibm.com>
+ */
+
+#include "ima.h"
+
+static int ima_init_namespace(struct ima_namespace *ns)
+{
+	INIT_LIST_HEAD(&ns->ima_default_rules);
+	INIT_LIST_HEAD(&ns->ima_policy_rules);
+	INIT_LIST_HEAD(&ns->ima_temp_rules);
+	ns->ima_rules = (struct list_head __rcu *)(&ns->ima_default_rules);
+	ns->ima_policy_flag = 0;
+
+	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_main.c b/security/integrity/ima/ima_main.c
index 3d3f8c5c502b..400865c521dd 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -185,10 +185,11 @@  static void ima_check_last_writer(struct integrity_iint_cache *iint,
  */
 void ima_file_free(struct file *file)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	struct inode *inode = file_inode(file);
 	struct integrity_iint_cache *iint;
 
-	if (!ima_policy_flag || !S_ISREG(inode->i_mode))
+	if (!ns->ima_policy_flag || !S_ISREG(inode->i_mode))
 		return;
 
 	iint = integrity_iint_find(inode);
@@ -198,7 +199,8 @@  void ima_file_free(struct file *file)
 	ima_check_last_writer(iint, inode, file);
 }
 
-static int process_measurement(struct file *file, const struct cred *cred,
+static int process_measurement(struct ima_namespace *ns,
+			       struct file *file, const struct cred *cred,
 			       u32 secid, char *buf, loff_t size, int mask,
 			       enum ima_hooks func)
 {
@@ -217,18 +219,18 @@  static int process_measurement(struct file *file, const struct cred *cred,
 	enum hash_algo hash_algo;
 	unsigned int allowed_algos = 0;
 
-	if (!ima_policy_flag || !S_ISREG(inode->i_mode))
+	if (!ns->ima_policy_flag || !S_ISREG(inode->i_mode))
 		return 0;
 
 	/* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action
 	 * bitmask based on the appraise/audit/measurement policy.
 	 * Included is the appraise submask.
 	 */
-	action = ima_get_action(file_mnt_user_ns(file), inode, cred, secid,
+	action = ima_get_action(ns, file_mnt_user_ns(file), inode, cred, secid,
 				mask, func, &pcr, &template_desc, NULL,
 				&allowed_algos);
 	violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
-			   (ima_policy_flag & IMA_MEASURE));
+			   (ns->ima_policy_flag & IMA_MEASURE));
 	if (!action && !violation_check)
 		return 0;
 
@@ -346,7 +348,7 @@  static int process_measurement(struct file *file, const struct cred *cred,
 				      xattr_value, xattr_len, modsig, pcr,
 				      template_desc);
 	if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) {
-		rc = ima_check_blacklist(iint, modsig, pcr);
+		rc = ima_check_blacklist(ns, iint, modsig, pcr);
 		if (rc != -EPERM) {
 			inode_lock(inode);
 			rc = ima_appraise_measurement(func, iint, file,
@@ -405,12 +407,13 @@  static int process_measurement(struct file *file, const struct cred *cred,
  */
 int ima_file_mmap(struct file *file, unsigned long prot)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	u32 secid;
 
 	if (file && (prot & PROT_EXEC)) {
 		security_current_getsecid_subj(&secid);
-		return process_measurement(file, current_cred(), secid, NULL,
-					   0, MAY_EXEC, MMAP_CHECK);
+		return process_measurement(ns, file, current_cred(), secid,
+					   NULL, 0, MAY_EXEC, MMAP_CHECK);
 	}
 
 	return 0;
@@ -431,6 +434,7 @@  int ima_file_mmap(struct file *file, unsigned long prot)
  */
 int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	struct ima_template_desc *template = NULL;
 	struct file *file = vma->vm_file;
 	char filename[NAME_MAX];
@@ -443,13 +447,13 @@  int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
 	int pcr;
 
 	/* Is mprotect making an mmap'ed file executable? */
-	if (!(ima_policy_flag & IMA_APPRAISE) || !vma->vm_file ||
+	if (!(ns->ima_policy_flag & IMA_APPRAISE) || !vma->vm_file ||
 	    !(prot & PROT_EXEC) || (vma->vm_flags & VM_EXEC))
 		return 0;
 
 	security_current_getsecid_subj(&secid);
 	inode = file_inode(vma->vm_file);
-	action = ima_get_action(file_mnt_user_ns(vma->vm_file), inode,
+	action = ima_get_action(ns, file_mnt_user_ns(vma->vm_file), inode,
 				current_cred(), secid, MAY_EXEC, MMAP_CHECK,
 				&pcr, &template, NULL, NULL);
 
@@ -485,17 +489,18 @@  int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
  */
 int ima_bprm_check(struct linux_binprm *bprm)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	int ret;
 	u32 secid;
 
 	security_current_getsecid_subj(&secid);
-	ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0,
-				  MAY_EXEC, BPRM_CHECK);
+	ret = process_measurement(ns, bprm->file, current_cred(), secid, NULL,
+				  0, MAY_EXEC, BPRM_CHECK);
 	if (ret)
 		return ret;
 
 	security_cred_getsecid(bprm->cred, &secid);
-	return process_measurement(bprm->file, bprm->cred, secid, NULL, 0,
+	return process_measurement(ns, bprm->file, bprm->cred, secid, NULL, 0,
 				   MAY_EXEC, CREDS_CHECK);
 }
 
@@ -511,22 +516,23 @@  int ima_bprm_check(struct linux_binprm *bprm)
  */
 int ima_file_check(struct file *file, int mask)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	u32 secid;
 
 	security_current_getsecid_subj(&secid);
-	return process_measurement(file, current_cred(), secid, NULL, 0,
+	return process_measurement(ns, file, current_cred(), secid, NULL, 0,
 				   mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
 					   MAY_APPEND), FILE_CHECK);
 }
 EXPORT_SYMBOL_GPL(ima_file_check);
 
-static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf,
-			    size_t buf_size)
+static int __ima_inode_hash(struct ima_namespace *ns, struct inode *inode,
+			    struct file *file, char *buf, size_t buf_size)
 {
 	struct integrity_iint_cache *iint = NULL, tmp_iint;
 	int rc, hash_algo;
 
-	if (ima_policy_flag) {
+	if (ns->ima_policy_flag) {
 		iint = integrity_iint_find(inode);
 		if (iint)
 			mutex_lock(&iint->mutex);
@@ -595,10 +601,12 @@  static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf,
  */
 int ima_file_hash(struct file *file, char *buf, size_t buf_size)
 {
+	struct ima_namespace *ns = &init_ima_ns;
+
 	if (!file)
 		return -EINVAL;
 
-	return __ima_inode_hash(file_inode(file), file, buf, buf_size);
+	return __ima_inode_hash(ns, file_inode(file), file, buf, buf_size);
 }
 EXPORT_SYMBOL_GPL(ima_file_hash);
 
@@ -622,10 +630,12 @@  EXPORT_SYMBOL_GPL(ima_file_hash);
  */
 int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size)
 {
+	struct ima_namespace *ns = &init_ima_ns;
+
 	if (!inode)
 		return -EINVAL;
 
-	return __ima_inode_hash(inode, NULL, buf, buf_size);
+	return __ima_inode_hash(ns, inode, NULL, buf, buf_size);
 }
 EXPORT_SYMBOL_GPL(ima_inode_hash);
 
@@ -641,13 +651,14 @@  EXPORT_SYMBOL_GPL(ima_inode_hash);
 void ima_post_create_tmpfile(struct user_namespace *mnt_userns,
 			     struct inode *inode)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	struct integrity_iint_cache *iint;
 	int must_appraise;
 
-	if (!ima_policy_flag || !S_ISREG(inode->i_mode))
+	if (!ns->ima_policy_flag || !S_ISREG(inode->i_mode))
 		return;
 
-	must_appraise = ima_must_appraise(mnt_userns, inode, MAY_ACCESS,
+	must_appraise = ima_must_appraise(ns, mnt_userns, inode, MAY_ACCESS,
 					  FILE_CHECK);
 	if (!must_appraise)
 		return;
@@ -673,14 +684,15 @@  void ima_post_create_tmpfile(struct user_namespace *mnt_userns,
 void ima_post_path_mknod(struct user_namespace *mnt_userns,
 			 struct dentry *dentry)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	struct integrity_iint_cache *iint;
 	struct inode *inode = dentry->d_inode;
 	int must_appraise;
 
-	if (!ima_policy_flag || !S_ISREG(inode->i_mode))
+	if (!ns->ima_policy_flag || !S_ISREG(inode->i_mode))
 		return;
 
-	must_appraise = ima_must_appraise(mnt_userns, inode, MAY_ACCESS,
+	must_appraise = ima_must_appraise(ns, mnt_userns, inode, MAY_ACCESS,
 					  FILE_CHECK);
 	if (!must_appraise)
 		return;
@@ -709,6 +721,7 @@  void ima_post_path_mknod(struct user_namespace *mnt_userns,
 int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
 		  bool contents)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	enum ima_hooks func;
 	u32 secid;
 
@@ -731,7 +744,7 @@  int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
 	/* Read entire file for all partial reads. */
 	func = read_idmap[read_id] ?: FILE_CHECK;
 	security_current_getsecid_subj(&secid);
-	return process_measurement(file, current_cred(), secid, NULL,
+	return process_measurement(ns, file, current_cred(), secid, NULL,
 				   0, MAY_READ, func);
 }
 
@@ -759,6 +772,7 @@  const int read_idmap[READING_MAX_ID] = {
 int ima_post_read_file(struct file *file, void *buf, loff_t size,
 		       enum kernel_read_file_id read_id)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	enum ima_hooks func;
 	u32 secid;
 
@@ -767,14 +781,15 @@  int ima_post_read_file(struct file *file, void *buf, loff_t size,
 		return 0;
 
 	if (!file || !buf || size == 0) { /* should never happen */
-		if (ima_appraise & IMA_APPRAISE_ENFORCE)
+		if (ns == &init_ima_ns &&
+		    (ima_appraise & IMA_APPRAISE_ENFORCE))
 			return -EACCES;
 		return 0;
 	}
 
 	func = read_idmap[read_id] ?: FILE_CHECK;
 	security_current_getsecid_subj(&secid);
-	return process_measurement(file, current_cred(), secid, buf, size,
+	return process_measurement(ns, file, current_cred(), secid, buf, size,
 				   MAY_READ, func);
 }
 
@@ -862,6 +877,7 @@  int ima_post_load_data(char *buf, loff_t size,
 
 /**
  * process_buffer_measurement - Measure the buffer or the buffer data hash
+ * @ns: IMA namespace that has the policy
  * @mnt_userns:	user namespace of the mount the inode was found from
  * @inode: inode associated with the object being measured (NULL for KEY_CHECK)
  * @buf: pointer to the buffer that needs to be added to the log.
@@ -880,7 +896,8 @@  int ima_post_load_data(char *buf, loff_t size,
  * has been written to the passed location but not added to a measurement entry,
  * a negative value otherwise.
  */
-int process_buffer_measurement(struct user_namespace *mnt_userns,
+int process_buffer_measurement(struct ima_namespace *ns,
+			       struct user_namespace *mnt_userns,
 			       struct inode *inode, const void *buf, int size,
 			       const char *eventname, enum ima_hooks func,
 			       int pcr, const char *func_data,
@@ -905,7 +922,7 @@  int process_buffer_measurement(struct user_namespace *mnt_userns,
 	if (digest && digest_len < digest_hash_len)
 		return -EINVAL;
 
-	if (!ima_policy_flag && !digest)
+	if (!ns->ima_policy_flag && !digest)
 		return -ENOENT;
 
 	template = ima_template_desc_buf();
@@ -924,7 +941,7 @@  int process_buffer_measurement(struct user_namespace *mnt_userns,
 	 */
 	if (func) {
 		security_current_getsecid_subj(&secid);
-		action = ima_get_action(mnt_userns, inode, current_cred(),
+		action = ima_get_action(ns, mnt_userns, inode, current_cred(),
 					secid, 0, func, &pcr, &template,
 					func_data, NULL);
 		if (!(action & IMA_MEASURE) && !digest)
@@ -961,7 +978,7 @@  int process_buffer_measurement(struct user_namespace *mnt_userns,
 	if (digest)
 		memcpy(digest, iint.ima_hash->digest, digest_hash_len);
 
-	if (!ima_policy_flag || (func && !(action & IMA_MEASURE)))
+	if (!ns->ima_policy_flag || (func && !(action & IMA_MEASURE)))
 		return 1;
 
 	ret = ima_alloc_init_template(&event_data, &entry, template);
@@ -995,6 +1012,7 @@  int process_buffer_measurement(struct user_namespace *mnt_userns,
  */
 void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	struct fd f;
 
 	if (!buf || !size)
@@ -1004,7 +1022,8 @@  void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
 	if (!f.file)
 		return;
 
-	process_buffer_measurement(file_mnt_user_ns(f.file), file_inode(f.file),
+	process_buffer_measurement(ns,
+				   file_mnt_user_ns(f.file), file_inode(f.file),
 				   buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0,
 				   NULL, false, NULL, 0);
 	fdput(f);
@@ -1034,10 +1053,12 @@  int ima_measure_critical_data(const char *event_label,
 			      const void *buf, size_t buf_len,
 			      bool hash, u8 *digest, size_t digest_len)
 {
+	struct ima_namespace *ns = &init_ima_ns;
+
 	if (!event_name || !event_label || !buf || !buf_len)
 		return -ENOPARAM;
 
-	return process_buffer_measurement(&init_user_ns, NULL, buf, buf_len,
+	return process_buffer_measurement(ns, &init_user_ns, NULL, buf, buf_len,
 					  event_name, CRITICAL_DATA, 0,
 					  event_label, hash, digest,
 					  digest_len);
@@ -1046,6 +1067,7 @@  EXPORT_SYMBOL_GPL(ima_measure_critical_data);
 
 static int __init init_ima(void)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	int error;
 
 	ima_appraise_parse_cmdline();
@@ -1070,7 +1092,7 @@  static int __init init_ima(void)
 		pr_warn("Couldn't register LSM notifier, error %d\n", error);
 
 	if (!error)
-		ima_update_policy_flags();
+		ima_update_policy_flags(ns);
 
 	return error;
 }
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index eea6e92500b8..69b19f4d5fee 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -51,7 +51,6 @@ 
 #define INVALID_PCR(a) (((a) < 0) || \
 	(a) >= (sizeof_field(struct integrity_iint_cache, measured_pcrs) * 8))
 
-int ima_policy_flag;
 static int temp_ima_appraise;
 static int build_ima_appraise __ro_after_init;
 
@@ -232,11 +231,6 @@  static struct ima_rule_entry critical_data_rules[] __ro_after_init = {
 /* An array of architecture specific rules */
 static struct ima_rule_entry *arch_policy_entry __ro_after_init;
 
-static LIST_HEAD(ima_default_rules);
-static LIST_HEAD(ima_policy_rules);
-static LIST_HEAD(ima_temp_rules);
-static struct list_head __rcu *ima_rules = (struct list_head __rcu *)(&ima_default_rules);
-
 static int ima_policy __initdata;
 
 static int __init default_measure_policy_setup(char *str)
@@ -453,12 +447,12 @@  static bool ima_rule_contains_lsm_cond(struct ima_rule_entry *entry)
  * to the old, stale LSM policy.  Update the IMA LSM based rules to reflect
  * the reloaded LSM policy.
  */
-static void ima_lsm_update_rules(void)
+static void ima_lsm_update_rules(struct ima_namespace *ns)
 {
 	struct ima_rule_entry *entry, *e;
 	int result;
 
-	list_for_each_entry_safe(entry, e, &ima_policy_rules, list) {
+	list_for_each_entry_safe(entry, e, &ns->ima_policy_rules, list) {
 		if (!ima_rule_contains_lsm_cond(entry))
 			continue;
 
@@ -473,10 +467,12 @@  static void ima_lsm_update_rules(void)
 int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
 			  void *lsm_data)
 {
+	struct ima_namespace *ns = &init_ima_ns;
+
 	if (event != LSM_POLICY_CHANGE)
 		return NOTIFY_DONE;
 
-	ima_lsm_update_rules();
+	ima_lsm_update_rules(ns);
 	return NOTIFY_OK;
 }
 
@@ -668,6 +664,7 @@  static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
 
 /**
  * ima_match_policy - decision based on LSM and other conditions
+ * @ns: IMA namespace that has the policy
  * @mnt_userns:	user namespace of the mount the inode was found from
  * @inode: pointer to an inode for which the policy decision is being made
  * @cred: pointer to a credentials structure for which the policy decision is
@@ -687,7 +684,8 @@  static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
  * list when walking it.  Reads are many orders of magnitude more numerous
  * than writes so ima_match_policy() is classical RCU candidate.
  */
-int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
+int ima_match_policy(struct ima_namespace *ns,
+		     struct user_namespace *mnt_userns, struct inode *inode,
 		     const struct cred *cred, u32 secid, enum ima_hooks func,
 		     int mask, int flags, int *pcr,
 		     struct ima_template_desc **template_desc,
@@ -701,7 +699,7 @@  int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
 		*template_desc = ima_template_desc_current();
 
 	rcu_read_lock();
-	ima_rules_tmp = rcu_dereference(ima_rules);
+	ima_rules_tmp = rcu_dereference(ns->ima_rules);
 	list_for_each_entry_rcu(entry, ima_rules_tmp, list) {
 
 		if (!(entry->action & actmask))
@@ -745,8 +743,8 @@  int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
 }
 
 /**
- * ima_update_policy_flags() - Update global IMA variables
- *
+ * ima_update_policy_flags() - Update namespaced IMA variables
+ * @ns: IMA namespace that has the policy
  * Update ima_policy_flag and ima_setxattr_allowed_hash_algorithms
  * based on the currently loaded policy.
  *
@@ -759,14 +757,14 @@  int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
  *
  * Context: called after a policy update and at system initialization.
  */
-void ima_update_policy_flags(void)
+void ima_update_policy_flags(struct ima_namespace *ns)
 {
 	struct ima_rule_entry *entry;
 	int new_policy_flag = 0;
 	struct list_head *ima_rules_tmp;
 
 	rcu_read_lock();
-	ima_rules_tmp = rcu_dereference(ima_rules);
+	ima_rules_tmp = rcu_dereference(ns->ima_rules);
 	list_for_each_entry_rcu(entry, ima_rules_tmp, list) {
 		/*
 		 * SETXATTR_CHECK rules do not implement a full policy check
@@ -796,7 +794,7 @@  void ima_update_policy_flags(void)
 	if (!ima_appraise)
 		new_policy_flag &= ~IMA_APPRAISE;
 
-	ima_policy_flag = new_policy_flag;
+	ns->ima_policy_flag = new_policy_flag;
 }
 
 static int ima_appraise_flag(enum ima_hooks func)
@@ -812,7 +810,8 @@  static int ima_appraise_flag(enum ima_hooks func)
 	return 0;
 }
 
-static void add_rules(struct ima_rule_entry *entries, int count,
+static void add_rules(struct ima_namespace *ns,
+		      struct ima_rule_entry *entries, int count,
 		      enum policy_rule_list policy_rule)
 {
 	int i = 0;
@@ -821,7 +820,7 @@  static void add_rules(struct ima_rule_entry *entries, int count,
 		struct ima_rule_entry *entry;
 
 		if (policy_rule & IMA_DEFAULT_POLICY)
-			list_add_tail(&entries[i].list, &ima_default_rules);
+			list_add_tail(&entries[i].list, &ns->ima_default_rules);
 
 		if (policy_rule & IMA_CUSTOM_POLICY) {
 			entry = kmemdup(&entries[i], sizeof(*entry),
@@ -829,7 +828,7 @@  static void add_rules(struct ima_rule_entry *entries, int count,
 			if (!entry)
 				continue;
 
-			list_add_tail(&entry->list, &ima_policy_rules);
+			list_add_tail(&entry->list, &ns->ima_policy_rules);
 		}
 		if (entries[i].action == APPRAISE) {
 			if (entries != build_appraise_rules)
@@ -842,9 +841,10 @@  static void add_rules(struct ima_rule_entry *entries, int count,
 	}
 }
 
-static int ima_parse_rule(char *rule, struct ima_rule_entry *entry);
+static int ima_parse_rule(struct ima_namespace *ns,
+			  char *rule, struct ima_rule_entry *entry);
 
-static int __init ima_init_arch_policy(void)
+static int __init ima_init_arch_policy(struct ima_namespace *ns)
 {
 	const char * const *arch_rules;
 	const char * const *rules;
@@ -872,7 +872,7 @@  static int __init ima_init_arch_policy(void)
 		result = strscpy(rule, *rules, sizeof(rule));
 
 		INIT_LIST_HEAD(&arch_policy_entry[i].list);
-		result = ima_parse_rule(rule, &arch_policy_entry[i]);
+		result = ima_parse_rule(ns, rule, &arch_policy_entry[i]);
 		if (result) {
 			pr_warn("Skipping unknown architecture policy rule: %s\n",
 				rule);
@@ -887,26 +887,27 @@  static int __init ima_init_arch_policy(void)
 
 /**
  * ima_init_policy - initialize the default measure rules.
- *
+ * @ns: IMA namespace to which the policy belongs to
  * ima_rules points to either the ima_default_rules or the new ima_policy_rules.
  */
-void __init ima_init_policy(void)
+void __init ima_init_policy(struct ima_namespace *ns)
 {
 	int build_appraise_entries, arch_entries;
 
 	/* if !ima_policy, we load NO default rules */
 	if (ima_policy)
-		add_rules(dont_measure_rules, ARRAY_SIZE(dont_measure_rules),
+		add_rules(ns, dont_measure_rules,
+			  ARRAY_SIZE(dont_measure_rules),
 			  IMA_DEFAULT_POLICY);
 
 	switch (ima_policy) {
 	case ORIGINAL_TCB:
-		add_rules(original_measurement_rules,
+		add_rules(ns, original_measurement_rules,
 			  ARRAY_SIZE(original_measurement_rules),
 			  IMA_DEFAULT_POLICY);
 		break;
 	case DEFAULT_TCB:
-		add_rules(default_measurement_rules,
+		add_rules(ns, default_measurement_rules,
 			  ARRAY_SIZE(default_measurement_rules),
 			  IMA_DEFAULT_POLICY);
 		break;
@@ -920,11 +921,11 @@  void __init ima_init_policy(void)
 	 * and custom policies, prior to other appraise rules.
 	 * (Highest priority)
 	 */
-	arch_entries = ima_init_arch_policy();
+	arch_entries = ima_init_arch_policy(ns);
 	if (!arch_entries)
 		pr_info("No architecture policies found\n");
 	else
-		add_rules(arch_policy_entry, arch_entries,
+		add_rules(ns, arch_policy_entry, arch_entries,
 			  IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY);
 
 	/*
@@ -932,7 +933,7 @@  void __init ima_init_policy(void)
 	 * signatures, prior to other appraise rules.
 	 */
 	if (ima_use_secure_boot)
-		add_rules(secure_boot_rules, ARRAY_SIZE(secure_boot_rules),
+		add_rules(ns, secure_boot_rules, ARRAY_SIZE(secure_boot_rules),
 			  IMA_DEFAULT_POLICY);
 
 	/*
@@ -944,39 +945,41 @@  void __init ima_init_policy(void)
 	build_appraise_entries = ARRAY_SIZE(build_appraise_rules);
 	if (build_appraise_entries) {
 		if (ima_use_secure_boot)
-			add_rules(build_appraise_rules, build_appraise_entries,
+			add_rules(ns, build_appraise_rules,
+				  build_appraise_entries,
 				  IMA_CUSTOM_POLICY);
 		else
-			add_rules(build_appraise_rules, build_appraise_entries,
+			add_rules(ns, build_appraise_rules,
+				  build_appraise_entries,
 				  IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY);
 	}
 
 	if (ima_use_appraise_tcb)
-		add_rules(default_appraise_rules,
+		add_rules(ns, default_appraise_rules,
 			  ARRAY_SIZE(default_appraise_rules),
 			  IMA_DEFAULT_POLICY);
 
 	if (ima_use_critical_data)
-		add_rules(critical_data_rules,
+		add_rules(ns, critical_data_rules,
 			  ARRAY_SIZE(critical_data_rules),
 			  IMA_DEFAULT_POLICY);
 
 	atomic_set(&ima_setxattr_allowed_hash_algorithms, 0);
 
-	ima_update_policy_flags();
+	ima_update_policy_flags(ns);
 }
 
 /* Make sure we have a valid policy, at least containing some rules. */
-int ima_check_policy(void)
+int ima_check_policy(struct ima_namespace *ns)
 {
-	if (list_empty(&ima_temp_rules))
+	if (list_empty(&ns->ima_temp_rules))
 		return -EINVAL;
 	return 0;
 }
 
 /**
  * ima_update_policy - update default_rules with new measure rules
- *
+ * @ns: IMA namespace that has the policy
  * Called on file .release to update the default rules with a complete new
  * policy.  What we do here is to splice ima_policy_rules and ima_temp_rules so
  * they make a queue.  The policy may be updated multiple times and this is the
@@ -985,16 +988,17 @@  int ima_check_policy(void)
  * Policy rules are never deleted so ima_policy_flag gets zeroed only once when
  * we switch from the default policy to user defined.
  */
-void ima_update_policy(void)
+void ima_update_policy(struct ima_namespace *ns)
 {
-	struct list_head *policy = &ima_policy_rules;
+	struct list_head *policy = &ns->ima_policy_rules;
 
-	list_splice_tail_init_rcu(&ima_temp_rules, policy, synchronize_rcu);
+	list_splice_tail_init_rcu(&ns->ima_temp_rules, policy,
+				  synchronize_rcu);
 
-	if (ima_rules != (struct list_head __rcu *)policy) {
-		ima_policy_flag = 0;
+	if (ns->ima_rules != (struct list_head __rcu *)policy) {
+		ns->ima_policy_flag = 0;
 
-		rcu_assign_pointer(ima_rules, policy);
+		rcu_assign_pointer(ns->ima_rules, policy);
 		/*
 		 * IMA architecture specific policy rules are specified
 		 * as strings and converted to an array of ima_entry_rules
@@ -1003,10 +1007,10 @@  void ima_update_policy(void)
 		 */
 		kfree(arch_policy_entry);
 	}
-	ima_update_policy_flags();
+	ima_update_policy_flags(ns);
 
 	/* Custom IMA policy has been loaded */
-	ima_process_queued_keys();
+	ima_process_queued_keys(ns);
 }
 
 /* Keep the enumeration in sync with the policy_tokens! */
@@ -1076,7 +1080,8 @@  static const match_table_t policy_tokens = {
 	{Opt_err, NULL}
 };
 
-static int ima_lsm_rule_init(struct ima_rule_entry *entry,
+static int ima_lsm_rule_init(struct ima_namespace *ns,
+			     struct ima_rule_entry *entry,
 			     substring_t *args, int lsm_rule, int audit_type)
 {
 	int result;
@@ -1096,7 +1101,8 @@  static int ima_lsm_rule_init(struct ima_rule_entry *entry,
 		pr_warn("rule for LSM \'%s\' is undefined\n",
 			entry->lsm[lsm_rule].args_p);
 
-		if (ima_rules == (struct list_head __rcu *)(&ima_default_rules)) {
+		if (ns->ima_rules ==
+			(struct list_head __rcu *)&ns->ima_default_rules) {
 			kfree(entry->lsm[lsm_rule].args_p);
 			entry->lsm[lsm_rule].args_p = NULL;
 			result = -EINVAL;
@@ -1323,7 +1329,8 @@  static unsigned int ima_parse_appraise_algos(char *arg)
 	return res;
 }
 
-static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
+static int ima_parse_rule(struct ima_namespace *ns,
+			  char *rule, struct ima_rule_entry *entry)
 {
 	struct audit_buffer *ab;
 	char *from;
@@ -1673,37 +1680,37 @@  static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 			break;
 		case Opt_obj_user:
 			ima_log_string(ab, "obj_user", args[0].from);
-			result = ima_lsm_rule_init(entry, args,
+			result = ima_lsm_rule_init(ns, entry, args,
 						   LSM_OBJ_USER,
 						   AUDIT_OBJ_USER);
 			break;
 		case Opt_obj_role:
 			ima_log_string(ab, "obj_role", args[0].from);
-			result = ima_lsm_rule_init(entry, args,
+			result = ima_lsm_rule_init(ns, entry, args,
 						   LSM_OBJ_ROLE,
 						   AUDIT_OBJ_ROLE);
 			break;
 		case Opt_obj_type:
 			ima_log_string(ab, "obj_type", args[0].from);
-			result = ima_lsm_rule_init(entry, args,
+			result = ima_lsm_rule_init(ns, entry, args,
 						   LSM_OBJ_TYPE,
 						   AUDIT_OBJ_TYPE);
 			break;
 		case Opt_subj_user:
 			ima_log_string(ab, "subj_user", args[0].from);
-			result = ima_lsm_rule_init(entry, args,
+			result = ima_lsm_rule_init(ns, entry, args,
 						   LSM_SUBJ_USER,
 						   AUDIT_SUBJ_USER);
 			break;
 		case Opt_subj_role:
 			ima_log_string(ab, "subj_role", args[0].from);
-			result = ima_lsm_rule_init(entry, args,
+			result = ima_lsm_rule_init(ns, entry, args,
 						   LSM_SUBJ_ROLE,
 						   AUDIT_SUBJ_ROLE);
 			break;
 		case Opt_subj_type:
 			ima_log_string(ab, "subj_type", args[0].from);
-			result = ima_lsm_rule_init(entry, args,
+			result = ima_lsm_rule_init(ns, entry, args,
 						   LSM_SUBJ_TYPE,
 						   AUDIT_SUBJ_TYPE);
 			break;
@@ -1804,12 +1811,13 @@  static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 
 /**
  * ima_parse_add_rule - add a rule to ima_policy_rules
+ * @ns: IMA namespace that has the policy
  * @rule - ima measurement policy rule
  *
  * Avoid locking by allowing just one writer at a time in ima_write_policy()
  * Returns the length of the rule parsed, an error code on failure
  */
-ssize_t ima_parse_add_rule(char *rule)
+ssize_t ima_parse_add_rule(struct ima_namespace *ns, char *rule)
 {
 	static const char op[] = "update_policy";
 	char *p;
@@ -1833,7 +1841,7 @@  ssize_t ima_parse_add_rule(char *rule)
 
 	INIT_LIST_HEAD(&entry->list);
 
-	result = ima_parse_rule(p, entry);
+	result = ima_parse_rule(ns, p, entry);
 	if (result) {
 		ima_free_rule(entry);
 		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
@@ -1842,23 +1850,24 @@  ssize_t ima_parse_add_rule(char *rule)
 		return result;
 	}
 
-	list_add_tail(&entry->list, &ima_temp_rules);
+	list_add_tail(&entry->list, &ns->ima_temp_rules);
 
 	return len;
 }
 
 /**
- * ima_delete_rules() called to cleanup invalid in-flight policy.
+ * ima_delete_rules - called to cleanup invalid in-flight policy.
+ * @ns: IMA namespace that has the policy
  * We don't need locking as we operate on the temp list, which is
  * different from the active one.  There is also only one user of
  * ima_delete_rules() at a time.
  */
-void ima_delete_rules(void)
+void ima_delete_rules(struct ima_namespace *ns)
 {
 	struct ima_rule_entry *entry, *tmp;
 
 	temp_ima_appraise = 0;
-	list_for_each_entry_safe(entry, tmp, &ima_temp_rules, list) {
+	list_for_each_entry_safe(entry, tmp, &ns->ima_temp_rules, list) {
 		list_del(&entry->list);
 		ima_free_rule(entry);
 	}
@@ -1884,12 +1893,13 @@  static const char *const mask_tokens[] = {
 
 void *ima_policy_start(struct seq_file *m, loff_t *pos)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	loff_t l = *pos;
 	struct ima_rule_entry *entry;
 	struct list_head *ima_rules_tmp;
 
 	rcu_read_lock();
-	ima_rules_tmp = rcu_dereference(ima_rules);
+	ima_rules_tmp = rcu_dereference(ns->ima_rules);
 	list_for_each_entry_rcu(entry, ima_rules_tmp, list) {
 		if (!l--) {
 			rcu_read_unlock();
@@ -1902,6 +1912,7 @@  void *ima_policy_start(struct seq_file *m, loff_t *pos)
 
 void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	struct ima_rule_entry *entry = v;
 
 	rcu_read_lock();
@@ -1909,8 +1920,8 @@  void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos)
 	rcu_read_unlock();
 	(*pos)++;
 
-	return (&entry->list == &ima_default_rules ||
-		&entry->list == &ima_policy_rules) ? NULL : entry;
+	return (&entry->list == &ns->ima_default_rules ||
+		&entry->list == &ns->ima_policy_rules) ? NULL : entry;
 }
 
 void ima_policy_stop(struct seq_file *m, void *v)
@@ -2173,6 +2184,7 @@  int ima_policy_show(struct seq_file *m, void *v)
  */
 bool ima_appraise_signature(enum kernel_read_file_id id)
 {
+	struct ima_namespace *ns = &init_ima_ns;
 	struct ima_rule_entry *entry;
 	bool found = false;
 	enum ima_hooks func;
@@ -2184,7 +2196,7 @@  bool ima_appraise_signature(enum kernel_read_file_id id)
 	func = read_idmap[id] ?: FILE_CHECK;
 
 	rcu_read_lock();
-	ima_rules_tmp = rcu_dereference(ima_rules);
+	ima_rules_tmp = rcu_dereference(ns->ima_rules);
 	list_for_each_entry_rcu(entry, ima_rules_tmp, list) {
 		if (entry->action != APPRAISE)
 			continue;
diff --git a/security/integrity/ima/ima_queue_keys.c b/security/integrity/ima/ima_queue_keys.c
index 93056c03bf5a..e366a21dd8be 100644
--- a/security/integrity/ima/ima_queue_keys.c
+++ b/security/integrity/ima/ima_queue_keys.c
@@ -10,6 +10,7 @@ 
 
 #include <linux/user_namespace.h>
 #include <linux/workqueue.h>
+#include <linux/ima.h>
 #include <keys/asymmetric-type.h>
 #include "ima.h"
 
@@ -42,7 +43,7 @@  static bool timer_expired;
 static void ima_keys_handler(struct work_struct *work)
 {
 	timer_expired = true;
-	ima_process_queued_keys();
+	ima_process_queued_keys(&init_ima_ns);
 }
 
 /*
@@ -130,11 +131,15 @@  bool ima_queue_key(struct key *keyring, const void *payload,
  * This function sets ima_process_keys to true and processes queued keys.
  * From here on keys will be processed right away (not queued).
  */
-void ima_process_queued_keys(void)
+void ima_process_queued_keys(struct ima_namespace *ns)
 {
 	struct ima_key_entry *entry, *tmp;
 	bool process = false;
 
+	/* only applies to init_ima_ns */
+	if (ns != &init_ima_ns)
+		return;
+
 	if (ima_process_keys)
 		return;
 
@@ -159,7 +164,7 @@  void ima_process_queued_keys(void)
 
 	list_for_each_entry_safe(entry, tmp, &ima_keys, list) {
 		if (!timer_expired)
-			process_buffer_measurement(&init_user_ns, NULL,
+			process_buffer_measurement(ns, &init_user_ns, NULL,
 						   entry->payload,
 						   entry->payload_len,
 						   entry->keyring_name,