[RFC 10/11] ima: handling all policy flags per namespace using ima_ns_policy structure

Guilherme Magalhaes guilherme.magalhaes at hpe.com
Thu May 11 14:00:02 UTC 2017


Global ima_appraise still saves the initial appraise mode and it is used to
initialize namespace.ima_appraise flag when a user defined policy is set.
Globals moved into ima_ns_policy structure (namespace IMA policy private data):
    - ima_policy_flag
    - ima_appraise
    - ima_rules
    - ima_policy_rules
Functions changed to take as parameter the correct ima_ns_policy structure.
ima_initial_namespace_policy is initialized in ima_init_policy and stores the
initial namespace IMA policy data.
Replacing direct uses of ima_ns_policy lock with the ima_namespace_lock() and
ima_namespace_unlock() functions.

Signed-off-by: Guilherme Magalhaes <guilherme.magalhaes at hpe.com>
---
 security/integrity/ima/ima.h          |  17 +++---
 security/integrity/ima/ima_api.c      |   6 +-
 security/integrity/ima/ima_appraise.c |  21 +++++--
 security/integrity/ima/ima_fs.c       |  26 ++++++---
 security/integrity/ima/ima_init.c     |  11 +++-
 security/integrity/ima/ima_main.c     |  36 ++++++++----
 security/integrity/ima/ima_policy.c   | 100 +++++++++++++++++++++++++---------
 7 files changed, 150 insertions(+), 67 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 20b927e..fd5cfe9 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -61,9 +61,6 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
 #endif
 
 
-/* current content of the policy */
-extern int ima_policy_flag;
-
 /* set during initialization */
 extern int ima_initialized;
 extern int ima_used_chip;
@@ -149,7 +146,6 @@ struct ima_ns_policy {
 	int ima_policy_flag;
 	int ima_appraise;
 };
-
 extern struct ima_ns_policy ima_initial_namespace_policy;
 #ifdef CONFIG_IMA_PER_NAMESPACE
 extern spinlock_t ima_ns_policy_lock;
@@ -241,7 +237,7 @@ enum ima_hooks {
 
 /* LIM API function definitions */
 int ima_get_action(struct inode *inode, int mask,
-		   enum ima_hooks func, int *pcr);
+		   enum ima_hooks func, int *pcr, struct ima_ns_policy *ins);
 int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
 int ima_collect_measurement(struct integrity_iint_cache *iint,
 			    struct file *file, void *buf, loff_t size,
@@ -262,10 +258,10 @@ const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
 
 /* IMA policy related functions */
 int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
-		     int flags, int *pcr);
+		     int flags, int *pcr, struct ima_ns_policy *ins);
 void ima_init_policy(void);
-void ima_update_policy(void);
-void ima_update_policy_flag(void);
+void ima_update_policy(struct ima_ns_policy *ins);
+void ima_update_policy_flag(struct ima_ns_policy *ins);
 ssize_t ima_parse_add_rule(char *);
 void ima_delete_rules(void);
 void ima_free_policy_rules(struct list_head *policy_rules);
@@ -283,12 +279,13 @@ int ima_policy_show(struct seq_file *m, void *v);
 #define IMA_APPRAISE_FIRMWARE	0x10
 #define IMA_APPRAISE_POLICY	0x20
 
+
 #ifdef CONFIG_IMA_APPRAISE
 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, int opened);
+			     int xattr_len, int opened, struct ima_ns_policy *ins);
 int ima_must_appraise(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,
@@ -304,7 +301,7 @@ static inline int ima_appraise_measurement(enum ima_hooks func,
 					   struct file *file,
 					   const unsigned char *filename,
 					   struct evm_ima_xattr_data *xattr_value,
-					   int xattr_len, int opened)
+					   int xattr_len, int opened, struct ima_ns_policy *ins)
 {
 	return INTEGRITY_UNKNOWN;
 }
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index b05c1fd..9aba542 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -173,13 +173,13 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
  * Returns IMA_MEASURE, IMA_APPRAISE mask.
  *
  */
