aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2011-09-14 19:53:38 -0400
committerJames Morris <jmorris@namei.org>2011-09-14 19:53:38 -0400
commit8de6ac7f58a22fdab399fbe97763e465ea49c735 (patch)
tree46104451c69f5270fcc11137aecff012a2ecf612 /security
parent843d183cdd816549b73e6bd3ae07f64adddf714b (diff)
parentfb788d8b981fa55603873416882f8dcf835e7924 (diff)
Merge branch 'next-evm' of git://github.com/mzohar/linux-evm into next
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig4
-rw-r--r--security/integrity/evm/Kconfig3
-rw-r--r--security/integrity/evm/Makefile1
-rw-r--r--security/integrity/evm/evm_main.c102
-rw-r--r--security/integrity/evm/evm_posix_acl.c26
-rw-r--r--security/integrity/iint.c1
-rw-r--r--security/keys/Makefile2
-rw-r--r--security/keys/encrypted-keys/Makefile6
-rw-r--r--security/keys/encrypted-keys/ecryptfs_format.c (renamed from security/keys/ecryptfs_format.c)0
-rw-r--r--security/keys/encrypted-keys/ecryptfs_format.h (renamed from security/keys/ecryptfs_format.h)0
-rw-r--r--security/keys/encrypted-keys/encrypted.c (renamed from security/keys/encrypted.c)35
-rw-r--r--security/keys/encrypted-keys/encrypted.h (renamed from security/keys/encrypted.h)11
-rw-r--r--security/keys/encrypted-keys/masterkey_trusted.c44
-rw-r--r--security/security.c4
14 files changed, 155 insertions, 84 deletions
diff --git a/security/Kconfig b/security/Kconfig
index 22847a889081..51bd5a0b69ae 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -38,7 +38,9 @@ config TRUSTED_KEYS
38 38
39config ENCRYPTED_KEYS 39config ENCRYPTED_KEYS
40 tristate "ENCRYPTED KEYS" 40 tristate "ENCRYPTED KEYS"
41 depends on KEYS && TRUSTED_KEYS 41 depends on KEYS
42 select CRYPTO
43 select CRYPTO_HMAC
42 select CRYPTO_AES 44 select CRYPTO_AES
43 select CRYPTO_CBC 45 select CRYPTO_CBC
44 select CRYPTO_SHA256 46 select CRYPTO_SHA256
diff --git a/security/integrity/evm/Kconfig b/security/integrity/evm/Kconfig
index 884617d4aad0..afbb59dd262d 100644
--- a/security/integrity/evm/Kconfig
+++ b/security/integrity/evm/Kconfig
@@ -1,11 +1,10 @@
1config EVM 1config EVM
2 boolean "EVM support" 2 boolean "EVM support"
3 depends on SECURITY && KEYS && TCG_TPM 3 depends on SECURITY && KEYS && (TRUSTED_KEYS=y || TRUSTED_KEYS=n)
4 select CRYPTO_HMAC 4 select CRYPTO_HMAC
5 select CRYPTO_MD5 5 select CRYPTO_MD5
6 select CRYPTO_SHA1 6 select CRYPTO_SHA1
7 select ENCRYPTED_KEYS 7 select ENCRYPTED_KEYS
8 select TRUSTED_KEYS
9 default n 8 default n
10 help 9 help
11 EVM protects a file's security extended attributes against 10 EVM protects a file's security extended attributes against
diff --git a/security/integrity/evm/Makefile b/security/integrity/evm/Makefile
index 0787d262b9e3..7393c415a066 100644
--- a/security/integrity/evm/Makefile
+++ b/security/integrity/evm/Makefile
@@ -4,3 +4,4 @@
4obj-$(CONFIG_EVM) += evm.o 4obj-$(CONFIG_EVM) += evm.o
5 5
6evm-y := evm_main.o evm_crypto.o evm_secfs.o 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_main.c b/security/integrity/evm/evm_main.c
index f0127e536f84..92d3d99a9f7b 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -66,7 +66,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
66 struct integrity_iint_cache *iint) 66 struct integrity_iint_cache *iint)
67{ 67{
68 struct evm_ima_xattr_data xattr_data; 68 struct evm_ima_xattr_data xattr_data;
69 enum integrity_status evm_status; 69 enum integrity_status evm_status = INTEGRITY_PASS;
70 int rc; 70 int rc;
71 71
72 if (iint && iint->evm_status == INTEGRITY_PASS) 72 if (iint && iint->evm_status == INTEGRITY_PASS)
@@ -76,25 +76,18 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
76 76
77 rc = evm_calc_hmac(dentry, xattr_name, xattr_value, 77 rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
78 xattr_value_len, xattr_data.digest); 78 xattr_value_len, xattr_data.digest);
79 if (rc < 0) 79 if (rc < 0) {
80 goto err_out; 80 evm_status = (rc == -ENODATA)
81 ? INTEGRITY_NOXATTRS : INTEGRITY_FAIL;
82 goto out;
83 }
81 84
82 xattr_data.type = EVM_XATTR_HMAC; 85 xattr_data.type = EVM_XATTR_HMAC;
83 rc = vfs_xattr_cmp(dentry, XATTR_NAME_EVM, (u8 *)&xattr_data, 86 rc = vfs_xattr_cmp(dentry, XATTR_NAME_EVM, (u8 *)&xattr_data,
84 sizeof xattr_data, GFP_NOFS); 87 sizeof xattr_data, GFP_NOFS);
85 if (rc < 0) 88 if (rc < 0)
86 goto err_out; 89 evm_status = (rc == -ENODATA)
87 evm_status = INTEGRITY_PASS; 90 ? INTEGRITY_NOLABEL : INTEGRITY_FAIL;
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: 91out:
99 if (iint) 92 if (iint)
100 iint->evm_status = evm_status; 93 iint->evm_status = evm_status;
@@ -159,21 +152,6 @@ enum integrity_status evm_verifyxattr(struct dentry *dentry,
159EXPORT_SYMBOL_GPL(evm_verifyxattr); 152EXPORT_SYMBOL_GPL(evm_verifyxattr);
160 153
161/* 154/*
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 155 * evm_verify_current_integrity - verify the dentry's metadata integrity
178 * @dentry: pointer to the affected dentry 156 * @dentry: pointer to the affected dentry
179 * 157 *
@@ -189,6 +167,39 @@ static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)
189 return evm_verify_hmac(dentry, NULL, NULL, 0, NULL); 167 return evm_verify_hmac(dentry, NULL, NULL, 0, NULL);
190} 168}
191 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
192/** 203/**
193 * evm_inode_setxattr - protect the EVM extended attribute 204 * evm_inode_setxattr - protect the EVM extended attribute
194 * @dentry: pointer to the affected dentry 205 * @dentry: pointer to the affected dentry
@@ -202,16 +213,8 @@ static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)
202int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name, 213int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name,
203 const void *xattr_value, size_t xattr_value_len) 214 const void *xattr_value, size_t xattr_value_len)
204{ 215{
205 216 return evm_protect_xattr(dentry, xattr_name, xattr_value,
206 enum integrity_status evm_status; 217 xattr_value_len);
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} 218}
216 219
217/** 220/**
@@ -224,14 +227,7 @@ int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name,
224 */ 227 */
225int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name) 228int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name)
226{ 229{
227 enum integrity_status evm_status; 230 return evm_protect_xattr(dentry, xattr_name, NULL, 0);
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} 231}
236 232
237/** 233/**
@@ -250,7 +246,8 @@ int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name)
250void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, 246void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
251 const void *xattr_value, size_t xattr_value_len) 247 const void *xattr_value, size_t xattr_value_len)
252{ 248{
253 if (!evm_initialized || !evm_protected_xattr(xattr_name)) 249 if (!evm_initialized || (!evm_protected_xattr(xattr_name)
250 && !posix_xattr_acl(xattr_name)))
254 return; 251 return;
255 252
256 evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len); 253 evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len);
@@ -286,10 +283,13 @@ int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
286 unsigned int ia_valid = attr->ia_valid; 283 unsigned int ia_valid = attr->ia_valid;
287 enum integrity_status evm_status; 284 enum integrity_status evm_status;
288 285
289 if (ia_valid & ~(ATTR_MODE | ATTR_UID | ATTR_GID)) 286 if (!(ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)))
290 return 0; 287 return 0;
291 evm_status = evm_verify_current_integrity(dentry); 288 evm_status = evm_verify_current_integrity(dentry);
292 return evm_status == INTEGRITY_PASS ? 0 : -EPERM; 289 if ((evm_status == INTEGRITY_PASS) ||
290 (evm_status == INTEGRITY_NOXATTRS))
291 return 0;
292 return -EPERM;
293} 293}
294 294
295/** 295/**
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/iint.c b/security/integrity/iint.c
index 0a23e075e1d2..399641c3e846 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -74,6 +74,7 @@ static void iint_free(struct integrity_iint_cache *iint)
74{ 74{
75 iint->version = 0; 75 iint->version = 0;
76 iint->flags = 0UL; 76 iint->flags = 0UL;
77 iint->evm_status = INTEGRITY_UNKNOWN;
77 kmem_cache_free(iint_cache, iint); 78 kmem_cache_free(iint_cache, iint);
78} 79}
79 80
diff --git a/security/keys/Makefile b/security/keys/Makefile
index b34cc6ee6900..a56f1ffdc64d 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -14,7 +14,7 @@ obj-y := \
14 user_defined.o 14 user_defined.o
15 15
16obj-$(CONFIG_TRUSTED_KEYS) += trusted.o 16obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
17obj-$(CONFIG_ENCRYPTED_KEYS) += ecryptfs_format.o encrypted.o 17obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
18obj-$(CONFIG_KEYS_COMPAT) += compat.o 18obj-$(CONFIG_KEYS_COMPAT) += compat.o
19obj-$(CONFIG_PROC_FS) += proc.o 19obj-$(CONFIG_PROC_FS) += proc.o
20obj-$(CONFIG_SYSCTL) += sysctl.o 20obj-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/security/keys/encrypted-keys/Makefile b/security/keys/encrypted-keys/Makefile
new file mode 100644
index 000000000000..6bc7a86d1027
--- /dev/null
+++ b/security/keys/encrypted-keys/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for encrypted keys
3#
4
5obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted.o ecryptfs_format.o
6obj-$(CONFIG_TRUSTED_KEYS) += masterkey_trusted.o
diff --git a/security/keys/ecryptfs_format.c b/security/keys/encrypted-keys/ecryptfs_format.c
index 6daa3b6ff9ed..6daa3b6ff9ed 100644
--- a/security/keys/ecryptfs_format.c
+++ b/security/keys/encrypted-keys/ecryptfs_format.c
diff --git a/security/keys/ecryptfs_format.h b/security/keys/encrypted-keys/ecryptfs_format.h
index 40294de238bb..40294de238bb 100644
--- a/security/keys/ecryptfs_format.h
+++ b/security/keys/encrypted-keys/ecryptfs_format.h
diff --git a/security/keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index e7eca9ec4c65..3f577954b85a 100644
--- a/security/keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -299,31 +299,6 @@ out:
299} 299}
300 300
301/* 301/*
302 * request_trusted_key - request the trusted key
303 *
304 * Trusted keys are sealed to PCRs and other metadata. Although userspace
305 * manages both trusted/encrypted key-types, like the encrypted key type
306 * data, trusted key type data is not visible decrypted from userspace.
307 */
308static struct key *request_trusted_key(const char *trusted_desc,
309 u8 **master_key, size_t *master_keylen)
310{
311 struct trusted_key_payload *tpayload;
312 struct key *tkey;
313
314 tkey = request_key(&key_type_trusted, trusted_desc, NULL);
315 if (IS_ERR(tkey))
316 goto error;
317
318 down_read(&tkey->sem);
319 tpayload = rcu_dereference(tkey->payload.data);
320 *master_key = tpayload->key;
321 *master_keylen = tpayload->key_len;
322error:
323 return tkey;
324}
325
326/*
327 * request_user_key - request the user key 302 * request_user_key - request the user key
328 * 303 *
329 * Use a user provided key to encrypt/decrypt an encrypted-key. 304 * Use a user provided key to encrypt/decrypt an encrypted-key.
@@ -469,8 +444,14 @@ static struct key *request_master_key(struct encrypted_key_payload *epayload,
469 goto out; 444 goto out;
470 445
471 if (IS_ERR(mkey)) { 446 if (IS_ERR(mkey)) {
472 pr_info("encrypted_key: key %s not found", 447 int ret = PTR_ERR(epayload);
473 epayload->master_desc); 448
449 if (ret == -ENOTSUPP)
450 pr_info("encrypted_key: key %s not supported",
451 epayload->master_desc);
452 else
453 pr_info("encrypted_key: key %s not found",
454 epayload->master_desc);
474 goto out; 455 goto out;
475 } 456 }
476 457
diff --git a/security/keys/encrypted.h b/security/keys/encrypted-keys/encrypted.h
index cef5e2f2b7d1..b6ade8945250 100644
--- a/security/keys/encrypted.h
+++ b/security/keys/encrypted-keys/encrypted.h
@@ -2,6 +2,17 @@
2#define __ENCRYPTED_KEY_H 2#define __ENCRYPTED_KEY_H
3 3
4#define ENCRYPTED_DEBUG 0 4#define ENCRYPTED_DEBUG 0
5#ifdef CONFIG_TRUSTED_KEYS
6extern struct key *request_trusted_key(const char *trusted_desc,
7 u8 **master_key, size_t *master_keylen);
8#else
9static inline struct key *request_trusted_key(const char *trusted_desc,
10 u8 **master_key,
11 size_t *master_keylen)
12{
13 return ERR_PTR(-EOPNOTSUPP);
14}
15#endif
5 16
6#if ENCRYPTED_DEBUG 17#if ENCRYPTED_DEBUG
7static inline void dump_master_key(const u8 *master_key, size_t master_keylen) 18static inline void dump_master_key(const u8 *master_key, size_t master_keylen)
diff --git a/security/keys/encrypted-keys/masterkey_trusted.c b/security/keys/encrypted-keys/masterkey_trusted.c
new file mode 100644
index 000000000000..a5da5128891b
--- /dev/null
+++ b/security/keys/encrypted-keys/masterkey_trusted.c
@@ -0,0 +1,44 @@
1/*
2 * Copyright (C) 2010 IBM Corporation
3 * Copyright (C) 2010 Politecnico di Torino, Italy
4 * TORSEC group -- http://security.polito.it
5 *
6 * Authors:
7 * Mimi Zohar <zohar@us.ibm.com>
8 * Roberto Sassu <roberto.sassu@polito.it>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, version 2 of the License.
13 *
14 * See Documentation/security/keys-trusted-encrypted.txt
15 */
16
17#include <linux/uaccess.h>
18#include <linux/module.h>
19#include <keys/trusted-type.h>
20
21/*
22 * request_trusted_key - request the trusted key
23 *
24 * Trusted keys are sealed to PCRs and other metadata. Although userspace
25 * manages both trusted/encrypted key-types, like the encrypted key type
26 * data, trusted key type data is not visible decrypted from userspace.
27 */
28struct key *request_trusted_key(const char *trusted_desc,
29 u8 **master_key, size_t *master_keylen)
30{
31 struct trusted_key_payload *tpayload;
32 struct key *tkey;
33
34 tkey = request_key(&key_type_trusted, trusted_desc, NULL);
35 if (IS_ERR(tkey))
36 goto error;
37
38 down_read(&tkey->sem);
39 tpayload = rcu_dereference(tkey->payload.data);
40 *master_key = tpayload->key;
41 *master_keylen = tpayload->key_len;
42error:
43 return tkey;
44}
diff --git a/security/security.c b/security/security.c
index 9ebda054a333..c1d69875db6c 100644
--- a/security/security.c
+++ b/security/security.c
@@ -348,7 +348,7 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
348 int ret; 348 int ret;
349 349
350 if (unlikely(IS_PRIVATE(inode))) 350 if (unlikely(IS_PRIVATE(inode)))
351 return -EOPNOTSUPP; 351 return 0;
352 352
353 memset(new_xattrs, 0, sizeof new_xattrs); 353 memset(new_xattrs, 0, sizeof new_xattrs);
354 if (!initxattrs) 354 if (!initxattrs)
@@ -381,7 +381,7 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir,
381 void **value, size_t *len) 381 void **value, size_t *len)
382{ 382{
383 if (unlikely(IS_PRIVATE(inode))) 383 if (unlikely(IS_PRIVATE(inode)))
384 return -EOPNOTSUPP; 384 return 0;
385 return security_ops->inode_init_security(inode, dir, qstr, name, value, 385 return security_ops->inode_init_security(inode, dir, qstr, name, value,
386 len); 386 len);
387} 387}