summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/fs.h2
-rw-r--r--security/integrity/ima/ima_iint.c16
-rw-r--r--security/integrity/ima/ima_main.c1
3 files changed, 14 insertions, 5 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 01e3a0047fed..bb77843de9d6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -235,6 +235,7 @@ struct inodes_stat_t {
#define S_NOCMTIME 128 /* Do not update file c/mtime */
#define S_SWAPFILE 256 /* Do not truncate: swapon got its bmaps */
#define S_PRIVATE 512 /* Inode is fs-internal */
+#define S_IMA 1024 /* Inode has an associated IMA struct */
/*
* Note that nosuid etc flags are inode-specific: setting some file-system
@@ -269,6 +270,7 @@ struct inodes_stat_t {
#define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME)
#define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE)
#define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE)
+#define IS_IMA(inode) ((inode)->i_flags & S_IMA)
/* the read-only stuff doesn't really belong here, but any other place is
probably as bad and I don't want to create yet another include file. */
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
index 969a1c1cb333..c442e47b6785 100644
--- a/security/integrity/ima/ima_iint.c
+++ b/security/integrity/ima/ima_iint.c
@@ -59,6 +59,9 @@ struct ima_iint_cache *ima_iint_find(struct inode *inode)
{
struct ima_iint_cache *iint;
+ if (!IS_IMA(inode))
+ return NULL;
+
spin_lock(&ima_iint_lock);
iint = __ima_iint_find(inode);
spin_unlock(&ima_iint_lock);
@@ -91,6 +94,7 @@ int ima_inode_alloc(struct inode *inode)
new_iint->inode = inode;
new_node = &new_iint->rb_node;
+ mutex_lock(&inode->i_mutex); /* i_flags */
spin_lock(&ima_iint_lock);
p = &ima_iint_tree.rb_node;
@@ -107,14 +111,17 @@ int ima_inode_alloc(struct inode *inode)
goto out_err;
}
+ inode->i_flags |= S_IMA;
rb_link_node(new_node, parent, p);
rb_insert_color(new_node, &ima_iint_tree);
spin_unlock(&ima_iint_lock);
+ mutex_unlock(&inode->i_mutex); /* i_flags */
return 0;
out_err:
spin_unlock(&ima_iint_lock);
+ mutex_unlock(&inode->i_mutex); /* i_flags */
iint_free(new_iint);
return rc;
@@ -135,15 +142,14 @@ void ima_inode_free(struct inode *inode)
inode->i_readcount = 0;
+ if (!IS_IMA(inode))
+ return;
+
spin_lock(&ima_iint_lock);
iint = __ima_iint_find(inode);
- if (iint)
- rb_erase(&iint->rb_node, &ima_iint_tree);
+ rb_erase(&iint->rb_node, &ima_iint_tree);
spin_unlock(&ima_iint_lock);
- if (!iint)
- return;
-
iint_free(iint);
}
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 1dccafef7494..60dd61527b1e 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -211,6 +211,7 @@ void ima_file_free(struct file *file)
if (!iint_initialized || !S_ISREG(inode->i_mode))
return;
+
iint = ima_iint_find(inode);
if (iint)