diff options
author | Eric Paris <eparis@redhat.com> | 2009-12-04 15:47:52 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-12-16 12:16:46 -0500 |
commit | 9353384ec8128cb443463016bbabb44ca857ff52 (patch) | |
tree | 411ff22e85868aea1575d8b133187def3b0e0498 | |
parent | ec29ea544b1ce204ba3575ba05fccf3069d00c3f (diff) |
ima: only insert at inode creation time
iints are supposed to be allocated when an inode is allocated (during
security_inode_alloc()) But we have code which will attempt to allocate
an iint during measurement calls. If we couldn't allocate the iint and we
cared, we should have died during security_inode_alloc(). Not make the
code more complex and less efficient.
Signed-off-by: Eric Paris <eparis@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | security/integrity/ima/ima.h | 1 | ||||
-rw-r--r-- | security/integrity/ima/ima_iint.c | 71 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 8 |
3 files changed, 14 insertions, 66 deletions
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 165eb5397ea5..349aabc83297 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -128,7 +128,6 @@ void ima_template_show(struct seq_file *m, void *e, | |||
128 | */ | 128 | */ |
129 | struct ima_iint_cache *ima_iint_insert(struct inode *inode); | 129 | struct ima_iint_cache *ima_iint_insert(struct inode *inode); |
130 | struct ima_iint_cache *ima_iint_find_get(struct inode *inode); | 130 | struct ima_iint_cache *ima_iint_find_get(struct inode *inode); |
131 | struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode); | ||
132 | void ima_iint_delete(struct inode *inode); | 131 | void ima_iint_delete(struct inode *inode); |
133 | void iint_free(struct kref *kref); | 132 | void iint_free(struct kref *kref); |
134 | void iint_rcu_free(struct rcu_head *rcu); | 133 | void iint_rcu_free(struct rcu_head *rcu); |
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c index 4a53f396d422..2f6ab5258b1e 100644 --- a/security/integrity/ima/ima_iint.c +++ b/security/integrity/ima/ima_iint.c | |||
@@ -45,22 +45,21 @@ out: | |||
45 | return iint; | 45 | return iint; |
46 | } | 46 | } |
47 | 47 | ||
48 | /* Allocate memory for the iint associated with the inode | 48 | /** |
49 | * from the iint_cache slab, initialize the iint, and | 49 | * ima_inode_alloc - allocate an iint associated with an inode |
50 | * insert it into the radix tree. | 50 | * @inode: pointer to the inode |
51 | * | ||
52 | * On success return a pointer to the iint; on failure return NULL. | ||
53 | */ | 51 | */ |
54 | struct ima_iint_cache *ima_iint_insert(struct inode *inode) | 52 | int ima_inode_alloc(struct inode *inode) |
55 | { | 53 | { |
56 | struct ima_iint_cache *iint = NULL; | 54 | struct ima_iint_cache *iint = NULL; |
57 | int rc = 0; | 55 | int rc = 0; |
58 | 56 | ||
59 | if (!ima_initialized) | 57 | if (!ima_initialized) |
60 | return iint; | 58 | return 0; |
59 | |||
61 | iint = kmem_cache_alloc(iint_cache, GFP_NOFS); | 60 | iint = kmem_cache_alloc(iint_cache, GFP_NOFS); |
62 | if (!iint) | 61 | if (!iint) |
63 | return iint; | 62 | return -ENOMEM; |
64 | 63 | ||
65 | rc = radix_tree_preload(GFP_NOFS); | 64 | rc = radix_tree_preload(GFP_NOFS); |
66 | if (rc < 0) | 65 | if (rc < 0) |
@@ -70,63 +69,13 @@ struct ima_iint_cache *ima_iint_insert(struct inode *inode) | |||
70 | rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint); | 69 | rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint); |
71 | spin_unlock(&ima_iint_lock); | 70 | spin_unlock(&ima_iint_lock); |
72 | out: | 71 | out: |
73 | if (rc < 0) { | 72 | if (rc < 0) |
74 | kmem_cache_free(iint_cache, iint); | 73 | 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 | |||
87 | /** | ||
88 | * ima_inode_alloc - allocate an iint associated with an inode | ||
89 | * @inode: pointer to the inode | ||
90 | */ | ||
91 | int ima_inode_alloc(struct inode *inode) | ||
92 | { | ||
93 | struct ima_iint_cache *iint; | ||
94 | |||
95 | if (!ima_initialized) | ||
96 | return 0; | ||
97 | |||
98 | iint = ima_iint_insert(inode); | ||
99 | if (!iint) | ||
100 | return -ENOMEM; | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | /* ima_iint_find_insert_get - get the iint associated with an inode | ||
105 | * | ||
106 | * Most insertions are done at inode_alloc, except those allocated | ||
107 | * before late_initcall. When the iint does not exist, allocate it, | ||
108 | * initialize and insert it, and increment the iint refcount. | ||
109 | * | ||
110 | * (Can't initialize at security_initcall before any inodes are | ||
111 | * allocated, got to wait at least until proc_init.) | ||
112 | * | ||
113 | * Return the iint. | ||
114 | */ | ||
115 | struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode) | ||
116 | { | ||
117 | struct ima_iint_cache *iint = NULL; | ||
118 | 74 | ||
119 | iint = ima_iint_find_get(inode); | 75 | radix_tree_preload_end(); |
120 | if (iint) | ||
121 | return iint; | ||
122 | |||
123 | iint = ima_iint_insert(inode); | ||
124 | if (iint) | ||
125 | kref_get(&iint->refcount); | ||
126 | 76 | ||
127 | return iint; | 77 | return rc; |
128 | } | 78 | } |
129 | EXPORT_SYMBOL_GPL(ima_iint_find_insert_get); | ||
130 | 79 | ||
131 | /* iint_free - called when the iint refcount goes to zero */ | 80 | /* iint_free - called when the iint refcount goes to zero */ |
132 | void iint_free(struct kref *kref) | 81 | void iint_free(struct kref *kref) |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index b85e61bcf246..96fafc01e2c7 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -161,7 +161,7 @@ int ima_path_check(struct path *path, int mask, int update_counts) | |||
161 | 161 | ||
162 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 162 | if (!ima_initialized || !S_ISREG(inode->i_mode)) |
163 | return 0; | 163 | return 0; |
164 | iint = ima_iint_find_insert_get(inode); | 164 | iint = ima_iint_find_get(inode); |
165 | if (!iint) | 165 | if (!iint) |
166 | return 0; | 166 | return 0; |
167 | 167 | ||
@@ -219,7 +219,7 @@ static int process_measurement(struct file *file, const unsigned char *filename, | |||
219 | 219 | ||
220 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 220 | if (!ima_initialized || !S_ISREG(inode->i_mode)) |
221 | return 0; | 221 | return 0; |
222 | iint = ima_iint_find_insert_get(inode); | 222 | iint = ima_iint_find_get(inode); |
223 | if (!iint) | 223 | if (!iint) |
224 | return -ENOMEM; | 224 | return -ENOMEM; |
225 | 225 | ||
@@ -255,7 +255,7 @@ void ima_counts_put(struct path *path, int mask) | |||
255 | */ | 255 | */ |
256 | if (!ima_initialized || !inode || !S_ISREG(inode->i_mode)) | 256 | if (!ima_initialized || !inode || !S_ISREG(inode->i_mode)) |
257 | return; | 257 | return; |
258 | iint = ima_iint_find_insert_get(inode); | 258 | iint = ima_iint_find_get(inode); |
259 | if (!iint) | 259 | if (!iint) |
260 | return; | 260 | return; |
261 | 261 | ||
@@ -286,7 +286,7 @@ void ima_counts_get(struct file *file) | |||
286 | 286 | ||
287 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 287 | if (!ima_initialized || !S_ISREG(inode->i_mode)) |
288 | return; | 288 | return; |
289 | iint = ima_iint_find_insert_get(inode); | 289 | iint = ima_iint_find_get(inode); |
290 | if (!iint) | 290 | if (!iint) |
291 | return; | 291 | return; |
292 | mutex_lock(&iint->mutex); | 292 | mutex_lock(&iint->mutex); |