-int ima_get_action(struct inode *inode, int mask, enum ima_hooks func, int *pcr)
+int ima_get_action(struct inode *inode, int mask, enum ima_hooks func, int *pcr, struct ima_ns_policy *ins)
 {
 	int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE;
 
-	flags &= ima_policy_flag;
+	flags &= ins->ima_policy_flag;
 
-	return ima_match_policy(inode, func, mask, flags, pcr);
+	return ima_match_policy(inode, func, mask, flags, pcr, ins);
 }
 
 /*
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 1fd9539..510bb2f 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -26,6 +26,7 @@ static int __init default_appraise_setup(char *str)
 		ima_appraise = IMA_APPRAISE_LOG;
 	else if (strncmp(str, "fix", 3) == 0)
 		ima_appraise = IMA_APPRAISE_FIX;
+
 	return 1;
 }
 
@@ -38,10 +39,12 @@ __setup("ima_appraise=", default_appraise_setup);
  */
 int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func)
 {
-	if (!ima_appraise)
+	struct ima_ns_policy *ins = ima_get_current_namespace_policy();
+
+	if (!ins->ima_appraise)
 		return 0;
 
-	return ima_match_policy(inode, func, mask, IMA_APPRAISE, NULL);
+	return ima_match_policy(inode, func, mask, IMA_APPRAISE, NULL, ins);
 }
 
 static int ima_fix_xattr(struct dentry *dentry,
@@ -189,7 +192,7 @@ 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, int opened)
+			     int xattr_len, int opened, struct ima_ns_policy *ins)
 {
 	static const char op[] = "appraise_data";
 	char *cause = "unknown";
@@ -273,7 +276,7 @@ int ima_appraise_measurement(enum ima_hooks func,
 
 out:
 	if (status != INTEGRITY_PASS) {
-		if ((ima_appraise & IMA_APPRAISE_FIX) &&
+		if ((ins->ima_appraise & IMA_APPRAISE_FIX) &&
 		    (!xattr_value ||
 		     xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
 			if (!ima_fix_xattr(dentry, iint))
@@ -326,8 +329,11 @@ void ima_inode_post_setattr(struct dentry *dentry)
 	struct inode *inode = d_backing_inode(dentry);
 	struct integrity_iint_cache *iint;
 	int must_appraise;
+	struct ima_ns_policy *ins;
 
-	if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
+	ins = ima_get_current_namespace_policy();
+
+	if (!(ins->ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
 	    || !(inode->i_opflags & IOP_XATTR))
 		return;
 
@@ -363,8 +369,11 @@ static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name,
 static void ima_reset_appraise_flags(struct inode *inode, int digsig)
 {
 	struct integrity_iint_cache *iint;
+	struct ima_ns_policy *ins;
+
+	ins = ima_get_current_namespace_policy();
 
-	if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode))
+	if (!(ins->ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode))
 		return;
 
 	iint = integrity_iint_find(inode);
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 94e89fe..bc18722 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -308,7 +308,7 @@ static int allocate_namespace_policy(struct ima_ns_policy **ins,
 
 	p->policy_dentry = policy_dentry;
 	p->ns_dentry = ns_dentry;
-	p->ima_appraise = 0;
+	p->ima_appraise = ima_appraise;
 	p->ima_policy_flag = 0;
 	INIT_LIST_HEAD(&p->ima_policy_rules);
 	/* namespace starts with empty rules and not pointing to
@@ -488,6 +488,7 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf,
 {
 	char *data;
 	ssize_t result;
+	struct ima_ns_policy *ins;
 
 	if (datalen >= PAGE_SIZE)
 		datalen = PAGE_SIZE - 1;
@@ -512,19 +513,30 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf,
 	if (result < 0)
 		goto out_free;
 
+	ima_namespace_lock();
+	ins = ima_get_namespace_policy_from_inode(file->f_inode);
+	if (!ins) {
+		/* the namespace is not valid anymore, indicate the error
+		 * and exit */
+		result = -EINVAL;
+		goto out_unlock;
+	}
+
 	if (data[0] == '/') {
 		result = ima_read_policy(data);
-	} else if (ima_appraise & IMA_APPRAISE_POLICY) {
+	} else if (ins->ima_appraise & IMA_APPRAISE_POLICY) {
 		pr_err("IMA: signed policy file (specified as an absolute pathname) required\n");
 		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
 				    "policy_update", "signed policy required",
 				    1, 0);
 
-		if (ima_appraise & IMA_APPRAISE_ENFORCE)
+		if (ins->ima_appraise & IMA_APPRAISE_ENFORCE)
 			result = -EACCES;
 	} else {
 		result = ima_parse_add_rule(data);
 	}
+out_unlock:
+	ima_namespace_unlock();
 	mutex_unlock(&ima_write_mutex);
 out_free:
 	kfree(data);
@@ -611,7 +623,7 @@ static int ima_release_policy(struct inode *inode, struct file *file)
 		return 0;
 	}
 
-	ima_update_policy();
+	ima_update_policy(ins);
 #ifndef	CONFIG_IMA_WRITE_POLICY
 	if (ins == &ima_initial_namespace_policy) {
 		securityfs_remove(ima_policy_initial_ns);
@@ -698,16 +710,16 @@ void ima_mnt_namespace_dying(unsigned int ns_id)
 {
 	struct ima_ns_policy *p;
 
-	spin_lock(&ima_ns_policy_lock);
+	ima_namespace_lock();
 	p = radix_tree_delete(&ima_ns_policy_mapping, ns_id);
 
 	if (!p) {
-		spin_unlock(&ima_ns_policy_lock);
+		ima_namespace_unlock();
 		return;
 	}
 
 	free_namespace_policy(p);
-	spin_unlock(&ima_ns_policy_lock);
+	ima_namespace_unlock();
 }
 
 static ssize_t handle_new_namespace_policy(const char *data, size_t datalen)
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index b557ee3..f0bb196 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -96,11 +96,16 @@ 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;
+	struct ima_ns_policy *ins;
 
-	ima_policy_flag &= ~unset_flags;
+	ins = ima_get_current_namespace_policy();
+
+	unset_flags = ins->ima_policy_flag & IMA_APPRAISE;
+
+	ins->ima_policy_flag &= ~unset_flags;
 	integrity_load_x509(INTEGRITY_KEYRING_IMA, CONFIG_IMA_X509_PATH);
-	ima_policy_flag |= unset_flags;
+	ins->ima_policy_flag |= unset_flags;
 }
 #endif
 
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 2aebb79..1b995bb 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -30,6 +30,7 @@
 int ima_initialized;
 
 #ifdef CONFIG_IMA_APPRAISE
+/* Used during IMA initialization only */
 int ima_appraise = IMA_APPRAISE_ENFORCE;
 #else
 int ima_appraise;
@@ -144,9 +145,13 @@ void ima_file_free(struct file *file)
 {
 	struct inode *inode = file_inode(file);
 	struct integrity_iint_cache *iint;
+	struct ima_ns_policy *ins;
 
-	if (!ima_policy_flag || !S_ISREG(inode->i_mode))
+	ins = ima_get_current_namespace_policy();
+
+	if (!ins->ima_policy_flag || !S_ISREG(inode->i_mode)) {
 		return;
+	}
 
 	iint = integrity_iint_find(inode);
 	if (!iint)
@@ -170,17 +175,20 @@ static int process_measurement(struct file *file, char *buf, loff_t size,
 	int xattr_len = 0;
 	bool violation_check;
 	enum hash_algo hash_algo;
+	struct ima_ns_policy *ins;
 
-	if (!ima_policy_flag || !S_ISREG(inode->i_mode))
+	ins = ima_get_current_namespace_policy();
+
+	if (!ins->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(inode, mask, func, &pcr);
+	action = ima_get_action(inode, mask, func, &pcr, ins);
 	violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
-			   (ima_policy_flag & IMA_MEASURE));
+			   (ins->ima_policy_flag & IMA_MEASURE));
 	if (!action && !violation_check)
 		return 0;
 
@@ -249,7 +257,7 @@ static int process_measurement(struct file *file, char *buf, loff_t size,
 				      xattr_value, xattr_len, pcr);
 	if (action & IMA_APPRAISE_SUBMASK)
 		rc = ima_appraise_measurement(func, iint, file, pathname,
-					      xattr_value, xattr_len, opened);
+					      xattr_value, xattr_len, opened, ins);
 	if (action & IMA_AUDIT)
 		ima_audit_measurement(iint, pathname);
 
@@ -263,7 +271,7 @@ static int process_measurement(struct file *file, char *buf, loff_t size,
 		__putname(pathbuf);
 out:
 	inode_unlock(inode);
-	if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE))
+	if ((rc && must_appraise) && (ins->ima_appraise & IMA_APPRAISE_ENFORCE))
 		return -EACCES;
 	return 0;
 }
@@ -361,8 +369,10 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
 {
 	if (!file && read_id == READING_MODULE) {
 #ifndef CONFIG_MODULE_SIG_FORCE
-		if ((ima_appraise & IMA_APPRAISE_MODULES) &&
-		    (ima_appraise & IMA_APPRAISE_ENFORCE))
+		struct ima_ns_policy *ins;
+		ins = ima_get_current_namespace_policy();
+		if ((ins->ima_appraise & IMA_APPRAISE_MODULES) &&
+		    (ins->ima_appraise & IMA_APPRAISE_ENFORCE))
 			return -EACCES;	/* INTEGRITY_UNKNOWN */
 #endif
 		return 0;	/* We rely on module signature checking */
@@ -395,10 +405,13 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
 		       enum kernel_read_file_id read_id)
 {
 	enum ima_hooks func;
+	struct ima_ns_policy *ins;
+
+	ins = ima_get_current_namespace_policy();
 
 	if (!file && read_id == READING_FIRMWARE) {
-		if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
-		    (ima_appraise & IMA_APPRAISE_ENFORCE))
+		if ((ins->ima_appraise & IMA_APPRAISE_FIRMWARE) &&
+		    (ins->ima_appraise & IMA_APPRAISE_ENFORCE))
 			return -EACCES;	/* INTEGRITY_UNKNOWN */
 		return 0;
 	}
@@ -407,7 +420,7 @@ 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 (ins->ima_appraise & IMA_APPRAISE_ENFORCE)
 			return -EACCES;
 		return 0;
 	}
@@ -425,7 +438,6 @@ static int __init init_ima(void)
 	error = ima_init();
 	if (!error) {
 		ima_initialized = 1;
-		ima_update_policy_flag();
 	}
 	return error;
 }
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 8c0d4c9..4ffb4ad 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -46,7 +46,7 @@
 #define INVALID_PCR(a) (((a) < 0) || \
 	(a) >= (FIELD_SIZEOF(struct integrity_iint_cache, measured_pcrs) * 8))
 
