aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity/ima
diff options
context:
space:
mode:
Diffstat (limited to 'security/integrity/ima')
-rw-r--r--security/integrity/ima/ima.h3
-rw-r--r--security/integrity/ima/ima_api.c4
-rw-r--r--security/integrity/ima/ima_iint.c9
-rw-r--r--security/integrity/ima/ima_main.c239
-rw-r--r--security/integrity/ima/ima_policy.c9
5 files changed, 105 insertions, 159 deletions
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index c41afe6639a0..47fb65d1fcbd 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -65,7 +65,6 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
65 const char *cause, int result, int info); 65 const char *cause, int result, int info);
66 66
67/* Internal IMA function definitions */ 67/* Internal IMA function definitions */
68void ima_iintcache_init(void);
69int ima_init(void); 68int ima_init(void);
70void ima_cleanup(void); 69void ima_cleanup(void);
71int ima_fs_init(void); 70int ima_fs_init(void);
@@ -131,7 +130,7 @@ void iint_free(struct kref *kref);
131void iint_rcu_free(struct rcu_head *rcu); 130void iint_rcu_free(struct rcu_head *rcu);
132 131
133/* IMA policy related functions */ 132/* IMA policy related functions */
134enum ima_hooks { PATH_CHECK = 1, FILE_MMAP, BPRM_CHECK }; 133enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK };
135 134
136int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask); 135int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask);
137void ima_init_policy(void); 136void ima_init_policy(void);
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 3cd58b60afd2..2a5e0bcf3887 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -95,12 +95,12 @@ err_out:
95 * ima_must_measure - measure decision based on policy. 95 * ima_must_measure - measure decision based on policy.
96 * @inode: pointer to inode to measure 96 * @inode: pointer to inode to measure
97 * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) 97 * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE)
98 * @function: calling function (PATH_CHECK, BPRM_CHECK, FILE_MMAP) 98 * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP)
99 * 99 *
100 * The policy is defined in terms of keypairs: 100 * The policy is defined in terms of keypairs:
101 * subj=, obj=, type=, func=, mask=, fsmagic= 101 * subj=, obj=, type=, func=, mask=, fsmagic=
102 * subj,obj, and type: are LSM specific. 102 * subj,obj, and type: are LSM specific.
103 * func: PATH_CHECK | BPRM_CHECK | FILE_MMAP 103 * func: FILE_CHECK | BPRM_CHECK | FILE_MMAP
104 * mask: contains the permission mask 104 * mask: contains the permission mask
105 * fsmagic: hex value 105 * fsmagic: hex value
106 * 106 *
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
index fa592ff1ac1c..0d83edcfc402 100644
--- a/security/integrity/ima/ima_iint.c
+++ b/security/integrity/ima/ima_iint.c
@@ -52,9 +52,6 @@ int ima_inode_alloc(struct inode *inode)
52 struct ima_iint_cache *iint = NULL; 52 struct ima_iint_cache *iint = NULL;
53 int rc = 0; 53 int rc = 0;
54 54
55 if (!ima_initialized)
56 return 0;
57
58 iint = kmem_cache_alloc(iint_cache, GFP_NOFS); 55 iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
59 if (!iint) 56 if (!iint)
60 return -ENOMEM; 57 return -ENOMEM;
@@ -118,8 +115,6 @@ void ima_inode_free(struct inode *inode)
118{ 115{
119 struct ima_iint_cache *iint; 116 struct ima_iint_cache *iint;
120 117
121 if (!ima_initialized)
122 return;
123 spin_lock(&ima_iint_lock); 118 spin_lock(&ima_iint_lock);
124 iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode); 119 iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode);
125 spin_unlock(&ima_iint_lock); 120 spin_unlock(&ima_iint_lock);
@@ -141,9 +136,11 @@ static void init_once(void *foo)
141 kref_set(&iint->refcount, 1); 136 kref_set(&iint->refcount, 1);
142} 137}
143 138
144void __init ima_iintcache_init(void) 139static int __init ima_iintcache_init(void)
145{ 140{
146 iint_cache = 141 iint_cache =
147 kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, 142 kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,
148 SLAB_PANIC, init_once); 143 SLAB_PANIC, init_once);
144 return 0;
149} 145}
146security_initcall(ima_iintcache_init);
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index a89f44d5e030..294b005d6520 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -14,7 +14,7 @@
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_file_check.
18 */ 18 */
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/file.h> 20#include <linux/file.h>
@@ -84,6 +84,36 @@ out:
84 return found; 84 return found;
85} 85}
86 86
87/* ima_read_write_check - reflect possible reading/writing errors in the PCR.
88 *
89 * When opening a file for read, if the file is already open for write,
90 * the file could change, resulting in a file measurement error.
91 *
92 * Opening a file for write, if the file is already open for read, results
93 * in a time of measure, time of use (ToMToU) error.
94 *
95 * In either case invalidate the PCR.
96 */
97enum iint_pcr_error { TOMTOU, OPEN_WRITERS };
98static void ima_read_write_check(enum iint_pcr_error error,
99 struct ima_iint_cache *iint,
100 struct inode *inode,
101 const unsigned char *filename)
102{
103 switch (error) {
104 case TOMTOU:
105 if (iint->readcount > 0)
106 ima_add_violation(inode, filename, "invalid_pcr",
107 "ToMToU");
108 break;
109 case OPEN_WRITERS:
110 if (iint->writecount > 0)
111 ima_add_violation(inode, filename, "invalid_pcr",
112 "open_writers");
113 break;
114 }
115}
116
87/* 117/*
88 * Update the counts given an fmode_t 118 * Update the counts given an fmode_t
89 */ 119 */
@@ -99,6 +129,47 @@ static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode)
99} 129}
100 130
101/* 131/*
132 * ima_counts_get - increment file counts
133 *
134 * Maintain read/write counters for all files, but only
135 * invalidate the PCR for measured files:
136 * - Opening a file for write when already open for read,
137 * results in a time of measure, time of use (ToMToU) error.
138 * - Opening a file for read when already open for write,
139 * could result in a file measurement error.
140 *
141 */
142void ima_counts_get(struct file *file)
143{
144 struct dentry *dentry = file->f_path.dentry;
145 struct inode *inode = dentry->d_inode;
146 fmode_t mode = file->f_mode;
147 struct ima_iint_cache *iint;
148 int rc;
149
150 if (!ima_initialized || !S_ISREG(inode->i_mode))
151 return;
152 iint = ima_iint_find_get(inode);
153 if (!iint)
154 return;
155 mutex_lock(&iint->mutex);
156 rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK);
157 if (rc < 0)
158 goto out;
159
160 if (mode & FMODE_WRITE) {
161 ima_read_write_check(TOMTOU, iint, inode, dentry->d_name.name);
162 goto out;
163 }
164 ima_read_write_check(OPEN_WRITERS, iint, inode, dentry->d_name.name);
165out:
166 ima_inc_counts(iint, file->f_mode);
167 mutex_unlock(&iint->mutex);
168
169 kref_put(&iint->refcount, iint_free);
170}
171
172/*
102 * Decrement ima counts 173 * Decrement ima counts
103 */ 174 */
104static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode, 175static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
@@ -153,123 +224,6 @@ void ima_file_free(struct file *file)
153 kref_put(&iint->refcount, iint_free); 224 kref_put(&iint->refcount, iint_free);
154} 225}
155 226
156/* ima_read_write_check - reflect possible reading/writing errors in the PCR.
157 *
158 * When opening a file for read, if the file is already open for write,
159 * the file could change, resulting in a file measurement error.
160 *
161 * Opening a file for write, if the file is already open for read, results
162 * in a time of measure, time of use (ToMToU) error.
163 *
164 * In either case invalidate the PCR.
165 */
166enum iint_pcr_error { TOMTOU, OPEN_WRITERS };
167static void ima_read_write_check(enum iint_pcr_error error,
168 struct ima_iint_cache *iint,
169 struct inode *inode,
170 const unsigned char *filename)
171{
172 switch (error) {
173 case TOMTOU:
174 if (iint->readcount > 0)
175 ima_add_violation(inode, filename, "invalid_pcr",
176 "ToMToU");
177 break;
178 case OPEN_WRITERS:
179 if (iint->writecount > 0)
180 ima_add_violation(inode, filename, "invalid_pcr",
181 "open_writers");
182 break;
183 }
184}
185
186static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
187 const unsigned char *filename)
188{
189 int rc = 0;
190
191 ima_inc_counts(iint, file->f_mode);
192
193 rc = ima_collect_measurement(iint, file);
194 if (!rc)
195 ima_store_measurement(iint, file, filename);
196 return rc;
197}
198
199/**
200 * ima_path_check - based on policy, collect/store measurement.
201 * @path: contains a pointer to the path to be measured
202 * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE
203 *
204 * Measure the file being open for readonly, based on the
205 * ima_must_measure() policy decision.
206 *
207 * Keep read/write counters for all files, but only
208 * invalidate the PCR for measured files:
209 * - Opening a file for write when already open for read,
210 * results in a time of measure, time of use (ToMToU) error.
211 * - Opening a file for read when already open for write,
212 * could result in a file measurement error.
213 *
214 * Always return 0 and audit dentry_open failures.
215 * (Return code will be based upon measurement appraisal.)
216 */
217int ima_path_check(struct path *path, int mask)
218{
219 struct inode *inode = path->dentry->d_inode;
220 struct ima_iint_cache *iint;
221 struct file *file = NULL;
222 int rc;
223
224 if (!ima_initialized || !S_ISREG(inode->i_mode))
225 return 0;
226 iint = ima_iint_find_get(inode);
227 if (!iint)
228 return 0;
229
230 mutex_lock(&iint->mutex);
231
232 rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK);
233 if (rc < 0)
234 goto out;
235
236 if ((mask & MAY_WRITE) || (mask == 0))
237 ima_read_write_check(TOMTOU, iint, inode,
238 path->dentry->d_name.name);
239
240 if ((mask & (MAY_WRITE | MAY_READ | MAY_EXEC)) != MAY_READ)
241 goto out;
242
243 ima_read_write_check(OPEN_WRITERS, iint, inode,
244 path->dentry->d_name.name);
245 if (!(iint->flags & IMA_MEASURED)) {
246 struct dentry *dentry = dget(path->dentry);
247 struct vfsmount *mnt = mntget(path->mnt);
248
249 file = dentry_open(dentry, mnt, O_RDONLY | O_LARGEFILE,
250 current_cred());
251 if (IS_ERR(file)) {
252 int audit_info = 0;
253
254 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
255 dentry->d_name.name,
256 "add_measurement",
257 "dentry_open failed",
258 1, audit_info);
259 file = NULL;
260 goto out;
261 }
262 rc = get_path_measurement(iint, file, dentry->d_name.name);
263 }
264out:
265 mutex_unlock(&iint->mutex);
266 if (file)
267 fput(file);
268 kref_put(&iint->refcount, iint_free);
269 return 0;
270}
271EXPORT_SYMBOL_GPL(ima_path_check);
272
273static int process_measurement(struct file *file, const unsigned char *filename, 227static int process_measurement(struct file *file, const unsigned char *filename,
274 int mask, int function) 228 int mask, int function)
275{ 229{
@@ -297,33 +251,6 @@ out:
297 return rc; 251 return rc;
298} 252}
299 253
300/*
301 * ima_counts_get - increment file counts
302 *
303 * - for IPC shm and shmat file.
304 * - for nfsd exported files.
305 *
306 * Increment the counts for these files to prevent unnecessary
307 * imbalance messages.
308 */
309void ima_counts_get(struct file *file)
310{
311 struct inode *inode = file->f_dentry->d_inode;
312 struct ima_iint_cache *iint;
313
314 if (!ima_initialized || !S_ISREG(inode->i_mode))
315 return;
316 iint = ima_iint_find_get(inode);
317 if (!iint)
318 return;
319 mutex_lock(&iint->mutex);
320 ima_inc_counts(iint, file->f_mode);
321 mutex_unlock(&iint->mutex);
322
323 kref_put(&iint->refcount, iint_free);
324}
325EXPORT_SYMBOL_GPL(ima_counts_get);
326
327/** 254/**
328 * ima_file_mmap - based on policy, collect/store measurement. 255 * ima_file_mmap - based on policy, collect/store measurement.
329 * @file: pointer to the file to be measured (May be NULL) 256 * @file: pointer to the file to be measured (May be NULL)
@@ -369,11 +296,31 @@ int ima_bprm_check(struct linux_binprm *bprm)
369 return 0; 296 return 0;
370} 297}
371 298
299/**
300 * ima_path_check - based on policy, collect/store measurement.
301 * @file: pointer to the file to be measured
302 * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE
303 *
304 * Measure files based on the ima_must_measure() policy decision.
305 *
306 * Always return 0 and audit dentry_open failures.
307 * (Return code will be based upon measurement appraisal.)
308 */
309int ima_file_check(struct file *file, int mask)
310{
311 int rc;
312
313 rc = process_measurement(file, file->f_dentry->d_name.name,
314 mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
315 FILE_CHECK);
316 return 0;
317}
318EXPORT_SYMBOL_GPL(ima_file_check);
319
372static int __init init_ima(void) 320static int __init init_ima(void)
373{ 321{
374 int error; 322 int error;
375 323
376 ima_iintcache_init();
377 error = ima_init(); 324 error = ima_init();
378 ima_initialized = 1; 325 ima_initialized = 1;
379 return error; 326 return error;
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index e1278399b345..4759d0f99335 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -67,7 +67,7 @@ static struct ima_measure_rule_entry default_rules[] = {
67 .flags = IMA_FUNC | IMA_MASK}, 67 .flags = IMA_FUNC | IMA_MASK},
68 {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC, 68 {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
69 .flags = IMA_FUNC | IMA_MASK}, 69 .flags = IMA_FUNC | IMA_MASK},
70 {.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0, 70 {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = 0,
71 .flags = IMA_FUNC | IMA_MASK | IMA_UID}, 71 .flags = IMA_FUNC | IMA_MASK | IMA_UID},
72}; 72};
73 73
@@ -282,8 +282,11 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
282 break; 282 break;
283 case Opt_func: 283 case Opt_func:
284 audit_log_format(ab, "func=%s ", args[0].from); 284 audit_log_format(ab, "func=%s ", args[0].from);
285 if (strcmp(args[0].from, "PATH_CHECK") == 0) 285 if (strcmp(args[0].from, "FILE_CHECK") == 0)
286 entry->func = PATH_CHECK; 286 entry->func = FILE_CHECK;
287 /* PATH_CHECK is for backwards compat */
288 else if (strcmp(args[0].from, "PATH_CHECK") == 0)
289 entry->func = FILE_CHECK;
287 else if (strcmp(args[0].from, "FILE_MMAP") == 0) 290 else if (strcmp(args[0].from, "FILE_MMAP") == 0)
288 entry->func = FILE_MMAP; 291 entry->func = FILE_MMAP;
289 else if (strcmp(args[0].from, "BPRM_CHECK") == 0) 292 else if (strcmp(args[0].from, "BPRM_CHECK") == 0)