]> git.karo-electronics.de Git - mv-sheeva.git/blob - security/integrity/ima/ima_main.c
integrity: IMA display
[mv-sheeva.git] / security / integrity / ima / ima_main.c
1 /*
2  * Copyright (C) 2005,2006,2007,2008 IBM Corporation
3  *
4  * Authors:
5  * Reiner Sailer <sailer@watson.ibm.com>
6  * Serge Hallyn <serue@us.ibm.com>
7  * Kylene Hall <kylene@us.ibm.com>
8  * Mimi Zohar <zohar@us.ibm.com>
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation, version 2 of the
13  * License.
14  *
15  * File: ima_main.c
16  *             implements the IMA hooks: ima_bprm_check, ima_file_mmap,
17  *             and ima_path_check.
18  */
19 #include <linux/module.h>
20 #include <linux/file.h>
21 #include <linux/binfmts.h>
22 #include <linux/mount.h>
23 #include <linux/mman.h>
24
25 #include "ima.h"
26
27 int ima_initialized;
28
29 char *ima_hash = "sha1";
30 static int __init hash_setup(char *str)
31 {
32         const char *op = "hash_setup";
33         const char *hash = "sha1";
34         int result = 0;
35         int audit_info = 0;
36
37         if (strncmp(str, "md5", 3) == 0) {
38                 hash = "md5";
39                 ima_hash = str;
40         } else if (strncmp(str, "sha1", 4) != 0) {
41                 hash = "invalid_hash_type";
42                 result = 1;
43         }
44         integrity_audit_msg(AUDIT_INTEGRITY_HASH, NULL, NULL, op, hash,
45                             result, audit_info);
46         return 1;
47 }
48 __setup("ima_hash=", hash_setup);
49
50 /**
51  * ima_file_free - called on __fput()
52  * @file: pointer to file structure being freed
53  *
54  * Flag files that changed, based on i_version;
55  * and decrement the iint readcount/writecount.
56  */
57 void ima_file_free(struct file *file)
58 {
59         struct inode *inode = file->f_dentry->d_inode;
60         struct ima_iint_cache *iint;
61
62         if (!ima_initialized || !S_ISREG(inode->i_mode))
63                 return;
64         iint = ima_iint_find_get(inode);
65         if (!iint)
66                 return;
67
68         mutex_lock(&iint->mutex);
69         if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
70                 iint->readcount--;
71
72         if (file->f_mode & FMODE_WRITE) {
73                 iint->writecount--;
74                 if (iint->writecount == 0) {
75                         if (iint->version != inode->i_version)
76                                 iint->flags &= ~IMA_MEASURED;
77                 }
78         }
79         mutex_unlock(&iint->mutex);
80         kref_put(&iint->refcount, iint_free);
81 }
82
83 /* ima_read_write_check - reflect possible reading/writing errors in the PCR.
84  *
85  * When opening a file for read, if the file is already open for write,
86  * the file could change, resulting in a file measurement error.
87  *
88  * Opening a file for write, if the file is already open for read, results
89  * in a time of measure, time of use (ToMToU) error.
90  *
91  * In either case invalidate the PCR.
92  */
93 enum iint_pcr_error { TOMTOU, OPEN_WRITERS };
94 static void ima_read_write_check(enum iint_pcr_error error,
95                                  struct ima_iint_cache *iint,
96                                  struct inode *inode,
97                                  const unsigned char *filename)
98 {
99         switch (error) {
100         case TOMTOU:
101                 if (iint->readcount > 0)
102                         ima_add_violation(inode, filename, "invalid_pcr",
103                                           "ToMToU");
104                 break;
105         case OPEN_WRITERS:
106                 if (iint->writecount > 0)
107                         ima_add_violation(inode, filename, "invalid_pcr",
108                                           "open_writers");
109                 break;
110         }
111 }
112
113 static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
114                                 const unsigned char *filename)
115 {
116         int rc = 0;
117
118         if (IS_ERR(file)) {
119                 pr_info("%s dentry_open failed\n", filename);
120                 return rc;
121         }
122         iint->readcount++;
123
124         rc = ima_collect_measurement(iint, file);
125         if (!rc)
126                 ima_store_measurement(iint, file, filename);
127         return rc;
128 }
129
130 /**
131  * ima_path_check - based on policy, collect/store measurement.
132  * @path: contains a pointer to the path to be measured
133  * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE
134  *
135  * Measure the file being open for readonly, based on the
136  * ima_must_measure() policy decision.
137  *
138  * Keep read/write counters for all files, but only
139  * invalidate the PCR for measured files:
140  *      - Opening a file for write when already open for read,
141  *        results in a time of measure, time of use (ToMToU) error.
142  *      - Opening a file for read when already open for write,
143  *        could result in a file measurement error.
144  *
145  * Return 0 on success, an error code on failure.
146  * (Based on the results of appraise_measurement().)
147  */
148 int ima_path_check(struct path *path, int mask)
149 {
150         struct inode *inode = path->dentry->d_inode;
151         struct ima_iint_cache *iint;
152         struct file *file = NULL;
153         int rc;
154
155         if (!ima_initialized || !S_ISREG(inode->i_mode))
156                 return 0;
157         iint = ima_iint_find_insert_get(inode);
158         if (!iint)
159                 return 0;
160
161         mutex_lock(&iint->mutex);
162         if ((mask & MAY_WRITE) || (mask == 0))
163                 iint->writecount++;
164         else if (mask & (MAY_READ | MAY_EXEC))
165                 iint->readcount++;
166
167         rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK);
168         if (rc < 0)
169                 goto out;
170
171         if ((mask & MAY_WRITE) || (mask == 0))
172                 ima_read_write_check(TOMTOU, iint, inode,
173                                      path->dentry->d_name.name);
174
175         if ((mask & (MAY_WRITE | MAY_READ | MAY_EXEC)) != MAY_READ)
176                 goto out;
177
178         ima_read_write_check(OPEN_WRITERS, iint, inode,
179                              path->dentry->d_name.name);
180         if (!(iint->flags & IMA_MEASURED)) {
181                 struct dentry *dentry = dget(path->dentry);
182                 struct vfsmount *mnt = mntget(path->mnt);
183
184                 file = dentry_open(dentry, mnt, O_RDONLY, current->cred);
185                 rc = get_path_measurement(iint, file, dentry->d_name.name);
186         }
187 out:
188         mutex_unlock(&iint->mutex);
189         if (file)
190                 fput(file);
191         kref_put(&iint->refcount, iint_free);
192         return 0;
193 }
194
195 static int process_measurement(struct file *file, const unsigned char *filename,
196                                int mask, int function)
197 {
198         struct inode *inode = file->f_dentry->d_inode;
199         struct ima_iint_cache *iint;
200         int rc;
201
202         if (!ima_initialized || !S_ISREG(inode->i_mode))
203                 return 0;
204         iint = ima_iint_find_insert_get(inode);
205         if (!iint)
206                 return -ENOMEM;
207
208         mutex_lock(&iint->mutex);
209         rc = ima_must_measure(iint, inode, mask, function);
210         if (rc != 0)
211                 goto out;
212
213         rc = ima_collect_measurement(iint, file);
214         if (!rc)
215                 ima_store_measurement(iint, file, filename);
216 out:
217         mutex_unlock(&iint->mutex);
218         kref_put(&iint->refcount, iint_free);
219         return rc;
220 }
221
222 /**
223  * ima_file_mmap - based on policy, collect/store measurement.
224  * @file: pointer to the file to be measured (May be NULL)
225  * @prot: contains the protection that will be applied by the kernel.
226  *
227  * Measure files being mmapped executable based on the ima_must_measure()
228  * policy decision.
229  *
230  * Return 0 on success, an error code on failure.
231  * (Based on the results of appraise_measurement().)
232  */
233 int ima_file_mmap(struct file *file, unsigned long prot)
234 {
235         int rc;
236
237         if (!file)
238                 return 0;
239         if (prot & PROT_EXEC)
240                 rc = process_measurement(file, file->f_dentry->d_name.name,
241                                          MAY_EXEC, FILE_MMAP);
242         return 0;
243 }
244
245 /**
246  * ima_bprm_check - based on policy, collect/store measurement.
247  * @bprm: contains the linux_binprm structure
248  *
249  * The OS protects against an executable file, already open for write,
250  * from being executed in deny_write_access() and an executable file,
251  * already open for execute, from being modified in get_write_access().
252  * So we can be certain that what we verify and measure here is actually
253  * what is being executed.
254  *
255  * Return 0 on success, an error code on failure.
256  * (Based on the results of appraise_measurement().)
257  */
258 int ima_bprm_check(struct linux_binprm *bprm)
259 {
260         int rc;
261
262         rc = process_measurement(bprm->file, bprm->filename,
263                                  MAY_EXEC, BPRM_CHECK);
264         return 0;
265 }
266
267 static int __init init_ima(void)
268 {
269         int error;
270
271         ima_iintcache_init();
272         error = ima_init();
273         ima_initialized = 1;
274         return error;
275 }
276
277 static void __exit cleanup_ima(void)
278 {
279         ima_cleanup();
280 }
281
282 late_initcall(init_ima);        /* Start IMA after the TPM is available */
283
284 MODULE_DESCRIPTION("Integrity Measurement Architecture");
285 MODULE_LICENSE("GPL");