aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-10-25 14:42:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-26 14:37:18 -0400
commitbc7d2a3e66b40477270c3cbe3b89b47093276e7a (patch)
tree8f0198b8ad455fde11b24e32a2e32c008a5ececb /security/integrity
parenta178d2027d3198b0a04517d764326ab71cd73da2 (diff)
IMA: only allocate iint when needed
IMA always allocates an integrity structure to hold information about every inode, but only needed this structure to track the number of readers and writers currently accessing a given inode. Since that information was moved into struct inode instead of the integrity struct this patch stops allocating the integrity stucture until it is needed. Thus greatly reducing memory usage. 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>
Diffstat (limited to 'security/integrity')
-rw-r--r--security/integrity/ima/ima_main.c94
1 files changed, 64 insertions, 30 deletions
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 2a77b14fee2..5e3229c797f 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -141,33 +141,62 @@ out:
141/* 141/*
142 * Decrement ima counts 142 * Decrement ima counts
143 */ 143 */
144static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode, 144static void ima_dec_counts(struct inode *inode, struct file *file)
145 struct file *file)
146{ 145{
147 mode_t mode = file->f_mode; 146 mode_t mode = file->f_mode;
148 bool dump = false;
149 147
150 BUG_ON(!mutex_is_locked(&iint->mutex));
151 assert_spin_locked(&inode->i_lock); 148 assert_spin_locked(&inode->i_lock);
152 149
153 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { 150 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
154 if (unlikely(inode->i_readcount == 0)) 151 if (unlikely(inode->i_readcount == 0)) {
155 dump = true; 152 if (!ima_limit_imbalance(file)) {
153 printk(KERN_INFO "%s: open/free imbalance (r:%u)\n",
154 __func__, inode->i_readcount);
155 dump_stack();
156 }
157 return;
158 }
156 inode->i_readcount--; 159 inode->i_readcount--;
157 } 160 }
158 if (mode & FMODE_WRITE) { 161}
159 if (atomic_read(&inode->i_writecount) <= 0)
160 dump = true;
161 if (atomic_read(&inode->i_writecount) == 1 &&
162 iint->version != inode->i_version)
163 iint->flags &= ~IMA_MEASURED;
164 }
165 162
166 if (dump && !ima_limit_imbalance(file)) { 163static void ima_check_last_writer(struct ima_iint_cache *iint,
167 printk(KERN_INFO "%s: open/free imbalance (r:%u)\n", 164 struct inode *inode,
168 __func__, inode->i_readcount); 165 struct file *file)
169 dump_stack(); 166{
170 } 167 mode_t mode = file->f_mode;
168
169 BUG_ON(!mutex_is_locked(&iint->mutex));
170 assert_spin_locked(&inode->i_lock);
171
172 if (mode & FMODE_WRITE &&
173 atomic_read(&inode->i_writecount) == 1 &&
174 iint->version != inode->i_version)
175 iint->flags &= ~IMA_MEASURED;
176}
177
178static void ima_file_free_iint(struct ima_iint_cache *iint, struct inode *inode,
179 struct file *file)
180{
181 mutex_lock(&iint->mutex);
182 spin_lock(&inode->i_lock);
183
184 ima_dec_counts(inode, file);
185 ima_check_last_writer(iint, inode, file);
186
187 spin_unlock(&inode->i_lock);
188 mutex_unlock(&iint->mutex);
189
190 kref_put(&iint->refcount, iint_free);
191}
192
193static void ima_file_free_noiint(struct inode *inode, struct file *file)
194{
195 spin_lock(&inode->i_lock);
196
197 ima_dec_counts(inode, file);
198
199 spin_unlock(&inode->i_lock);
171} 200}
172 201
173/** 202/**
@@ -175,7 +204,7 @@ static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
175 * @file: pointer to file structure being freed 204 * @file: pointer to file structure being freed
176 * 205 *
177 * Flag files that changed, based on i_version; 206 * Flag files that changed, based on i_version;
178 * and decrement the iint readcount/writecount. 207 * and decrement the i_readcount.
179 */ 208 */
180void ima_file_free(struct file *file) 209void ima_file_free(struct file *file)
181{ 210{
@@ -185,17 +214,12 @@ void ima_file_free(struct file *file)
185 if (!iint_initialized || !S_ISREG(inode->i_mode)) 214 if (!iint_initialized || !S_ISREG(inode->i_mode))
186 return; 215 return;
187 iint = ima_iint_find_get(inode); 216 iint = ima_iint_find_get(inode);
188 if (!iint)
189 return;
190 217
191 mutex_lock(&iint->mutex); 218 if (iint)
192 spin_lock(&inode->i_lock); 219 ima_file_free_iint(iint, inode, file);
193 220 else
194 ima_dec_counts(iint, inode, file); 221 ima_file_free_noiint(inode, file);
195 222
196 spin_unlock(&inode->i_lock);
197 mutex_unlock(&iint->mutex);
198 kref_put(&iint->refcount, iint_free);
199} 223}
200 224
201static int process_measurement(struct file *file, const unsigned char *filename, 225static int process_measurement(struct file *file, const unsigned char *filename,
@@ -207,11 +231,21 @@ static int process_measurement(struct file *file, const unsigned char *filename,
207 231
208 if (!ima_initialized || !S_ISREG(inode->i_mode)) 232 if (!ima_initialized || !S_ISREG(inode->i_mode))
209 return 0; 233 return 0;
234
235 rc = ima_must_measure(NULL, inode, mask, function);
236 if (rc != 0)
237 return rc;
238retry:
210 iint = ima_iint_find_get(inode); 239 iint = ima_iint_find_get(inode);
211 if (!iint) 240 if (!iint) {
212 return -ENOMEM; 241 rc = ima_inode_alloc(inode);
242 if (!rc || rc == -EEXIST)
243 goto retry;
244 return rc;
245 }
213 246
214 mutex_lock(&iint->mutex); 247 mutex_lock(&iint->mutex);
248
215 rc = ima_must_measure(iint, inode, mask, function); 249 rc = ima_must_measure(iint, inode, mask, function);
216 if (rc != 0) 250 if (rc != 0)
217 goto out; 251 goto out;