aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2011-08-08 20:31:03 -0400
committerJames Morris <jmorris@namei.org>2011-08-08 20:31:03 -0400
commit5a2f3a02aea164f4f59c0c3497772090a411b462 (patch)
treed3ebe03d4f97575290087843960baa01de3acd0a /security
parent1d568ab068c021672d6cd7f50f92a3695a921ffb (diff)
parent817b54aa45db03437c6d09a7693fc6926eb8e822 (diff)
Merge branch 'next-evm' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/ima-2.6 into next
Conflicts: fs/attr.c Resolve conflict manually. Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig2
-rw-r--r--security/Makefile4
-rw-r--r--security/integrity/Kconfig7
-rw-r--r--security/integrity/Makefile12
-rw-r--r--security/integrity/evm/Kconfig12
-rw-r--r--security/integrity/evm/Makefile6
-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_secfs.c108
-rw-r--r--security/integrity/iint.c171
-rw-r--r--security/integrity/ima/Kconfig1
-rw-r--r--security/integrity/ima/Makefile2
-rw-r--r--security/integrity/ima/ima.h29
-rw-r--r--security/integrity/ima/ima_api.c7
-rw-r--r--security/integrity/ima/ima_iint.c169
-rw-r--r--security/integrity/ima/ima_main.c12
-rw-r--r--security/integrity/integrity.h47
-rw-r--r--security/security.c71
19 files changed, 1089 insertions, 209 deletions
diff --git a/security/Kconfig b/security/Kconfig
index e0f08b52e4ab..22847a889081 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -186,7 +186,7 @@ source security/smack/Kconfig
186source security/tomoyo/Kconfig 186source security/tomoyo/Kconfig
187source security/apparmor/Kconfig 187source security/apparmor/Kconfig
188 188
189source security/integrity/ima/Kconfig 189source security/integrity/Kconfig
190 190
191choice 191choice
192 prompt "Default security module" 192 prompt "Default security module"
diff --git a/security/Makefile b/security/Makefile
index 8bb0fe9e1ca9..a5e502f8a05b 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -24,5 +24,5 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/built-in.o
24obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o 24obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
25 25
26# Object integrity file lists 26# Object integrity file lists
27subdir-$(CONFIG_IMA) += integrity/ima 27subdir-$(CONFIG_INTEGRITY) += integrity
28obj-$(CONFIG_IMA) += integrity/ima/built-in.o 28obj-$(CONFIG_INTEGRITY) += integrity/built-in.o
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..73f654099a4b
--- /dev/null
+++ b/security/integrity/evm/Kconfig
@@ -0,0 +1,12 @@
1config EVM
2 boolean "EVM support"
3 depends on SECURITY && KEYS && ENCRYPTED_KEYS
4 select CRYPTO_HMAC
5 select CRYPTO_MD5
6 select CRYPTO_SHA1
7 default n
8 help
9 EVM protects a file's security extended attributes against
10 integrity attacks.
11
12 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..0787d262b9e3
--- /dev/null
+++ b/security/integrity/evm/Makefile
@@ -0,0 +1,6 @@
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
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..8fc5b5d7ceaa
--- /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;
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 goto err_out;
81
82 xattr_data.type = EVM_XATTR_HMAC;
83 rc = vfs_xattr_cmp(dentry, XATTR_NAME_EVM, (u8 *)&xattr_data,
84 sizeof xattr_data, GFP_NOFS);
85 if (rc < 0)
86 goto err_out;
87 evm_status = INTEGRITY_PASS;
88 goto out;
89
90err_out:
91 switch (rc) {
92 case -ENODATA: /* file not labelled */
93 evm_status = INTEGRITY_NOLABEL;
94 break;
95 default:
96 evm_status = INTEGRITY_FAIL;
97 }
98out:
99 if (iint)
100 iint->evm_status = evm_status;
101 return evm_status;
102}
103
104static int evm_protected_xattr(const char *req_xattr_name)
105{
106 char **xattrname;
107 int namelen;
108 int found = 0;
109
110 namelen = strlen(req_xattr_name);
111 for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
112 if ((strlen(*xattrname) == namelen)
113 && (strncmp(req_xattr_name, *xattrname, namelen) == 0)) {
114 found = 1;
115 break;
116 }
117 if (strncmp(req_xattr_name,
118 *xattrname + XATTR_SECURITY_PREFIX_LEN,
119 strlen(req_xattr_name)) == 0) {
120 found = 1;
121 break;
122 }
123 }
124 return found;
125}
126
127/**
128 * evm_verifyxattr - verify the integrity of the requested xattr
129 * @dentry: object of the verify xattr
130 * @xattr_name: requested xattr
131 * @xattr_value: requested xattr value
132 * @xattr_value_len: requested xattr value length
133 *
134 * Calculate the HMAC for the given dentry and verify it against the stored
135 * security.evm xattr. For performance, use the xattr value and length
136 * previously retrieved to calculate the HMAC.
137 *
138 * Returns the xattr integrity status.
139 *
140 * This function requires the caller to lock the inode's i_mutex before it
141 * is executed.
142 */
143enum integrity_status evm_verifyxattr(struct dentry *dentry,
144 const char *xattr_name,
145 void *xattr_value, size_t xattr_value_len,
146 struct integrity_iint_cache *iint)
147{
148 if (!evm_initialized || !evm_protected_xattr(xattr_name))
149 return INTEGRITY_UNKNOWN;
150
151 if (!iint) {
152 iint = integrity_iint_find(dentry->d_inode);
153 if (!iint)
154 return INTEGRITY_UNKNOWN;
155 }
156 return evm_verify_hmac(dentry, xattr_name, xattr_value,
157 xattr_value_len, iint);
158}
159EXPORT_SYMBOL_GPL(evm_verifyxattr);
160
161/*
162 * evm_protect_xattr - protect the EVM extended attribute
163 *
164 * Prevent security.evm from being modified or removed.
165 */
166static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
167 const void *xattr_value, size_t xattr_value_len)
168{
169 if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) {
170 if (!capable(CAP_SYS_ADMIN))
171 return -EPERM;
172 }
173 return 0;
174}
175
176/*
177 * evm_verify_current_integrity - verify the dentry's metadata integrity
178 * @dentry: pointer to the affected dentry
179 *
180 * Verify and return the dentry's metadata integrity. The exceptions are
181 * before EVM is initialized or in 'fix' mode.
182 */
183static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)
184{
185 struct inode *inode = dentry->d_inode;
186
187 if (!evm_initialized || !S_ISREG(inode->i_mode) || evm_fixmode)
188 return 0;
189 return evm_verify_hmac(dentry, NULL, NULL, 0, NULL);
190}
191
192/**
193 * evm_inode_setxattr - protect the EVM extended attribute
194 * @dentry: pointer to the affected dentry
195 * @xattr_name: pointer to the affected extended attribute name
196 * @xattr_value: pointer to the new extended attribute value
197 * @xattr_value_len: pointer to the new extended attribute value length
198 *
199 * Updating 'security.evm' requires CAP_SYS_ADMIN privileges and that
200 * the current value is valid.
201 */
202int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name,
203 const void *xattr_value, size_t xattr_value_len)
204{
205
206 enum integrity_status evm_status;
207 int ret;
208
209 ret = evm_protect_xattr(dentry, xattr_name, xattr_value,
210 xattr_value_len);
211 if (ret)
212 return ret;
213 evm_status = evm_verify_current_integrity(dentry);
214 return evm_status == INTEGRITY_PASS ? 0 : -EPERM;
215}
216
217/**
218 * evm_inode_removexattr - protect the EVM extended attribute
219 * @dentry: pointer to the affected dentry
220 * @xattr_name: pointer to the affected extended attribute name
221 *
222 * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that
223 * the current value is valid.
224 */
225int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name)
226{
227 enum integrity_status evm_status;
228 int ret;
229
230 ret = evm_protect_xattr(dentry, xattr_name, NULL, 0);
231 if (ret)
232 return ret;
233 evm_status = evm_verify_current_integrity(dentry);
234 return evm_status == INTEGRITY_PASS ? 0 : -EPERM;
235}
236
237/**
238 * evm_inode_post_setxattr - update 'security.evm' to reflect the changes
239 * @dentry: pointer to the affected dentry
240 * @xattr_name: pointer to the affected extended attribute name
241 * @xattr_value: pointer to the new extended attribute value
242 * @xattr_value_len: pointer to the new extended attribute value length
243 *
244 * Update the HMAC stored in 'security.evm' to reflect the change.
245 *
246 * No need to take the i_mutex lock here, as this function is called from
247 * __vfs_setxattr_noperm(). The caller of which has taken the inode's
248 * i_mutex lock.
249 */
250void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
251 const void *xattr_value, size_t xattr_value_len)
252{
253 if (!evm_initialized || !evm_protected_xattr(xattr_name))
254 return;
255
256 evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len);
257 return;
258}
259
260/**
261 * evm_inode_post_removexattr - update 'security.evm' after removing the xattr
262 * @dentry: pointer to the affected dentry
263 * @xattr_name: pointer to the affected extended attribute name
264 *
265 * Update the HMAC stored in 'security.evm' to reflect removal of the xattr.
266 */
267void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
268{
269 struct inode *inode = dentry->d_inode;
270
271 if (!evm_initialized || !evm_protected_xattr(xattr_name))
272 return;
273
274 mutex_lock(&inode->i_mutex);
275 evm_update_evmxattr(dentry, xattr_name, NULL, 0);
276 mutex_unlock(&inode->i_mutex);
277 return;
278}
279
280/**
281 * evm_inode_setattr - prevent updating an invalid EVM extended attribute
282 * @dentry: pointer to the affected dentry
283 */
284int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
285{
286 unsigned int ia_valid = attr->ia_valid;
287 enum integrity_status evm_status;
288
289 if (ia_valid & ~(ATTR_MODE | ATTR_UID | ATTR_GID))
290 return 0;
291 evm_status = evm_verify_current_integrity(dentry);
292 return evm_status == INTEGRITY_PASS ? 0 : -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 -EOPNOTSUPP;
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_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..0a23e075e1d2
--- /dev/null
+++ b/security/integrity/iint.c
@@ -0,0 +1,171 @@
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 kmem_cache_free(iint_cache, iint);
78}
79
80/**
81 * integrity_inode_alloc - allocate an iint associated with an inode
82 * @inode: pointer to the inode
83 */
84int integrity_inode_alloc(struct inode *inode)
85{
86 struct rb_node **p;
87 struct rb_node *new_node, *parent = NULL;
88 struct integrity_iint_cache *new_iint, *test_iint;
89 int rc;
90
91 new_iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
92 if (!new_iint)
93 return -ENOMEM;
94
95 new_iint->inode = inode;
96 new_node = &new_iint->rb_node;
97
98 mutex_lock(&inode->i_mutex); /* i_flags */
99 spin_lock(&integrity_iint_lock);
100
101 p = &integrity_iint_tree.rb_node;
102 while (*p) {
103 parent = *p;
104 test_iint = rb_entry(parent, struct integrity_iint_cache,
105 rb_node);
106 rc = -EEXIST;
107 if (inode < test_iint->inode)
108 p = &(*p)->rb_left;
109 else if (inode > test_iint->inode)
110 p = &(*p)->rb_right;
111 else
112 goto out_err;
113 }
114
115 inode->i_flags |= S_IMA;
116 rb_link_node(new_node, parent, p);
117 rb_insert_color(new_node, &integrity_iint_tree);
118
119 spin_unlock(&integrity_iint_lock);
120 mutex_unlock(&inode->i_mutex); /* i_flags */
121
122 return 0;
123out_err:
124 spin_unlock(&integrity_iint_lock);
125 mutex_unlock(&inode->i_mutex); /* i_flags */
126 iint_free(new_iint);
127
128 return rc;
129}
130
131/**
132 * integrity_inode_free - called on security_inode_free
133 * @inode: pointer to the inode
134 *
135 * Free the integrity information(iint) associated with an inode.
136 */
137void integrity_inode_free(struct inode *inode)
138{
139 struct integrity_iint_cache *iint;
140
141 if (!IS_IMA(inode))
142 return;
143
144 spin_lock(&integrity_iint_lock);
145 iint = __integrity_iint_find(inode);
146 rb_erase(&iint->rb_node, &integrity_iint_tree);
147 spin_unlock(&integrity_iint_lock);
148
149 iint_free(iint);
150}
151
152static void init_once(void *foo)
153{
154 struct integrity_iint_cache *iint = foo;
155
156 memset(iint, 0, sizeof *iint);
157 iint->version = 0;
158 iint->flags = 0UL;
159 mutex_init(&iint->mutex);
160 iint->evm_status = INTEGRITY_UNKNOWN;
161}
162
163static int __init integrity_iintcache_init(void)
164{
165 iint_cache =
166 kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache),
167 0, SLAB_PANIC, init_once);
168 iint_initialized = 1;
169 return 0;
170}
171security_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..29d97af5e9a4 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -24,11 +24,13 @@
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
@@ -96,34 +98,21 @@ static inline unsigned long ima_hash_key(u8 *digest)
96 return hash_long(*digest, IMA_HASH_BITS); 98 return hash_long(*digest, IMA_HASH_BITS);
97} 99}
98 100
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 */ 101/* LIM API function definitions */
113int ima_must_measure(struct inode *inode, int mask, int function); 102int ima_must_measure(struct inode *inode, int mask, int function);
114int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file); 103int ima_collect_measurement(struct integrity_iint_cache *iint,
115void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, 104 struct file *file);
105void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
116 const unsigned char *filename); 106 const unsigned char *filename);
117int ima_store_template(struct ima_template_entry *entry, int violation, 107int ima_store_template(struct ima_template_entry *entry, int violation,
118 struct inode *inode); 108 struct inode *inode);
119void ima_template_show(struct seq_file *m, void *e, 109void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show);
120 enum ima_show_type show);
121 110
122/* rbtree tree calls to lookup, insert, delete 111/* rbtree tree calls to lookup, insert, delete
123 * integrity data associated with an inode. 112 * integrity data associated with an inode.
124 */ 113 */
125struct ima_iint_cache *ima_iint_insert(struct inode *inode); 114struct integrity_iint_cache *integrity_iint_insert(struct inode *inode);
126struct ima_iint_cache *ima_iint_find(struct inode *inode); 115struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
127 116
128/* IMA policy related functions */ 117/* IMA policy related functions */
129enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK }; 118enum 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_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..42dc27007fdd 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -82,7 +82,7 @@ out:
82 "open_writers"); 82 "open_writers");
83} 83}
84 84
85static void ima_check_last_writer(struct ima_iint_cache *iint, 85static void ima_check_last_writer(struct integrity_iint_cache *iint,
86 struct inode *inode, 86 struct inode *inode,
87 struct file *file) 87 struct file *file)
88{ 88{
@@ -105,12 +105,12 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
105void ima_file_free(struct file *file) 105void ima_file_free(struct file *file)
106{ 106{
107 struct inode *inode = file->f_dentry->d_inode; 107 struct inode *inode = file->f_dentry->d_inode;
108 struct ima_iint_cache *iint; 108 struct integrity_iint_cache *iint;
109 109
110 if (!iint_initialized || !S_ISREG(inode->i_mode)) 110 if (!iint_initialized || !S_ISREG(inode->i_mode))
111 return; 111 return;
112 112
113 iint = ima_iint_find(inode); 113 iint = integrity_iint_find(inode);
114 if (!iint) 114 if (!iint)
115 return; 115 return;
116 116
@@ -121,7 +121,7 @@ static int process_measurement(struct file *file, const unsigned char *filename,
121 int mask, int function) 121 int mask, int function)
122{ 122{
123 struct inode *inode = file->f_dentry->d_inode; 123 struct inode *inode = file->f_dentry->d_inode;
124 struct ima_iint_cache *iint; 124 struct integrity_iint_cache *iint;
125 int rc = 0; 125 int rc = 0;
126 126
127 if (!ima_initialized || !S_ISREG(inode->i_mode)) 127 if (!ima_initialized || !S_ISREG(inode->i_mode))
@@ -131,9 +131,9 @@ static int process_measurement(struct file *file, const unsigned char *filename,
131 if (rc != 0) 131 if (rc != 0)
132 return rc; 132 return rc;
133retry: 133retry:
134 iint = ima_iint_find(inode); 134 iint = integrity_iint_find(inode);
135 if (!iint) { 135 if (!iint) {
136 rc = ima_inode_alloc(inode); 136 rc = integrity_inode_alloc(inode);
137 if (!rc || rc == -EEXIST) 137 if (!rc || rc == -EEXIST)
138 goto retry; 138 goto retry;
139 return rc; 139 return rc;
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
new file mode 100644
index 000000000000..880bbee2f534
--- /dev/null
+++ b/security/integrity/integrity.h
@@ -0,0 +1,47 @@
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);
diff --git a/security/security.c b/security/security.c
index 0e4fccfef12c..a6328421a055 100644
--- a/security/security.c
+++ b/security/security.c
@@ -16,7 +16,11 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/security.h> 18#include <linux/security.h>
19#include <linux/integrity.h>
19#include <linux/ima.h> 20#include <linux/ima.h>
21#include <linux/evm.h>
22
23#define MAX_LSM_EVM_XATTR 2
20 24
21/* Boot-time LSM user choice */ 25/* Boot-time LSM user choice */
22static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = 26static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
@@ -334,20 +338,57 @@ int security_inode_alloc(struct inode *inode)
334 338
335void security_inode_free(struct inode *inode) 339void security_inode_free(struct inode *inode)
336{ 340{
337 ima_inode_free(inode); 341 integrity_inode_free(inode);
338 security_ops->inode_free_security(inode); 342 security_ops->inode_free_security(inode);
339} 343}
340 344
341int security_inode_init_security(struct inode *inode, struct inode *dir, 345int security_inode_init_security(struct inode *inode, struct inode *dir,
342 const struct qstr *qstr, char **name, 346 const struct qstr *qstr,
343 void **value, size_t *len) 347 const initxattrs initxattrs, void *fs_data)
348{
349 struct xattr new_xattrs[MAX_LSM_EVM_XATTR + 1];
350 struct xattr *lsm_xattr, *evm_xattr, *xattr;
351 int ret;
352
353 if (unlikely(IS_PRIVATE(inode)))
354 return -EOPNOTSUPP;
355
356 memset(new_xattrs, 0, sizeof new_xattrs);
357 if (!initxattrs)
358 return security_ops->inode_init_security(inode, dir, qstr,
359 NULL, NULL, NULL);
360 lsm_xattr = new_xattrs;
361 ret = security_ops->inode_init_security(inode, dir, qstr,
362 &lsm_xattr->name,
363 &lsm_xattr->value,
364 &lsm_xattr->value_len);
365 if (ret)
366 goto out;
367
368 evm_xattr = lsm_xattr + 1;
369 ret = evm_inode_init_security(inode, lsm_xattr, evm_xattr);
370 if (ret)
371 goto out;
372 ret = initxattrs(inode, new_xattrs, fs_data);
373out:
374 for (xattr = new_xattrs; xattr->name != NULL; xattr++) {
375 kfree(xattr->name);
376 kfree(xattr->value);
377 }
378 return (ret == -EOPNOTSUPP) ? 0 : ret;
379}
380EXPORT_SYMBOL(security_inode_init_security);
381
382int security_old_inode_init_security(struct inode *inode, struct inode *dir,
383 const struct qstr *qstr, char **name,
384 void **value, size_t *len)
344{ 385{
345 if (unlikely(IS_PRIVATE(inode))) 386 if (unlikely(IS_PRIVATE(inode)))
346 return -EOPNOTSUPP; 387 return -EOPNOTSUPP;
347 return security_ops->inode_init_security(inode, dir, qstr, name, value, 388 return security_ops->inode_init_security(inode, dir, qstr, name, value,
348 len); 389 len);
349} 390}
350EXPORT_SYMBOL(security_inode_init_security); 391EXPORT_SYMBOL(security_old_inode_init_security);
351 392
352#ifdef CONFIG_SECURITY_PATH 393#ifdef CONFIG_SECURITY_PATH
353int security_path_mknod(struct path *dir, struct dentry *dentry, int mode, 394int security_path_mknod(struct path *dir, struct dentry *dentry, int mode,
@@ -523,9 +564,14 @@ int security_inode_permission(struct inode *inode, int mask)
523 564
524int security_inode_setattr(struct dentry *dentry, struct iattr *attr) 565int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
525{ 566{
567 int ret;
568
526 if (unlikely(IS_PRIVATE(dentry->d_inode))) 569 if (unlikely(IS_PRIVATE(dentry->d_inode)))
527 return 0; 570 return 0;
528 return security_ops->inode_setattr(dentry, attr); 571 ret = security_ops->inode_setattr(dentry, attr);
572 if (ret)
573 return ret;
574 return evm_inode_setattr(dentry, attr);
529} 575}
530EXPORT_SYMBOL_GPL(security_inode_setattr); 576EXPORT_SYMBOL_GPL(security_inode_setattr);
531 577
@@ -539,9 +585,14 @@ int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
539int security_inode_setxattr(struct dentry *dentry, const char *name, 585int security_inode_setxattr(struct dentry *dentry, const char *name,
540 const void *value, size_t size, int flags) 586 const void *value, size_t size, int flags)
541{ 587{
588 int ret;
589
542 if (unlikely(IS_PRIVATE(dentry->d_inode))) 590 if (unlikely(IS_PRIVATE(dentry->d_inode)))
543 return 0; 591 return 0;
544 return security_ops->inode_setxattr(dentry, name, value, size, flags); 592 ret = security_ops->inode_setxattr(dentry, name, value, size, flags);
593 if (ret)
594 return ret;
595 return evm_inode_setxattr(dentry, name, value, size);
545} 596}
546 597
547void security_inode_post_setxattr(struct dentry *dentry, const char *name, 598void security_inode_post_setxattr(struct dentry *dentry, const char *name,
@@ -550,6 +601,7 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name,
550 if (unlikely(IS_PRIVATE(dentry->d_inode))) 601 if (unlikely(IS_PRIVATE(dentry->d_inode)))
551 return; 602 return;
552 security_ops->inode_post_setxattr(dentry, name, value, size, flags); 603 security_ops->inode_post_setxattr(dentry, name, value, size, flags);
604 evm_inode_post_setxattr(dentry, name, value, size);
553} 605}
554 606
555int security_inode_getxattr(struct dentry *dentry, const char *name) 607int security_inode_getxattr(struct dentry *dentry, const char *name)
@@ -568,9 +620,14 @@ int security_inode_listxattr(struct dentry *dentry)
568 620
569int security_inode_removexattr(struct dentry *dentry, const char *name) 621int security_inode_removexattr(struct dentry *dentry, const char *name)
570{ 622{
623 int ret;
624
571 if (unlikely(IS_PRIVATE(dentry->d_inode))) 625 if (unlikely(IS_PRIVATE(dentry->d_inode)))
572 return 0; 626 return 0;
573 return security_ops->inode_removexattr(dentry, name); 627 ret = security_ops->inode_removexattr(dentry, name);
628 if (ret)
629 return ret;
630 return evm_inode_removexattr(dentry, name);
574} 631}
575 632
576int security_inode_need_killpriv(struct dentry *dentry) 633int security_inode_need_killpriv(struct dentry *dentry)