summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-10-25 22:42:19 +0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-26 22:37:19 +0400
commit196f518128d2ee6e0028b50e6fec0313640db142 (patch)
tree43a1d76bee477dbaa682233979e86f58a98369f0
parent64c62f06bef8314a64d3189cb9c78062d54169b3 (diff)
downloadlinux-196f518128d2ee6e0028b50e6fec0313640db142.tar.xz
IMA: explicit IMA i_flag to remove global lock on inode_delete
Currently for every removed inode IMA must take a global lock and search the IMA rbtree looking for an associated integrity structure. Instead we explicitly mark an inode when we add an integrity structure so we only have to take the global lock and do the removal if it exists. Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-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)