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

From: Guilherme Magalhaes
Date: Thu May 11 2017 - 12:27:30 EST


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@xxxxxxx>
---
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