-int ima_policy_flag;
+/* used only during policy initialization and policy change */
 static int temp_ima_appraise;
 
 #ifdef CONFIG_IMA_PER_NAMESPACE
@@ -66,6 +66,7 @@ struct ima_ns_policy ima_initial_namespace_policy = {
 			   .ima_appraise = 0
 	   };
 
+
 #define MAX_LSM_RULES 6
 enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
 	LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
@@ -166,11 +167,12 @@ static struct ima_rule_entry default_appraise_rules[] = {
 #endif
 };
 
+/* used only during policy setup of the initial namespace */
 static LIST_HEAD(ima_default_rules);
-static LIST_HEAD(ima_policy_rules);
+/* used during policy setting and cleaned up for the next policy setting */
 static LIST_HEAD(ima_temp_rules);
-static struct list_head *ima_rules;
 
+/* only used during setup of the initial namespace policy */
 static int ima_policy __initdata;
 
 static int __init default_measure_policy_setup(char *str)
@@ -268,13 +270,14 @@ struct ima_ns_policy *ima_get_current_namespace_policy(void)
  * the reloaded LSM policy.  We assume the rules still exist; and BUG_ON() if
  * they don't.
  */
-static void ima_lsm_update_rules(void)
+static void ima_lsm_update_rules(struct ima_ns_policy *ins)
 {
 	struct ima_rule_entry *entry;
 	int result;
 	int i;
 
-	list_for_each_entry(entry, &ima_policy_rules, list) {
+	rcu_read_lock();
+	list_for_each_entry_rcu(entry, &ins->ima_policy_rules, list) {
 		for (i = 0; i < MAX_LSM_RULES; i++) {
 			if (!entry->lsm[i].rule)
 				continue;
@@ -285,6 +288,7 @@ static void ima_lsm_update_rules(void)
 			BUG_ON(!entry->lsm[i].rule);
 		}
 	}
+	rcu_read_unlock();
 }
 
 /**
@@ -297,7 +301,7 @@ static void ima_lsm_update_rules(void)
  * Returns true on rule match, false on failure.
  */
 static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
-			    enum ima_hooks func, int mask)
+			    enum ima_hooks func, int mask, struct ima_ns_policy *ins)
 {
 	struct task_struct *tsk = current;
 	const struct cred *cred = current_cred();
@@ -365,7 +369,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
 		}
 		if ((rc < 0) && (!retried)) {
 			retried = 1;
-			ima_lsm_update_rules();
+			ima_lsm_update_rules(ins);
 			goto retry;
 		}
 		if (!rc)
