aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity/ima/ima_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/integrity/ima/ima_main.c')
-rw-r--r--security/integrity/ima/ima_main.c184
1 files changed, 103 insertions, 81 deletions
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index b85e61bcf246..a89f44d5e030 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -13,8 +13,8 @@
13 * License. 13 * License.
14 * 14 *
15 * File: ima_main.c 15 * File: ima_main.c
16 * implements the IMA hooks: ima_bprm_check, ima_file_mmap, 16 * implements the IMA hooks: ima_bprm_check, ima_file_mmap,
17 * and ima_path_check. 17 * and ima_path_check.
18 */ 18 */
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/file.h> 20#include <linux/file.h>
@@ -35,6 +35,100 @@ static int __init hash_setup(char *str)
35} 35}
36__setup("ima_hash=", hash_setup); 36__setup("ima_hash=", hash_setup);
37 37
38struct ima_imbalance {
39 struct hlist_node node;
40 unsigned long fsmagic;
41};
42
43/*
44 * ima_limit_imbalance - emit one imbalance message per filesystem type
45 *
46 * Maintain list of filesystem types that do not measure files properly.
47 * Return false if unknown, true if known.
48 */
49static bool ima_limit_imbalance(struct file *file)
50{
51 static DEFINE_SPINLOCK(ima_imbalance_lock);
52 static HLIST_HEAD(ima_imbalance_list);
53
54 struct super_block *sb = file->f_dentry->d_sb;
55 struct ima_imbalance *entry;
56 struct hlist_node *node;
57 bool found = false;
58
59 rcu_read_lock();
60 hlist_for_each_entry_rcu(entry, node, &ima_imbalance_list, node) {
61 if (entry->fsmagic == sb->s_magic) {
62 found = true;
63 break;
64 }
65 }
66 rcu_read_unlock();
67 if (found)
68 goto out;
69
70 entry = kmalloc(sizeof(*entry), GFP_NOFS);
71 if (!entry)
72 goto out;
73 entry->fsmagic = sb->s_magic;
74 spin_lock(&ima_imbalance_lock);
75 /*
76 * we could have raced and something else might have added this fs
77 * to the list, but we don't really care
78 */
79 hlist_add_head_rcu(&entry->node, &ima_imbalance_list);
80 spin_unlock(&ima_imbalance_lock);
81 printk(KERN_INFO "IMA: unmeasured files on fsmagic: %lX\n",
82 entry->fsmagic);
83out:
84 return found;
85}
86
87/*
88 * Update the counts given an fmode_t
89 */
90static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode)
91{
92 BUG_ON(!mutex_is_locked(&iint->mutex));
93
94 iint->opencount++;
95 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
96 iint->readcount++;
97 if (mode & FMODE_WRITE)
98 iint->writecount++;
99}
100
101/*
102 * Decrement ima counts
103 */
104static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
105 struct file *file)
106{
107 mode_t mode = file->f_mode;
108 BUG_ON(!mutex_is_locked(&iint->mutex));
109
110 iint->opencount--;
111 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
112 iint->readcount--;
113 if (mode & FMODE_WRITE) {
114 iint->writecount--;
115 if (iint->writecount == 0) {
116 if (iint->version != inode->i_version)
117 iint->flags &= ~IMA_MEASURED;
118 }
119 }
120
121 if (((iint->opencount < 0) ||
122 (iint->readcount < 0) ||
123 (iint->writecount < 0)) &&
124 !ima_limit_imbalance(file)) {
125 printk(KERN_INFO "%s: open/free imbalance (r:%ld w:%ld o:%ld)\n",
126 __FUNCTION__, iint->readcount, iint->writecount,
127 iint->opencount);
128 dump_stack();
129 }
130}
131
38/** 132/**
39 * ima_file_free - called on __fput() 133 * ima_file_free - called on __fput()
40 * @file: pointer to file structure being freed 134 * @file: pointer to file structure being freed
@@ -54,29 +148,7 @@ void ima_file_free(struct file *file)
54 return; 148 return;
55 149
56 mutex_lock(&iint->mutex); 150 mutex_lock(&iint->mutex);
57 if (iint->opencount <= 0) { 151 ima_dec_counts(iint, inode, file);
58 printk(KERN_INFO
59 "%s: %s open/free imbalance (r:%ld w:%ld o:%ld f:%ld)\n",
60 __FUNCTION__, file->f_dentry->d_name.name,
61 iint->readcount, iint->writecount,
62 iint->opencount, atomic_long_read(&file->f_count));
63 if (!(iint->flags & IMA_IINT_DUMP_STACK)) {
64 dump_stack();
65 iint->flags |= IMA_IINT_DUMP_STACK;
66 }
67 }
68 iint->opencount--;
69
70 if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
71 iint->readcount--;
72
73 if (file->f_mode & FMODE_WRITE) {
74 iint->writecount--;
75 if (iint->writecount == 0) {
76 if (iint->version != inode->i_version)
77 iint->flags &= ~IMA_MEASURED;
78 }
79 }
80 mutex_unlock(&iint->mutex); 152 mutex_unlock(&iint->mutex);
81 kref_put(&iint->refcount, iint_free); 153 kref_put(&iint->refcount, iint_free);
82} 154}
@@ -116,8 +188,7 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
116{ 188{
117 int rc = 0; 189 int rc = 0;
118 190
119 iint->opencount++; 191 ima_inc_counts(iint, file->f_mode);
120 iint->readcount++;
121 192
122 rc = ima_collect_measurement(iint, file); 193 rc = ima_collect_measurement(iint, file);
123 if (!rc) 194 if (!rc)
@@ -125,15 +196,6 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
125 return rc; 196 return rc;
126} 197}
127 198
128static void ima_update_counts(struct ima_iint_cache *iint, int mask)
129{
130 iint->opencount++;
131 if ((mask & MAY_WRITE) || (mask == 0))
132 iint->writecount++;
133 else if (mask & (MAY_READ | MAY_EXEC))
134 iint->readcount++;
135}
136
137/** 199/**
138 * ima_path_check - based on policy, collect/store measurement. 200 * ima_path_check - based on policy, collect/store measurement.
139 * @path: contains a pointer to the path to be measured 201 * @path: contains a pointer to the path to be measured
@@ -152,7 +214,7 @@ static void ima_update_counts(struct ima_iint_cache *iint, int mask)
152 * Always return 0 and audit dentry_open failures. 214 * Always return 0 and audit dentry_open failures.
153 * (Return code will be based upon measurement appraisal.) 215 * (Return code will be based upon measurement appraisal.)
154 */ 216 */
155int ima_path_check(struct path *path, int mask, int update_counts) 217int ima_path_check(struct path *path, int mask)
156{ 218{
157 struct inode *inode = path->dentry->d_inode; 219 struct inode *inode = path->dentry->d_inode;
158 struct ima_iint_cache *iint; 220 struct ima_iint_cache *iint;
@@ -161,13 +223,11 @@ int ima_path_check(struct path *path, int mask, int update_counts)
161 223
162 if (!ima_initialized || !S_ISREG(inode->i_mode)) 224 if (!ima_initialized || !S_ISREG(inode->i_mode))
163 return 0; 225 return 0;
164 iint = ima_iint_find_insert_get(inode); 226 iint = ima_iint_find_get(inode);
165 if (!iint) 227 if (!iint)
166 return 0; 228 return 0;
167 229
168 mutex_lock(&iint->mutex); 230 mutex_lock(&iint->mutex);
169 if (update_counts)
170 ima_update_counts(iint, mask);
171 231
172 rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK); 232 rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK);
173 if (rc < 0) 233 if (rc < 0)
@@ -219,7 +279,7 @@ static int process_measurement(struct file *file, const unsigned char *filename,
219 279
220 if (!ima_initialized || !S_ISREG(inode->i_mode)) 280 if (!ima_initialized || !S_ISREG(inode->i_mode))
221 return 0; 281 return 0;
222 iint = ima_iint_find_insert_get(inode); 282 iint = ima_iint_find_get(inode);
223 if (!iint) 283 if (!iint)
224 return -ENOMEM; 284 return -ENOMEM;
225 285
@@ -238,39 +298,6 @@ out:
238} 298}
239 299
240/* 300/*
241 * ima_counts_put - decrement file counts
242 *
243 * File counts are incremented in ima_path_check. On file open
244 * error, such as ETXTBSY, decrement the counts to prevent
245 * unnecessary imbalance messages.
246 */
247void ima_counts_put(struct path *path, int mask)
248{
249 struct inode *inode = path->dentry->d_inode;
250 struct ima_iint_cache *iint;
251
252 /* The inode may already have been freed, freeing the iint
253 * with it. Verify the inode is not NULL before dereferencing
254 * it.
255 */
256 if (!ima_initialized || !inode || !S_ISREG(inode->i_mode))
257 return;
258 iint = ima_iint_find_insert_get(inode);
259 if (!iint)
260 return;
261
262 mutex_lock(&iint->mutex);
263 iint->opencount--;
264 if ((mask & MAY_WRITE) || (mask == 0))
265 iint->writecount--;
266 else if (mask & (MAY_READ | MAY_EXEC))
267 iint->readcount--;
268 mutex_unlock(&iint->mutex);
269
270 kref_put(&iint->refcount, iint_free);
271}
272
273/*
274 * ima_counts_get - increment file counts 301 * ima_counts_get - increment file counts
275 * 302 *
276 * - for IPC shm and shmat file. 303 * - for IPC shm and shmat file.
@@ -286,16 +313,11 @@ void ima_counts_get(struct file *file)
286 313
287 if (!ima_initialized || !S_ISREG(inode->i_mode)) 314 if (!ima_initialized || !S_ISREG(inode->i_mode))
288 return; 315 return;
289 iint = ima_iint_find_insert_get(inode); 316 iint = ima_iint_find_get(inode);
290 if (!iint) 317 if (!iint)
291 return; 318 return;
292 mutex_lock(&iint->mutex); 319 mutex_lock(&iint->mutex);
293 iint->opencount++; 320 ima_inc_counts(iint, file->f_mode);
294 if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
295 iint->readcount++;
296
297 if (file->f_mode & FMODE_WRITE)
298 iint->writecount++;
299 mutex_unlock(&iint->mutex); 321 mutex_unlock(&iint->mutex);
300 322
301 kref_put(&iint->refcount, iint_free); 323 kref_put(&iint->refcount, iint_free);