aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity
diff options
context:
space:
mode:
Diffstat (limited to 'security/integrity')
-rw-r--r--security/integrity/Kconfig7
-rw-r--r--security/integrity/Makefile12
-rw-r--r--security/integrity/evm/Kconfig13
-rw-r--r--security/integrity/evm/Makefile7
-rw-r--r--security/integrity/evm/evm.h38
-rw-r--r--security/integrity/evm/evm_crypto.c216
-rw-r--r--security/integrity/evm/evm_main.c384
-rw-r--r--security/integrity/evm/evm_posix_acl.c26
-rw-r--r--security/integrity/evm/evm_secfs.c108
-rw-r--r--security/integrity/iint.c172
-rw-r--r--security/integrity/ima/Kconfig1
-rw-r--r--security/integrity/ima/Makefile2
-rw-r--r--security/integrity/ima/ima.h30
-rw-r--r--security/integrity/ima/ima_api.c7
-rw-r--r--security/integrity/ima/ima_fs.c2
-rw-r--r--security/integrity/ima/ima_iint.c169
-rw-r--r--security/integrity/ima/ima_main.c13
-rw-r--r--security/integrity/integrity.h50
18 files changed, 1056 insertions, 201 deletions
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
new file mode 100644
index 000000000000..4bf00acf7937
--- /dev/null
+++ b/security/integrity/Kconfig
@@ -0,0 +1,7 @@
1#
2config INTEGRITY
3 def_bool y
4 depends on IMA || EVM
5
6source security/integrity/ima/Kconfig
7source security/integrity/evm/Kconfig
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
new file mode 100644
index 000000000000..0ae44aea6516
--- /dev/null
+++ b/security/integrity/Makefile
@@ -0,0 +1,12 @@
1#
2# Makefile for caching inode integrity data (iint)
3#
4
5obj-$(CONFIG_INTEGRITY) += integrity.o
6
7integrity-y := iint.o
8
9subdir-$(CONFIG_IMA) += ima
10obj-$(CONFIG_IMA) += ima/built-in.o
11subdir-$(CONFIG_EVM) += evm
12obj-$(CONFIG_EVM) += evm/built-in.o
diff --git a/security/integrity/evm/Kconfig b/security/integrity/evm/Kconfig
new file mode 100644
index 000000000000..afbb59dd262d
--- /dev/null
+++ b/security/integrity/evm/Kconfig
@@ -0,0 +1,13 @@
1config EVM
2 boolean "EVM support"
3 depends on SECURITY && KEYS && (TRUSTED_KEYS=y || TRUSTED_KEYS=n)
4 select CRYPTO_HMAC
5 select CRYPTO_MD5
6 select CRYPTO_SHA1
7 select ENCRYPTED_KEYS
8 default n
9 help
10 EVM protects a file's security extended attributes against
11 integrity attacks.
12
13 If you are unsure how to answer this question, answer N.
diff --git a/security/integrity/evm/Makefile b/security/integrity/evm/Makefile
new file mode 100644
index 000000000000..7393c415a066
--- /dev/null
+++ b/security/integrity/evm/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for building the Extended Verification Module(EVM)
3#
4obj-$(CONFIG_EVM) += evm.o
5
6evm-y := evm_main.o evm_crypto.o evm_secfs.o
7evm-$(CONFIG_FS_POSIX_ACL) += evm_posix_acl.o
diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h
new file mode 100644
index 000000000000..d320f5197437
--- /dev/null
+++ b/security/integrity/evm/evm.h
@@ -0,0 +1,38 @@
1/*
2 * Copyright (C) 2005-2010 IBM Corporation
3 *
4 * Authors:
5 * Mimi Zohar <zohar@us.ibm.com>
6 * Kylene Hall <kjhall@us.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, version 2 of the License.
11 *
12 * File: evm.h
13 *
14 */
15#include <linux/xattr.h>
16#include <linux/security.h>
17#include "../integrity.h"
18
19extern int evm_initialized;
20extern char *evm_hmac;
21
22extern struct crypto_shash *hmac_tfm;
23
24/* List of EVM protected security xattrs */
25extern char *evm_config_xattrnames[];
26
27extern int evm_init_key(void);
28extern int evm_update_evmxattr(struct dentry *dentry,
29 const char *req_xattr_name,
30 const char *req_xattr_value,
31 size_t req_xattr_value_len);
32extern int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
33 const char *req_xattr_value,
34 size_t req_xattr_value_len, char *digest);
35extern int evm_init_hmac(struct inode *inode, const struct xattr *xattr,
36 char *hmac_val);
37extern int evm_init_secfs(void);
38extern void evm_cleanup_secfs(void);
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
new file mode 100644
index 000000000000..5dd5b140242c
--- /dev/null
+++ b/security/integrity/evm/evm_crypto.c
@@ -0,0 +1,216 @@
1/*
2 * Copyright (C) 2005-2010 IBM Corporation
3 *
4 * Authors:
5 * Mimi Zohar <zohar@us.ibm.com>
6 * Kylene Hall <kjhall@us.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, version 2 of the License.
11 *
12 * File: evm_crypto.c
13 * Using root's kernel master key (kmk), calculate the HMAC
14 */
15
16#include <linux/module.h>
17#include <linux/crypto.h>
18#include <linux/xattr.h>
19#include <keys/encrypted-type.h>
20#include <crypto/hash.h>
21#include "evm.h"
22
23#define EVMKEY "evm-key"
24#define MAX_KEY_SIZE 128
25static unsigned char evmkey[MAX_KEY_SIZE];
26static int evmkey_len = MAX_KEY_SIZE;
27
28struct crypto_shash *hmac_tfm;
29
30static struct shash_desc *init_desc(void)
31{
32 int rc;
33 struct shash_desc *desc;
34
35 if (hmac_tfm == NULL) {
36 hmac_tfm = crypto_alloc_shash(evm_hmac, 0, CRYPTO_ALG_ASYNC);
37 if (IS_ERR(hmac_tfm)) {
38 pr_err("Can not allocate %s (reason: %ld)\n",
39 evm_hmac, PTR_ERR(hmac_tfm));
40 rc = PTR_ERR(hmac_tfm);
41 hmac_tfm = NULL;
42 return ERR_PTR(rc);
43 }
44 }
45
46 desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac_tfm),
47 GFP_KERNEL);
48 if (!desc)
49 return ERR_PTR(-ENOMEM);
50
51 desc->tfm = hmac_tfm;
52 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
53
54 rc = crypto_shash_setkey(hmac_tfm, evmkey, evmkey_len);
55 if (rc)
56 goto out;
57 rc = crypto_shash_init(desc);
58out:
59 if (rc) {
60 kfree(desc);
61 return ERR_PTR(rc);
62 }
63 return desc;
64}
65
66/* Protect against 'cutting & pasting' security.evm xattr, include inode
67 * specific info.
68 *
69 * (Additional directory/file metadata needs to be added for more complete
70 * protection.)
71 */
72static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
73 char *digest)
74{
75 struct h_misc {
76 unsigned long ino;
77 __u32 generation;
78 uid_t uid;
79 gid_t gid;
80 umode_t mode;
81 } hmac_misc;
82
83 memset(&hmac_misc, 0, sizeof hmac_misc);
84 hmac_misc.ino = inode->i_ino;
85 hmac_misc.generation = inode->i_generation;
86 hmac_misc.uid = inode->i_uid;
87 hmac_misc.gid = inode->i_gid;
88 hmac_misc.mode = inode->i_mode;
89 crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof hmac_misc);
90 crypto_shash_final(desc, digest);
91}
92
93/*
94 * Calculate the HMAC value across the set of protected security xattrs.
95 *
96 * Instead of retrieving the requested xattr, for performance, calculate
97 * the hmac using the requested xattr value. Don't alloc/free memory for
98 * each xattr, but attempt to re-use the previously allocated memory.
99 */
100int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
101 const char *req_xattr_value, size_t req_xattr_value_len,
102 char *digest)
103{
104 struct inode *inode = dentry->d_inode;
105 struct shash_desc *desc;
106 char **xattrname;
107 size_t xattr_size = 0;
108 char *xattr_value = NULL;
109 int error;
110 int size;
111
112 if (!inode->i_op || !inode->i_op->getxattr)
113 return -EOPNOTSUPP;
114 desc = init_desc();
115 if (IS_ERR(desc))
116 return PTR_ERR(desc);
117
118 error = -ENODATA;
119 for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
120 if ((req_xattr_name && req_xattr_value)
121 && !strcmp(*xattrname, req_xattr_name)) {
122 error = 0;
123 crypto_shash_update(desc, (const u8 *)req_xattr_value,
124 req_xattr_value_len);
125 continue;
126 }
127 size = vfs_getxattr_alloc(dentry, *xattrname,
128 &xattr_value, xattr_size, GFP_NOFS);
129 if (size == -ENOMEM) {
130 error = -ENOMEM;
131 goto out;
132 }
133 if (size < 0)
134 continue;
135
136 error = 0;
137 xattr_size = size;
138 crypto_shash_update(desc, (const u8 *)xattr_value, xattr_size);
139 }
140 hmac_add_misc(desc, inode, digest);
141
142out:
143 kfree(xattr_value);
144 kfree(desc);
145 return error;
146}
147
148/*
149 * Calculate the hmac and update security.evm xattr
150 *
151 * Expects to be called with i_mutex locked.
152 */
153int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
154 const char *xattr_value, size_t xattr_value_len)
155{
156 struct inode *inode = dentry->d_inode;
157 struct evm_ima_xattr_data xattr_data;
158 int rc = 0;
159
160 rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
161 xattr_value_len, xattr_data.digest);
162 if (rc == 0) {
163 xattr_data.type = EVM_XATTR_HMAC;
164 rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
165 &xattr_data,
166 sizeof(xattr_data), 0);
167 }
168 else if (rc == -ENODATA)
169 rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM);
170 return rc;
171}
172
173int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
174 char *hmac_val)
175{
176 struct shash_desc *desc;
177
178 desc = init_desc();
179 if (IS_ERR(desc)) {
180 printk(KERN_INFO "init_desc failed\n");
181 return PTR_ERR(desc);
182 }
183
184 crypto_shash_update(desc, lsm_xattr->value, lsm_xattr->value_len);
185 hmac_add_misc(desc, inode, hmac_val);
186 kfree(desc);
187 return 0;
188}
189
190/*
191 * Get the key from the TPM for the SHA1-HMAC
192 */
193int evm_init_key(void)
194{
195 struct key *evm_key;
196 struct encrypted_key_payload *ekp;
197 int rc = 0;
198
199 evm_key = request_key(&key_type_encrypted, EVMKEY, NULL);
200 if (IS_ERR(evm_key))
201 return -ENOENT;
202
203 down_read(&evm_key->sem);
204 ekp = evm_key->payload.data;
205 if (ekp->decrypted_datalen > MAX_KEY_SIZE) {
206 rc = -EINVAL;
207 goto out;
208 }
209 memcpy(evmkey, ekp->decrypted_data, ekp->decrypted_datalen);
210out:
211 /* burn the original key contents */
212 memset(ekp->decrypted_data, 0, ekp->decrypted_datalen);
213 up_read(&evm_key->sem);
214 key_put(evm_key);
215 return rc;
216}
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
new file mode 100644
index 000000000000..92d3d99a9f7b
--- /dev/null
+++ b/security/integrity/evm/evm_main.c
@@ -0,0 +1,384 @@
1/*
2 * Copyright (C) 2005-2010 IBM Corporation
3 *
4 * Author:
5 * Mimi Zohar <zohar@us.ibm.com>
6 * Kylene Hall <kjhall@us.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, version 2 of the License.
11 *
12 * File: evm_main.c
13 * implements evm_inode_setxattr, evm_inode_post_setxattr,
14 * evm_inode_removexattr, and evm_verifyxattr
15 */
16
17#include <linux/module.h>
18#include <linux/crypto.h>
19#include <linux/xattr.h>
20#include <linux/integrity.h>
21#include <linux/evm.h>
22#include <crypto/hash.h>
23#include "evm.h"
24
25int evm_initialized;
26
27char *evm_hmac = "hmac(sha1)";
28
29char *evm_config_xattrnames[] = {
30#ifdef CONFIG_SECURITY_SELINUX
31 XATTR_NAME_SELINUX,
32#endif
33#ifdef CONFIG_SECURITY_SMACK
34 XATTR_NAME_SMACK,
35#endif
36 XATTR_NAME_CAPS,
37 NULL
38};
39
40static int evm_fixmode;
41static int __init evm_set_fixmode(char *str)
42{
43 if (strncmp(str, "fix", 3) == 0)
44 evm_fixmode = 1;
45 return 0;
46}
47__setup("evm=", evm_set_fixmode);
48
49/*
50 * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr
51 *
52 * Compute the HMAC on the dentry's protected set of extended attributes
53 * and compare it against the stored security.evm xattr.
54 *
55 * For performance:
56 * - use the previoulsy retrieved xattr value and length to calculate the
57 * HMAC.)
58 * - cache the verification result in the iint, when available.
59 *
60 * Returns integrity status
61 */
62static enum integrity_status evm_verify_hmac(struct dentry *dentry,
63 const char *xattr_name,
64 char *xattr_value,
65 size_t xattr_value_len,
66 struct integrity_iint_cache *iint)
67{
68 struct evm_ima_xattr_data xattr_data;
69 enum integrity_status evm_status = INTEGRITY_PASS;
70 int rc;
71
72 if (iint && iint->evm_status == INTEGRITY_PASS)
73 return iint->evm_status;
74
75 /* if status is not PASS, try to check again - against -ENOMEM */
76
77 rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
78 xattr_value_len, xattr_data.digest);
79 if (rc < 0) {
80 evm_status = (rc == -ENODATA)
81 ? INTEGRITY_NOXATTRS : INTEGRITY_FAIL;
82 goto out;
83 }
84
85 xattr_data.type = EVM_XATTR_HMAC;
86 rc = vfs_xattr_cmp(dentry, XATTR_NAME_EVM, (u8 *)&xattr_data,
87 sizeof xattr_data, GFP_NOFS);
88 if (rc < 0)
89 evm_status = (rc == -ENODATA)
90 ? INTEGRITY_NOLABEL : INTEGRITY_FAIL;
91out:
92 if (iint)
93 iint->evm_status = evm_status;
94 return evm_status;
95}
96
97static int evm_protected_xattr(const char *req_xattr_name)
98{
99 char **xattrname;
100 int namelen;
101 int found = 0;
102
103 namelen = strlen(req_xattr_name);
104 for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
105 if ((strlen(*xattrname) == namelen)
106 && (strncmp(req_xattr_name, *xattrname, namelen) == 0)) {
107 found = 1;
108 break;
109 }
110 if (strncmp(req_xattr_name,
111 *xattrname + XATTR_SECURITY_PREFIX_LEN,
112 strlen(req_xattr_name)) == 0) {
113 found = 1;
114 break;
115 }
116 }
117 return found;
118}
119
120/**
121 * evm_verifyxattr - verify the integrity of the requested xattr
122 * @dentry: object of the verify xattr
123 * @xattr_name: requested xattr
124 * @xattr_value: requested xattr value
125 * @xattr_value_len: requested xattr value length
126 *
127 * Calculate the HMAC for the given dentry and verify it against the stored
128 * security.evm xattr. For performance, use the xattr value and length
129 * previously retrieved to calculate the HMAC.
130 *
131 * Returns the xattr integrity status.
132 *
133 * This function requires the caller to lock the inode's i_mutex before it
134 * is executed.
135 */
136enum integrity_status evm_verifyxattr(struct dentry *dentry,
137 const char *xattr_name,
138 void *xattr_value, size_t xattr_value_len,
139 struct integrity_iint_cache *iint)
140{
141 if (!evm_initialized || !evm_protected_xattr(xattr_name))
142 return INTEGRITY_UNKNOWN;
143
144 if (!iint) {
145 iint = integrity_iint_find(dentry->d_inode);
146 if (!iint)
147 return INTEGRITY_UNKNOWN;
148 }
149 return evm_verify_hmac(dentry, xattr_name, xattr_value,
150 xattr_value_len, iint);
151}
152EXPORT_SYMBOL_GPL(evm_verifyxattr);
153
154/*
155 * evm_verify_current_integrity - verify the dentry's metadata integrity
156 * @dentry: pointer to the affected dentry
157 *
158 * Verify and return the dentry's metadata integrity. The exceptions are
159 * before EVM is initialized or in 'fix' mode.
160 */
161static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)
162{
163 struct inode *inode = dentry->d_inode;
164
165 if (!evm_initialized || !S_ISREG(inode->i_mode) || evm_fixmode)
166 return 0;
167 return evm_verify_hmac(dentry, NULL, NULL, 0, NULL);
168}
169
170/*
171 * evm_protect_xattr - protect the EVM extended attribute
172 *
173 * Prevent security.evm from being modified or removed without the
174 * necessary permissions or when the existing value is invalid.
175 *
176 * The posix xattr acls are 'system' prefixed, which normally would not
177 * affect security.evm. An interesting side affect of writing posix xattr
178 * acls is their modifying of the i_mode, which is included in security.evm.
179 * For posix xattr acls only, permit security.evm, even if it currently
180 * doesn't exist, to be updated.
181 */
182static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
183 const void *xattr_value, size_t xattr_value_len)
184{
185 enum integrity_status evm_status;
186
187 if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) {
188 if (!capable(CAP_SYS_ADMIN))
189 return -EPERM;
190 } else if (!evm_protected_xattr(xattr_name)) {
191 if (!posix_xattr_acl(xattr_name))
192 return 0;
193 evm_status = evm_verify_current_integrity(dentry);
194 if ((evm_status == INTEGRITY_PASS) ||
195 (evm_status == INTEGRITY_NOXATTRS))
196 return 0;
197 return -EPERM;
198 }
199 evm_status = evm_verify_current_integrity(dentry);
200 return evm_status == INTEGRITY_PASS ? 0 : -EPERM;
201}
202
203/**
204 * evm_inode_setxattr - protect the EVM extended attribute
205 * @dentry: pointer to the affected dentry
206 * @xattr_name: pointer to the affected extended attribute name
207 * @xattr_value: pointer to the new extended attribute value
208 * @xattr_value_len: pointer to the new extended attribute value length
209 *
210 * Updating 'security.evm' requires CAP_SYS_ADMIN privileges and that
211 * the current value is valid.
212 */
213int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name,
214 const void *xattr_value, size_t xattr_value_len)
215{
216 return evm_protect_xattr(dentry, xattr_name, xattr_value,
217 xattr_value_len);
218}
219
220/**
221 * evm_inode_removexattr - protect the EVM extended attribute
222 * @dentry: pointer to the affected dentry
223 * @xattr_name: pointer to the affected extended attribute name
224 *
225 * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that
226 * the current value is valid.
227 */
228int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name)
229{
230 return evm_protect_xattr(dentry, xattr_name, NULL, 0);
231}
232
233/**
234 * evm_inode_post_setxattr - update 'security.evm' to reflect the changes
235 * @dentry: pointer to the affected dentry
236 * @xattr_name: pointer to the affected extended attribute name
237 * @xattr_value: pointer to the new extended attribute value
238 * @xattr_value_len: pointer to the new extended attribute value length
239 *
240 * Update the HMAC stored in 'security.evm' to reflect the change.
241 *
242 * No need to take the i_mutex lock here, as this function is called from
243 * __vfs_setxattr_noperm(). The caller of which has taken the inode's
244 * i_mutex lock.
245 */
246void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
247 const void *xattr_value, size_t xattr_value_len)
248{
249 if (!evm_initialized || (!evm_protected_xattr(xattr_name)
250 && !posix_xattr_acl(xattr_name)))
251 return;
252
253 evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len);
254 return;
255}
256
257/**
258 * evm_inode_post_removexattr - update 'security.evm' after removing the xattr
259 * @dentry: pointer to the affected dentry
260 * @xattr_name: pointer to the affected extended attribute name
261 *
262 * Update the HMAC stored in 'security.evm' to reflect removal of the xattr.
263 */
264void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
265{
266 struct inode *inode = dentry->d_inode;
267
268 if (!evm_initialized || !evm_protected_xattr(xattr_name))
269 return;
270
271 mutex_lock(&inode->i_mutex);
272 evm_update_evmxattr(dentry, xattr_name, NULL, 0);
273 mutex_unlock(&inode->i_mutex);
274 return;
275}
276
277/**
278 * evm_inode_setattr - prevent updating an invalid EVM extended attribute
279 * @dentry: pointer to the affected dentry
280 */
281int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
282{
283 unsigned int ia_valid = attr->ia_valid;
284 enum integrity_status evm_status;
285
286 if (!(ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)))
287 return 0;
288 evm_status = evm_verify_current_integrity(dentry);
289 if ((evm_status == INTEGRITY_PASS) ||
290 (evm_status == INTEGRITY_NOXATTRS))
291 return 0;
292 return -EPERM;
293}
294
295/**
296 * evm_inode_post_setattr - update 'security.evm' after modifying metadata
297 * @dentry: pointer to the affected dentry
298 * @ia_valid: for the UID and GID status
299 *
300 * For now, update the HMAC stored in 'security.evm' to reflect UID/GID
301 * changes.
302 *
303 * This function is called from notify_change(), which expects the caller
304 * to lock the inode's i_mutex.
305 */
306void evm_inode_post_setattr(struct dentry *dentry, int ia_valid)
307{
308 if (!evm_initialized)
309 return;
310
311 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
312 evm_update_evmxattr(dentry, NULL, NULL, 0);
313 return;
314}
315
316/*
317 * evm_inode_init_security - initializes security.evm
318 */
319int evm_inode_init_security(struct inode *inode,
320 const struct xattr *lsm_xattr,
321 struct xattr *evm_xattr)
322{
323 struct evm_ima_xattr_data *xattr_data;
324 int rc;
325
326 if (!evm_initialized || !evm_protected_xattr(lsm_xattr->name))
327 return 0;
328
329 xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS);
330 if (!xattr_data)
331 return -ENOMEM;
332
333 xattr_data->type = EVM_XATTR_HMAC;
334 rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest);
335 if (rc < 0)
336 goto out;
337
338 evm_xattr->value = xattr_data;
339 evm_xattr->value_len = sizeof(*xattr_data);
340 evm_xattr->name = kstrdup(XATTR_EVM_SUFFIX, GFP_NOFS);
341 return 0;
342out:
343 kfree(xattr_data);
344 return rc;
345}
346EXPORT_SYMBOL_GPL(evm_inode_init_security);
347
348static int __init init_evm(void)
349{
350 int error;
351
352 error = evm_init_secfs();
353 if (error < 0) {
354 printk(KERN_INFO "EVM: Error registering secfs\n");
355 goto err;
356 }
357err:
358 return error;
359}
360
361static void __exit cleanup_evm(void)
362{
363 evm_cleanup_secfs();
364 if (hmac_tfm)
365 crypto_free_shash(hmac_tfm);
366}
367
368/*
369 * evm_display_config - list the EVM protected security extended attributes
370 */
371static int __init evm_display_config(void)
372{
373 char **xattrname;
374
375 for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++)
376 printk(KERN_INFO "EVM: %s\n", *xattrname);
377 return 0;
378}
379
380pure_initcall(evm_display_config);
381late_initcall(init_evm);
382
383MODULE_DESCRIPTION("Extended Verification Module");
384MODULE_LICENSE("GPL");
diff --git a/security/integrity/evm/evm_posix_acl.c b/security/integrity/evm/evm_posix_acl.c
new file mode 100644
index 000000000000..b1753e98bf9a
--- /dev/null
+++ b/security/integrity/evm/evm_posix_acl.c
@@ -0,0 +1,26 @@
1/*
2 * Copyright (C) 2011 IBM Corporation
3 *
4 * Author:
5 * Mimi Zohar <zohar@us.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, version 2 of the License.
10 */
11
12#include <linux/module.h>
13#include <linux/xattr.h>
14
15int posix_xattr_acl(char *xattr)
16{
17 int xattr_len = strlen(xattr);
18
19 if ((strlen(XATTR_NAME_POSIX_ACL_ACCESS) == xattr_len)
20 && (strncmp(XATTR_NAME_POSIX_ACL_ACCESS, xattr, xattr_len) == 0))
21 return 1;
22 if ((strlen(XATTR_NAME_POSIX_ACL_DEFAULT) == xattr_len)
23 && (strncmp(XATTR_NAME_POSIX_ACL_DEFAULT, xattr, xattr_len) == 0))
24 return 1;
25 return 0;
26}
diff --git a/security/integrity/evm/evm_secfs.c b/security/integrity/evm/evm_secfs.c
new file mode 100644
index 000000000000..ac7629950578
--- /dev/null
+++ b/security/integrity/evm/evm_secfs.c
@@ -0,0 +1,108 @@
1/*
2 * Copyright (C) 2010 IBM Corporation
3 *
4 * Authors:
5 * Mimi Zohar <zohar@us.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, version 2 of the License.
10 *
11 * File: evm_secfs.c
12 * - Used to signal when key is on keyring
13 * - Get the key and enable EVM
14 */
15
16#include <linux/uaccess.h>
17#include <linux/module.h>
18#include "evm.h"
19
20static struct dentry *evm_init_tpm;
21
22/**
23 * evm_read_key - read() for <securityfs>/evm
24 *
25 * @filp: file pointer, not actually used
26 * @buf: where to put the result
27 * @count: maximum to send along
28 * @ppos: where to start
29 *
30 * Returns number of bytes read or error code, as appropriate
31 */
32static ssize_t evm_read_key(struct file *filp, char __user *buf,
33 size_t count, loff_t *ppos)
34{
35 char temp[80];
36 ssize_t rc;
37
38 if (*ppos != 0)
39 return 0;
40
41 sprintf(temp, "%d", evm_initialized);
42 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
43
44 return rc;
45}
46
47/**
48 * evm_write_key - write() for <securityfs>/evm
49 * @file: file pointer, not actually used
50 * @buf: where to get the data from
51 * @count: bytes sent
52 * @ppos: where to start
53 *
54 * Used to signal that key is on the kernel key ring.
55 * - get the integrity hmac key from the kernel key ring
56 * - create list of hmac protected extended attributes
57 * Returns number of bytes written or error code, as appropriate
58 */
59static ssize_t evm_write_key(struct file *file, const char __user *buf,
60 size_t count, loff_t *ppos)
61{
62 char temp[80];
63 int i, error;
64
65 if (!capable(CAP_SYS_ADMIN) || evm_initialized)
66 return -EPERM;
67
68 if (count >= sizeof(temp) || count == 0)
69 return -EINVAL;
70
71 if (copy_from_user(temp, buf, count) != 0)
72 return -EFAULT;
73
74 temp[count] = '\0';
75
76 if ((sscanf(temp, "%d", &i) != 1) || (i != 1))
77 return -EINVAL;
78
79 error = evm_init_key();
80 if (!error) {
81 evm_initialized = 1;
82 pr_info("EVM: initialized\n");
83 } else
84 pr_err("EVM: initialization failed\n");
85 return count;
86}
87
88static const struct file_operations evm_key_ops = {
89 .read = evm_read_key,
90 .write = evm_write_key,
91};
92
93int __init evm_init_secfs(void)
94{
95 int error = 0;
96
97 evm_init_tpm = securityfs_create_file("evm", S_IRUSR | S_IRGRP,
98 NULL, NULL, &evm_key_ops);
99 if (!evm_init_tpm || IS_ERR(evm_init_tpm))
100 error = -EFAULT;
101 return error;
102}
103
104void __exit evm_cleanup_secfs(void)
105{
106 if (evm_init_tpm)
107 securityfs_remove(evm_init_tpm);
108}
diff --git a/security/integrity/iint.c b/security/integrity/iint.c
new file mode 100644
index 000000000000..399641c3e846
--- /dev/null
+++ b/security/integrity/iint.c
@@ -0,0 +1,172 @@
1/*
2 * Copyright (C) 2008 IBM Corporation
3 *
4 * Authors:
5 * Mimi Zohar <zohar@us.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, version 2 of the
10 * License.
11 *
12 * File: integrity_iint.c
13 * - implements the integrity hooks: integrity_inode_alloc,
14 * integrity_inode_free
15 * - cache integrity information associated with an inode
16 * using a rbtree tree.
17 */
18#include <linux/slab.h>
19#include <linux/module.h>
20#include <linux/spinlock.h>
21#include <linux/rbtree.h>
22#include "integrity.h"
23
24static struct rb_root integrity_iint_tree = RB_ROOT;
25static DEFINE_SPINLOCK(integrity_iint_lock);
26static struct kmem_cache *iint_cache __read_mostly;
27
28int iint_initialized;
29
30/*
31 * __integrity_iint_find - return the iint associated with an inode
32 */
33static struct integrity_iint_cache *__integrity_iint_find(struct inode *inode)
34{
35 struct integrity_iint_cache *iint;
36 struct rb_node *n = integrity_iint_tree.rb_node;
37
38 assert_spin_locked(&integrity_iint_lock);
39
40 while (n) {
41 iint = rb_entry(n, struct integrity_iint_cache, rb_node);
42
43 if (inode < iint->inode)
44 n = n->rb_left;
45 else if (inode > iint->inode)
46 n = n->rb_right;
47 else
48 break;
49 }
50 if (!n)
51 return NULL;
52
53 return iint;
54}
55
56/*
57 * integrity_iint_find - return the iint associated with an inode
58 */
59struct integrity_iint_cache *integrity_iint_find(struct inode *inode)
60{
61 struct integrity_iint_cache *iint;
62
63 if (!IS_IMA(inode))
64 return NULL;
65
66 spin_lock(&integrity_iint_lock);
67 iint = __integrity_iint_find(inode);
68 spin_unlock(&integrity_iint_lock);
69
70 return iint;
71}
72
73static void iint_free(struct integrity_iint_cache *iint)
74{
75 iint->version = 0;
76 iint->flags = 0UL;
77 iint->evm_status = INTEGRITY_UNKNOWN;
78 kmem_cache_free(iint_cache, iint);
79}
80
81/**
82 * integrity_inode_alloc - allocate an iint associated with an inode
83 * @inode: pointer to the inode
84 */
85int integrity_inode_alloc(struct inode *inode)
86{
87 struct rb_node **p;
88 struct rb_node *new_node, *parent = NULL;
89 struct integrity_iint_cache *new_iint, *test_iint;
90 int rc;
91
92 new_iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
93 if (!new_iint)
94 return -ENOMEM;
95
96 new_iint->inode = inode;
97 new_node = &new_iint->rb_node;
98
99 mutex_lock(&inode->i_mutex); /* i_flags */
100 spin_lock(&integrity_iint_lock);
101
102 p = &integrity_iint_tree.rb_node;
103 while (*p) {
104 parent = *p;
105 test_iint = rb_entry(parent, struct integrity_iint_cache,
106 rb_node);
107 rc = -EEXIST;
108 if (inode < test_iint->inode)
109 p = &(*p)->rb_left;
110 else if (inode > test_iint->inode)
111 p = &(*p)->rb_right;
112 else
113 goto out_err;
114 }
115
116 inode->i_flags |= S_IMA;
117 rb_link_node(new_node, parent, p);
118 rb_insert_color(new_node, &integrity_iint_tree);
119
120 spin_unlock(&integrity_iint_lock);
121 mutex_unlock(&inode->i_mutex); /* i_flags */
122
123 return 0;
124out_err:
125 spin_unlock(&integrity_iint_lock);
126 mutex_unlock(&inode->i_mutex); /* i_flags */
127 iint_free(new_iint);
128
129 return rc;
130}
131
132/**
133 * integrity_inode_free - called on security_inode_free
134 * @inode: pointer to the inode
135 *
136 * Free the integrity information(iint) associated with an inode.
137 */
138void integrity_inode_free(struct inode *inode)
139{
140 struct integrity_iint_cache *iint;
141
142 if (!IS_IMA(inode))
143 return;
144
145 spin_lock(&integrity_iint_lock);
146 iint = __integrity_iint_find(inode);
147 rb_erase(&iint->rb_node, &integrity_iint_tree);
148 spin_unlock(&integrity_iint_lock);
149
150 iint_free(iint);
151}
152
153static void init_once(void *foo)
154{
155 struct integrity_iint_cache *iint = foo;
156
157 memset(iint, 0, sizeof *iint);
158 iint->version = 0;
159 iint->flags = 0UL;
160 mutex_init(&iint->mutex);
161 iint->evm_status = INTEGRITY_UNKNOWN;
162}
163
164static int __init integrity_iintcache_init(void)
165{
166 iint_cache =
167 kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache),
168 0, SLAB_PANIC, init_once);
169 iint_initialized = 1;
170 return 0;
171}
172security_initcall(integrity_iintcache_init);
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index b6ecfd4d8d78..19c053b82303 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -3,6 +3,7 @@
3config IMA 3config IMA
4 bool "Integrity Measurement Architecture(IMA)" 4 bool "Integrity Measurement Architecture(IMA)"
5 depends on SECURITY 5 depends on SECURITY
6 select INTEGRITY
6 select SECURITYFS 7 select SECURITYFS
7 select CRYPTO 8 select CRYPTO
8 select CRYPTO_HMAC 9 select CRYPTO_HMAC
diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
index 787c4cb916cd..5690c021de8f 100644
--- a/security/integrity/ima/Makefile
+++ b/security/integrity/ima/Makefile
@@ -6,4 +6,4 @@
6obj-$(CONFIG_IMA) += ima.o 6obj-$(CONFIG_IMA) += ima.o
7 7
8ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ 8ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
9 ima_policy.o ima_iint.o ima_audit.o 9 ima_policy.o ima_audit.o
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 08408bd71462..3ccf7acac6df 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -24,18 +24,19 @@
24#include <linux/tpm.h> 24#include <linux/tpm.h>
25#include <linux/audit.h> 25#include <linux/audit.h>
26 26
27#include "../integrity.h"
28
27enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_ASCII }; 29enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_ASCII };
28enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; 30enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
29 31
30/* digest size for IMA, fits SHA1 or MD5 */ 32/* digest size for IMA, fits SHA1 or MD5 */
31#define IMA_DIGEST_SIZE 20 33#define IMA_DIGEST_SIZE SHA1_DIGEST_SIZE
32#define IMA_EVENT_NAME_LEN_MAX 255 34#define IMA_EVENT_NAME_LEN_MAX 255
33 35
34#define IMA_HASH_BITS 9 36#define IMA_HASH_BITS 9
35#define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS) 37#define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS)
36 38
37/* set during initialization */ 39/* set during initialization */
38extern int iint_initialized;
39extern int ima_initialized; 40extern int ima_initialized;
40extern int ima_used_chip; 41extern int ima_used_chip;
41extern char *ima_hash; 42extern char *ima_hash;
@@ -96,34 +97,21 @@ static inline unsigned long ima_hash_key(u8 *digest)
96 return hash_long(*digest, IMA_HASH_BITS); 97 return hash_long(*digest, IMA_HASH_BITS);
97} 98}
98 99
99/* iint cache flags */
100#define IMA_MEASURED 0x01
101
102/* integrity data associated with an inode */
103struct ima_iint_cache {
104 struct rb_node rb_node; /* rooted in ima_iint_tree */
105 struct inode *inode; /* back pointer to inode in question */
106 u64 version; /* track inode changes */
107 unsigned char flags;
108 u8 digest[IMA_DIGEST_SIZE];
109 struct mutex mutex; /* protects: version, flags, digest */
110};
111
112/* LIM API function definitions */ 100/* LIM API function definitions */
113int ima_must_measure(struct inode *inode, int mask, int function); 101int ima_must_measure(struct inode *inode, int mask, int function);
114int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file); 102int ima_collect_measurement(struct integrity_iint_cache *iint,
115void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, 103 struct file *file);
104void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
116 const unsigned char *filename); 105 const unsigned char *filename);
117int ima_store_template(struct ima_template_entry *entry, int violation, 106int ima_store_template(struct ima_template_entry *entry, int violation,
118 struct inode *inode); 107 struct inode *inode);
119void ima_template_show(struct seq_file *m, void *e, 108void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show);
120 enum ima_show_type show);
121 109
122/* rbtree tree calls to lookup, insert, delete 110/* rbtree tree calls to lookup, insert, delete
123 * integrity data associated with an inode. 111 * integrity data associated with an inode.
124 */ 112 */
125struct ima_iint_cache *ima_iint_insert(struct inode *inode); 113struct integrity_iint_cache *integrity_iint_insert(struct inode *inode);
126struct ima_iint_cache *ima_iint_find(struct inode *inode); 114struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
127 115
128/* IMA policy related functions */ 116/* IMA policy related functions */
129enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK }; 117enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK };
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index da36d2c085a4..0d50df04ccc4 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -126,7 +126,8 @@ int ima_must_measure(struct inode *inode, int mask, int function)
126 * 126 *
127 * Return 0 on success, error code otherwise 127 * Return 0 on success, error code otherwise
128 */ 128 */
129int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file) 129int ima_collect_measurement(struct integrity_iint_cache *iint,
130 struct file *file)
130{ 131{
131 int result = -EEXIST; 132 int result = -EEXIST;
132 133
@@ -156,8 +157,8 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file)
156 * 157 *
157 * Must be called with iint->mutex held. 158 * Must be called with iint->mutex held.
158 */ 159 */
159void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, 160void ima_store_measurement(struct integrity_iint_cache *iint,
160 const unsigned char *filename) 161 struct file *file, const unsigned char *filename)
161{ 162{
162 const char *op = "add_template_measure"; 163 const char *op = "add_template_measure";
163 const char *audit_cause = "ENOMEM"; 164 const char *audit_cause = "ENOMEM";
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index ef21b96a0b42..e1aa2b482dd2 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -287,7 +287,7 @@ static atomic_t policy_opencount = ATOMIC_INIT(1);
287/* 287/*
288 * ima_open_policy: sequentialize access to the policy file 288 * ima_open_policy: sequentialize access to the policy file
289 */ 289 */
290int ima_open_policy(struct inode * inode, struct file * filp) 290static int ima_open_policy(struct inode * inode, struct file * filp)
291{ 291{
292 /* No point in being allowed to open it if you aren't going to write */ 292 /* No point in being allowed to open it if you aren't going to write */
293 if (!(filp->f_flags & O_WRONLY)) 293 if (!(filp->f_flags & O_WRONLY))
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
deleted file mode 100644
index 4ae73040ab7b..000000000000
--- a/security/integrity/ima/ima_iint.c
+++ /dev/null
@@ -1,169 +0,0 @@
1/*
2 * Copyright (C) 2008 IBM Corporation
3 *
4 * Authors:
5 * Mimi Zohar <zohar@us.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, version 2 of the
10 * License.
11 *
12 * File: ima_iint.c
13 * - implements the IMA hooks: ima_inode_alloc, ima_inode_free
14 * - cache integrity information associated with an inode
15 * using a rbtree tree.
16 */
17#include <linux/slab.h>
18#include <linux/module.h>
19#include <linux/spinlock.h>
20#include <linux/rbtree.h>
21#include "ima.h"
22
23static struct rb_root ima_iint_tree = RB_ROOT;
24static DEFINE_SPINLOCK(ima_iint_lock);
25static struct kmem_cache *iint_cache __read_mostly;
26
27int iint_initialized = 0;
28
29/*
30 * __ima_iint_find - return the iint associated with an inode
31 */
32static struct ima_iint_cache *__ima_iint_find(struct inode *inode)
33{
34 struct ima_iint_cache *iint;
35 struct rb_node *n = ima_iint_tree.rb_node;
36
37 assert_spin_locked(&ima_iint_lock);
38
39 while (n) {
40 iint = rb_entry(n, struct ima_iint_cache, rb_node);
41
42 if (inode < iint->inode)
43 n = n->rb_left;
44 else if (inode > iint->inode)
45 n = n->rb_right;
46 else
47 break;
48 }
49 if (!n)
50 return NULL;
51
52 return iint;
53}
54
55/*
56 * ima_iint_find - return the iint associated with an inode
57 */
58struct ima_iint_cache *ima_iint_find(struct inode *inode)
59{
60 struct ima_iint_cache *iint;
61
62 if (!IS_IMA(inode))
63 return NULL;
64
65 spin_lock(&ima_iint_lock);
66 iint = __ima_iint_find(inode);
67 spin_unlock(&ima_iint_lock);
68
69 return iint;
70}
71
72static void iint_free(struct ima_iint_cache *iint)
73{
74 iint->version = 0;
75 iint->flags = 0UL;
76 kmem_cache_free(iint_cache, iint);
77}
78
79/**
80 * ima_inode_alloc - allocate an iint associated with an inode
81 * @inode: pointer to the inode
82 */
83int ima_inode_alloc(struct inode *inode)
84{
85 struct rb_node **p;
86 struct rb_node *new_node, *parent = NULL;
87 struct ima_iint_cache *new_iint, *test_iint;
88 int rc;
89
90 new_iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
91 if (!new_iint)
92 return -ENOMEM;
93
94 new_iint->inode = inode;
95 new_node = &new_iint->rb_node;
96
97 mutex_lock(&inode->i_mutex); /* i_flags */
98 spin_lock(&ima_iint_lock);
99
100 p = &ima_iint_tree.rb_node;
101 while (*p) {
102 parent = *p;
103 test_iint = rb_entry(parent, struct ima_iint_cache, rb_node);
104
105 rc = -EEXIST;
106 if (inode < test_iint->inode)
107 p = &(*p)->rb_left;
108 else if (inode > test_iint->inode)
109 p = &(*p)->rb_right;
110 else
111 goto out_err;
112 }
113
114 inode->i_flags |= S_IMA;
115 rb_link_node(new_node, parent, p);
116 rb_insert_color(new_node, &ima_iint_tree);
117
118 spin_unlock(&ima_iint_lock);
119 mutex_unlock(&inode->i_mutex); /* i_flags */
120
121 return 0;
122out_err:
123 spin_unlock(&ima_iint_lock);
124 mutex_unlock(&inode->i_mutex); /* i_flags */
125 iint_free(new_iint);
126
127 return rc;
128}
129
130/**
131 * ima_inode_free - called on security_inode_free
132 * @inode: pointer to the inode
133 *
134 * Free the integrity information(iint) associated with an inode.
135 */
136void ima_inode_free(struct inode *inode)
137{
138 struct ima_iint_cache *iint;
139
140 if (!IS_IMA(inode))
141 return;
142
143 spin_lock(&ima_iint_lock);
144 iint = __ima_iint_find(inode);
145 rb_erase(&iint->rb_node, &ima_iint_tree);
146 spin_unlock(&ima_iint_lock);
147
148 iint_free(iint);
149}
150
151static void init_once(void *foo)
152{
153 struct ima_iint_cache *iint = foo;
154
155 memset(iint, 0, sizeof *iint);
156 iint->version = 0;
157 iint->flags = 0UL;
158 mutex_init(&iint->mutex);
159}
160
161static int __init ima_iintcache_init(void)
162{
163 iint_cache =
164 kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,
165 SLAB_PANIC, init_once);
166 iint_initialized = 1;
167 return 0;
168}
169security_initcall(ima_iintcache_init);
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 26b46ff74663..1eff5cb001e5 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -22,6 +22,7 @@
22#include <linux/mount.h> 22#include <linux/mount.h>
23#include <linux/mman.h> 23#include <linux/mman.h>
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/ima.h>
25 26
26#include "ima.h" 27#include "ima.h"
27 28
@@ -82,7 +83,7 @@ out:
82 "open_writers"); 83 "open_writers");
83} 84}
84 85
85static void ima_check_last_writer(struct ima_iint_cache *iint, 86static void ima_check_last_writer(struct integrity_iint_cache *iint,
86 struct inode *inode, 87 struct inode *inode,
87 struct file *file) 88 struct file *file)
88{ 89{
@@ -105,12 +106,12 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
105void ima_file_free(struct file *file) 106void ima_file_free(struct file *file)
106{ 107{
107 struct inode *inode = file->f_dentry->d_inode; 108 struct inode *inode = file->f_dentry->d_inode;
108 struct ima_iint_cache *iint; 109 struct integrity_iint_cache *iint;
109 110
110 if (!iint_initialized || !S_ISREG(inode->i_mode)) 111 if (!iint_initialized || !S_ISREG(inode->i_mode))
111 return; 112 return;
112 113
113 iint = ima_iint_find(inode); 114 iint = integrity_iint_find(inode);
114 if (!iint) 115 if (!iint)
115 return; 116 return;
116 117
@@ -121,7 +122,7 @@ static int process_measurement(struct file *file, const unsigned char *filename,
121 int mask, int function) 122 int mask, int function)
122{ 123{
123 struct inode *inode = file->f_dentry->d_inode; 124 struct inode *inode = file->f_dentry->d_inode;
124 struct ima_iint_cache *iint; 125 struct integrity_iint_cache *iint;
125 int rc = 0; 126 int rc = 0;
126 127
127 if (!ima_initialized || !S_ISREG(inode->i_mode)) 128 if (!ima_initialized || !S_ISREG(inode->i_mode))
@@ -131,9 +132,9 @@ static int process_measurement(struct file *file, const unsigned char *filename,
131 if (rc != 0) 132 if (rc != 0)
132 return rc; 133 return rc;
133retry: 134retry:
134 iint = ima_iint_find(inode); 135 iint = integrity_iint_find(inode);
135 if (!iint) { 136 if (!iint) {
136 rc = ima_inode_alloc(inode); 137 rc = integrity_inode_alloc(inode);
137 if (!rc || rc == -EEXIST) 138 if (!rc || rc == -EEXIST)
138 goto retry; 139 goto retry;
139 return rc; 140 return rc;
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
new file mode 100644
index 000000000000..3143a3c39868
--- /dev/null
+++ b/security/integrity/integrity.h
@@ -0,0 +1,50 @@
1/*
2 * Copyright (C) 2009-2010 IBM Corporation
3 *
4 * Authors:
5 * Mimi Zohar <zohar@us.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, version 2 of the
10 * License.
11 *
12 */
13
14#include <linux/types.h>
15#include <linux/integrity.h>
16#include <crypto/sha.h>
17
18/* iint cache flags */
19#define IMA_MEASURED 0x01
20
21enum evm_ima_xattr_type {
22 IMA_XATTR_DIGEST = 0x01,
23 EVM_XATTR_HMAC,
24 EVM_IMA_XATTR_DIGSIG,
25};
26
27struct evm_ima_xattr_data {
28 u8 type;
29 u8 digest[SHA1_DIGEST_SIZE];
30} __attribute__((packed));
31
32/* integrity data associated with an inode */
33struct integrity_iint_cache {
34 struct rb_node rb_node; /* rooted in integrity_iint_tree */
35 struct inode *inode; /* back pointer to inode in question */
36 u64 version; /* track inode changes */
37 unsigned char flags;
38 u8 digest[SHA1_DIGEST_SIZE];
39 struct mutex mutex; /* protects: version, flags, digest */
40 enum integrity_status evm_status;
41};
42
43/* rbtree tree calls to lookup, insert, delete
44 * integrity data associated with an inode.
45 */
46struct integrity_iint_cache *integrity_iint_insert(struct inode *inode);
47struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
48
49/* set during initialization */
50extern int iint_initialized;