@@ -412,18 +416,18 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
  * than writes so ima_match_policy() is classical RCU candidate.
  */
 int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
-		     int flags, int *pcr)
+		     int flags, int *pcr, struct ima_ns_policy *ins)
 {
 	struct ima_rule_entry *entry;
 	int action = 0, actmask = flags | (flags << 1);
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(entry, ima_rules, list) {
+	list_for_each_entry_rcu(entry, ins->ima_rules, list) {
 
 		if (!(entry->action & actmask))
 			continue;
 
-		if (!ima_match_rules(entry, inode, func, mask))
+		if (!ima_match_rules(entry, inode, func, mask, ins))
 			continue;
 
 		action |= entry->flags & IMA_ACTION_FLAGS;
@@ -454,18 +458,20 @@ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
  * out of a function or not call the function in the first place
  * can be made earlier.
  */
-void ima_update_policy_flag(void)
+void ima_update_policy_flag(struct ima_ns_policy *ins)
 {
 	struct ima_rule_entry *entry;
 
-	list_for_each_entry(entry, ima_rules, list) {
+	rcu_read_lock();
+	list_for_each_entry_rcu(entry, ins->ima_rules, list) {
 		if (entry->action & IMA_DO_MASK)
-			ima_policy_flag |= entry->action;
+			ins->ima_policy_flag |= entry->action;
 	}
+	rcu_read_unlock();
 
-	ima_appraise |= temp_ima_appraise;
-	if (!ima_appraise)
-		ima_policy_flag &= ~IMA_APPRAISE;
+	ins->ima_appraise |= temp_ima_appraise;
+	if (!ins->ima_appraise)
+		ins->ima_policy_flag &= ~IMA_APPRAISE;
 }
 
 /**
@@ -477,6 +483,7 @@ void ima_update_policy_flag(void)
 void __init ima_init_policy(void)
 {
 	int i, measure_entries, appraise_entries;
+	struct ima_ns_policy *ins;
 
 	/* if !ima_policy set entries = 0 so we load NO default rules */
 	measure_entries = ima_policy ? ARRAY_SIZE(dont_measure_rules) : 0;
@@ -507,8 +514,13 @@ void __init ima_init_policy(void)
 			temp_ima_appraise |= IMA_APPRAISE_POLICY;
 	}
 
-	ima_rules = &ima_default_rules;
-	ima_update_policy_flag();
+	ins = &ima_initial_namespace_policy;
+
+	ins->ima_rules = &ima_default_rules;
+	ins->ima_appraise = ima_appraise;
+
+	ima_update_policy_flag(ins);
+	temp_ima_appraise = 0;
 }
 
 /* Make sure we have a valid policy, at least containing some rules. */
@@ -530,14 +542,14 @@ 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_ns_policy *ins)
 {
 	struct list_head *first, *last, *policy;
 
 	/* append current policy with the new rules */
 	first = (&ima_temp_rules)->next;
 	last = (&ima_temp_rules)->prev;
-	policy = &ima_policy_rules;
+	policy = &ins->ima_policy_rules;
 
 	synchronize_rcu();
 
@@ -549,11 +561,14 @@ void ima_update_policy(void)
 	/* prepare for the next policy rules addition */
 	INIT_LIST_HEAD(&ima_temp_rules);
 
-	if (ima_rules != policy) {
-		ima_policy_flag = 0;
-		ima_rules = policy;
+	if (ins->ima_rules != policy) {
+		ins->ima_policy_flag = 0;
+		ins->ima_rules = policy;
+		ins->ima_appraise = ima_appraise;
 	}
-	ima_update_policy_flag();
+
+	ima_update_policy_flag(ins);
+	temp_ima_appraise = 0;
 }
 
 enum {
@@ -964,6 +979,7 @@ void ima_free_policy_rules(struct list_head *policy_rules)
 void ima_delete_rules(void)
 {
 	temp_ima_appraise = 0;
+
 	ima_free_policy_rules(&ima_temp_rules);
 }
 
@@ -1002,28 +1018,49 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos)
 {
 	loff_t l = *pos;
 	struct ima_rule_entry *entry;
+	struct ima_ns_policy *ins;
+
+	ima_namespace_lock();
+	ins = ima_get_namespace_policy_from_inode(m->file->f_inode);
+	if (!ins) {
+		ima_namespace_unlock();
+		return NULL;
+	}
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(entry, ima_rules, list) {
+	list_for_each_entry_rcu(entry, ins->ima_rules, list) {
 		if (!l--) {
 			rcu_read_unlock();
+			ima_namespace_unlock();
 			return entry;
 		}
 	}
 	rcu_read_unlock();
+	ima_namespace_unlock();
 	return NULL;
 }
 
 void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos)
 {
 	struct ima_rule_entry *entry = v;
+	struct ima_ns_policy *ins;
+	void *p;
+
+	ima_namespace_lock();
+	ins = ima_get_namespace_policy_from_inode(m->file->f_inode);
+	if (!ins) {
+		ima_namespace_unlock();
+		return NULL;
+	}
 
 	rcu_read_lock();
 	entry = list_entry_rcu(entry->list.next, struct ima_rule_entry, list);
 	rcu_read_unlock();
 	(*pos)++;
 
-	return (&entry->list == ima_rules) ? NULL : entry;
+	p = (&entry->list == ins->ima_rules) ? NULL : entry;
+	ima_namespace_unlock();
+	return p;
 }
 
 void ima_policy_stop(struct seq_file *m, void *v)
@@ -1082,6 +1119,16 @@ int ima_policy_show(struct seq_file *m, void *v)
 	struct ima_rule_entry *entry = v;
 	int i;
 	char tbuf[64] = {0,};
+	struct ima_ns_policy *ins;
+
+	ima_namespace_lock();
+	ins = ima_get_namespace_policy_from_inode(m->file->f_inode);
+	if (!ins) {
+		/* this namespace was release and the policy entry is not valid
+		 * anymore */
+		ima_namespace_unlock();
+		return 0;
+	}
 
 	rcu_read_lock();
 
@@ -1184,6 +1231,7 @@ int ima_policy_show(struct seq_file *m, void *v)
 		seq_puts(m, "permit_directio ");
 	rcu_read_unlock();
 	seq_puts(m, "\n");
+	ima_namespace_unlock();
 	return 0;
 }
 #endif	/* CONFIG_IMA_READ_POLICY */
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the Linux-security-module-archive mailing list