aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity/ima/ima_iint.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/integrity/ima/ima_iint.c')
-rw-r--r--security/integrity/ima/ima_iint.c86
1 files changed, 14 insertions, 72 deletions
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
index a4e2b1dac943..2c744d488014 100644
--- a/security/integrity/ima/ima_iint.c
+++ b/security/integrity/ima/ima_iint.c
@@ -14,13 +14,12 @@
14 * - cache integrity information associated with an inode 14 * - cache integrity information associated with an inode
15 * using a radix tree. 15 * using a radix tree.
16 */ 16 */
17#include <linux/slab.h>
17#include <linux/module.h> 18#include <linux/module.h>
18#include <linux/spinlock.h> 19#include <linux/spinlock.h>
19#include <linux/radix-tree.h> 20#include <linux/radix-tree.h>
20#include "ima.h" 21#include "ima.h"
21 22
22#define ima_iint_delete ima_inode_free
23
24RADIX_TREE(ima_iint_store, GFP_ATOMIC); 23RADIX_TREE(ima_iint_store, GFP_ATOMIC);
25DEFINE_SPINLOCK(ima_iint_lock); 24DEFINE_SPINLOCK(ima_iint_lock);
26 25
@@ -45,22 +44,18 @@ out:
45 return iint; 44 return iint;
46} 45}
47 46
48/* Allocate memory for the iint associated with the inode 47/**
49 * from the iint_cache slab, initialize the iint, and 48 * ima_inode_alloc - allocate an iint associated with an inode
50 * insert it into the radix tree. 49 * @inode: pointer to the inode
51 *
52 * On success return a pointer to the iint; on failure return NULL.
53 */ 50 */
54struct ima_iint_cache *ima_iint_insert(struct inode *inode) 51int ima_inode_alloc(struct inode *inode)
55{ 52{
56 struct ima_iint_cache *iint = NULL; 53 struct ima_iint_cache *iint = NULL;
57 int rc = 0; 54 int rc = 0;
58 55
59 if (!ima_initialized)
60 return iint;
61 iint = kmem_cache_alloc(iint_cache, GFP_NOFS); 56 iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
62 if (!iint) 57 if (!iint)
63 return iint; 58 return -ENOMEM;
64 59
65 rc = radix_tree_preload(GFP_NOFS); 60 rc = radix_tree_preload(GFP_NOFS);
66 if (rc < 0) 61 if (rc < 0)
@@ -69,67 +64,14 @@ struct ima_iint_cache *ima_iint_insert(struct inode *inode)
69 spin_lock(&ima_iint_lock); 64 spin_lock(&ima_iint_lock);
70 rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint); 65 rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint);
71 spin_unlock(&ima_iint_lock); 66 spin_unlock(&ima_iint_lock);
67 radix_tree_preload_end();
72out: 68out:
73 if (rc < 0) { 69 if (rc < 0)
74 kmem_cache_free(iint_cache, iint); 70 kmem_cache_free(iint_cache, iint);
75 if (rc == -EEXIST) {
76 spin_lock(&ima_iint_lock);
77 iint = radix_tree_lookup(&ima_iint_store,
78 (unsigned long)inode);
79 spin_unlock(&ima_iint_lock);
80 } else
81 iint = NULL;
82 }
83 radix_tree_preload_end();
84 return iint;
85}
86 71
87/** 72 return rc;
88 * ima_inode_alloc - allocate an iint associated with an inode
89 * @inode: pointer to the inode
90 *
91 * Return 0 on success, 1 on failure.
92 */
93int ima_inode_alloc(struct inode *inode)
94{
95 struct ima_iint_cache *iint;
96
97 if (!ima_initialized)
98 return 0;
99
100 iint = ima_iint_insert(inode);
101 if (!iint)
102 return 1;
103 return 0;
104} 73}
105 74
106/* ima_iint_find_insert_get - get the iint associated with an inode
107 *
108 * Most insertions are done at inode_alloc, except those allocated
109 * before late_initcall. When the iint does not exist, allocate it,
110 * initialize and insert it, and increment the iint refcount.
111 *
112 * (Can't initialize at security_initcall before any inodes are
113 * allocated, got to wait at least until proc_init.)
114 *
115 * Return the iint.
116 */
117struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode)
118{
119 struct ima_iint_cache *iint = NULL;
120
121 iint = ima_iint_find_get(inode);
122 if (iint)
123 return iint;
124
125 iint = ima_iint_insert(inode);
126 if (iint)
127 kref_get(&iint->refcount);
128
129 return iint;
130}
131EXPORT_SYMBOL_GPL(ima_iint_find_insert_get);
132
133/* iint_free - called when the iint refcount goes to zero */ 75/* iint_free - called when the iint refcount goes to zero */
134void iint_free(struct kref *kref) 76void iint_free(struct kref *kref)
135{ 77{
@@ -164,17 +106,15 @@ void iint_rcu_free(struct rcu_head *rcu_head)
164} 106}
165 107
166/** 108/**
167 * ima_iint_delete - called on integrity_inode_free 109 * ima_inode_free - called on security_inode_free
168 * @inode: pointer to the inode 110 * @inode: pointer to the inode
169 * 111 *
170 * Free the integrity information(iint) associated with an inode. 112 * Free the integrity information(iint) associated with an inode.
171 */ 113 */
172void ima_iint_delete(struct inode *inode) 114void ima_inode_free(struct inode *inode)
173{ 115{
174 struct ima_iint_cache *iint; 116 struct ima_iint_cache *iint;
175 117
176 if (!ima_initialized)
177 return;
178 spin_lock(&ima_iint_lock); 118 spin_lock(&ima_iint_lock);
179 iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode); 119 iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode);
180 spin_unlock(&ima_iint_lock); 120 spin_unlock(&ima_iint_lock);
@@ -196,9 +136,11 @@ static void init_once(void *foo)
196 kref_set(&iint->refcount, 1); 136 kref_set(&iint->refcount, 1);
197} 137}
198 138
199void __init ima_iintcache_init(void) 139static int __init ima_iintcache_init(void)
200{ 140{
201 iint_cache = 141 iint_cache =
202 kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, 142 kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,
203 SLAB_PANIC, init_once); 143 SLAB_PANIC, init_once);
144 return 0;
204} 145}
146security_initcall(ima_iintcache_init);