IMA: explicit IMA i_flag to remove global lock on inode_delete
authorEric Paris <eparis@redhat.com>
Mon, 25 Oct 2010 18:42:19 +0000 (14:42 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Oct 2010 18:37:19 +0000 (11:37 -0700)
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>
include/linux/fs.h
security/integrity/ima/ima_iint.c
security/integrity/ima/ima_main.c

index 01e3a0047fed244b2ee4e71712a562b035f99ee7..bb77843de9d65630799fd1e4d413a58037504db8 100644 (file)
@@ -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. */
index 969a1c1cb333ebf156767a9aed8f2cae3413fef4..c442e47b67853099e776c4e5b95dd3fa321183ae 100644 (file)
@@ -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);
 }
 
index 1dccafef7494b6e2d4986de522edb7cf63b2680f..60dd61527b1e0881eb1818e97cde3034b0d2d026 100644 (file)
@@ -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)