diff options
| author | James Morris <jmorris@namei.org> | 2011-09-15 09:53:38 +1000 | 
|---|---|---|
| committer | James Morris <jmorris@namei.org> | 2011-09-15 09:53:38 +1000 | 
| commit | 8de6ac7f58a22fdab399fbe97763e465ea49c735 (patch) | |
| tree | 46104451c69f5270fcc11137aecff012a2ecf612 | |
| parent | 843d183cdd816549b73e6bd3ae07f64adddf714b (diff) | |
| parent | fb788d8b981fa55603873416882f8dcf835e7924 (diff) | |
Merge branch 'next-evm' of git://github.com/mzohar/linux-evm into next
| -rw-r--r-- | include/linux/evm.h | 8 | ||||
| -rw-r--r-- | include/linux/integrity.h | 1 | ||||
| -rw-r--r-- | include/linux/xattr.h | 5 | ||||
| -rw-r--r-- | security/Kconfig | 4 | ||||
| -rw-r--r-- | security/integrity/evm/Kconfig | 3 | ||||
| -rw-r--r-- | security/integrity/evm/Makefile | 1 | ||||
| -rw-r--r-- | security/integrity/evm/evm_main.c | 102 | ||||
| -rw-r--r-- | security/integrity/evm/evm_posix_acl.c | 26 | ||||
| -rw-r--r-- | security/integrity/iint.c | 1 | ||||
| -rw-r--r-- | security/keys/Makefile | 2 | ||||
| -rw-r--r-- | security/keys/encrypted-keys/Makefile | 6 | ||||
| -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.c | 44 | ||||
| -rw-r--r-- | security/security.c | 4 | 
17 files changed, 169 insertions, 84 deletions
| diff --git a/include/linux/evm.h b/include/linux/evm.h index ea603c9e775d..9fc13a760928 100644 --- a/include/linux/evm.h +++ b/include/linux/evm.h @@ -33,6 +33,14 @@ extern void evm_inode_post_removexattr(struct dentry *dentry,  extern int evm_inode_init_security(struct inode *inode,  				   const struct xattr *xattr_array,  				   struct xattr *evm); +#ifdef CONFIG_FS_POSIX_ACL +extern int posix_xattr_acl(const char *xattrname); +#else +static inline int posix_xattr_acl(const char *xattrname) +{ +	return 0; +} +#endif  #else  #ifdef CONFIG_INTEGRITY  static inline enum integrity_status evm_verifyxattr(struct dentry *dentry, diff --git a/include/linux/integrity.h b/include/linux/integrity.h index 968443385678..a0c41256cb92 100644 --- a/include/linux/integrity.h +++ b/include/linux/integrity.h @@ -16,6 +16,7 @@ enum integrity_status {  	INTEGRITY_PASS = 0,  	INTEGRITY_FAIL,  	INTEGRITY_NOLABEL, +	INTEGRITY_NOXATTRS,  	INTEGRITY_UNKNOWN,  }; diff --git a/include/linux/xattr.h b/include/linux/xattr.h index b20cb965c322..e5d122031542 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -52,6 +52,11 @@  #define XATTR_CAPS_SUFFIX "capability"  #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX +#define XATTR_POSIX_ACL_ACCESS  "posix_acl_access" +#define XATTR_NAME_POSIX_ACL_ACCESS XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_ACCESS +#define XATTR_POSIX_ACL_DEFAULT  "posix_acl_default" +#define XATTR_NAME_POSIX_ACL_DEFAULT XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_DEFAULT +  #ifdef  __KERNEL__  #include <linux/types.h> 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  config ENCRYPTED_KEYS  	tristate "ENCRYPTED KEYS" -	depends on KEYS && TRUSTED_KEYS +	depends on KEYS +	select CRYPTO +	select CRYPTO_HMAC  	select CRYPTO_AES  	select CRYPTO_CBC  	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 @@  config EVM  	boolean "EVM support" -	depends on SECURITY && KEYS && TCG_TPM +	depends on SECURITY && KEYS && (TRUSTED_KEYS=y || TRUSTED_KEYS=n)  	select CRYPTO_HMAC  	select CRYPTO_MD5  	select CRYPTO_SHA1  	select ENCRYPTED_KEYS -	select TRUSTED_KEYS  	default n  	help  	  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 @@  obj-$(CONFIG_EVM) += evm.o  evm-y := evm_main.o evm_crypto.o evm_secfs.o +evm-$(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,  					     struct integrity_iint_cache *iint)  {  	struct evm_ima_xattr_data xattr_data; -	enum integrity_status evm_status; +	enum integrity_status evm_status = INTEGRITY_PASS;  	int rc;  	if (iint && iint->evm_status == INTEGRITY_PASS) @@ -76,25 +76,18 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,  	rc = evm_calc_hmac(dentry, xattr_name, xattr_value,  			   xattr_value_len, xattr_data.digest); -	if (rc < 0) -		goto err_out; +	if (rc < 0) { +		evm_status = (rc == -ENODATA) +		    ? INTEGRITY_NOXATTRS : INTEGRITY_FAIL; +		goto out; +	}  	xattr_data.type = EVM_XATTR_HMAC;  	rc = vfs_xattr_cmp(dentry, XATTR_NAME_EVM, (u8 *)&xattr_data,  			   sizeof xattr_data, GFP_NOFS);  	if (rc < 0) -		goto err_out; -	evm_status = INTEGRITY_PASS; -	goto out; - -err_out: -	switch (rc) { -	case -ENODATA:		/* file not labelled */ -		evm_status = INTEGRITY_NOLABEL; -		break; -	default: -		evm_status = INTEGRITY_FAIL; -	} +		evm_status = (rc == -ENODATA) +		    ? INTEGRITY_NOLABEL : INTEGRITY_FAIL;  out:  	if (iint)  		iint->evm_status = evm_status; @@ -159,21 +152,6 @@ enum integrity_status evm_verifyxattr(struct dentry *dentry,  EXPORT_SYMBOL_GPL(evm_verifyxattr);  /* - * evm_protect_xattr - protect the EVM extended attribute - * - * Prevent security.evm from being modified or removed. - */ -static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, -			     const void *xattr_value, size_t xattr_value_len) -{ -	if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { -		if (!capable(CAP_SYS_ADMIN)) -			return -EPERM; -	} -	return 0; -} - -/*   * evm_verify_current_integrity - verify the dentry's metadata integrity   * @dentry: pointer to the affected dentry   * @@ -189,6 +167,39 @@ static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)  	return evm_verify_hmac(dentry, NULL, NULL, 0, NULL);  } +/* + * evm_protect_xattr - protect the EVM extended attribute + * + * Prevent security.evm from being modified or removed without the + * necessary permissions or when the existing value is invalid. + * + * The posix xattr acls are 'system' prefixed, which normally would not + * affect security.evm.  An interesting side affect of writing posix xattr + * acls is their modifying of the i_mode, which is included in security.evm. + * For posix xattr acls only, permit security.evm, even if it currently + * doesn't exist, to be updated. + */ +static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, +			     const void *xattr_value, size_t xattr_value_len) +{ +	enum integrity_status evm_status; + +	if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { +		if (!capable(CAP_SYS_ADMIN)) +			return -EPERM; +	} else if (!evm_protected_xattr(xattr_name)) { +		if (!posix_xattr_acl(xattr_name)) +			return 0; +		evm_status = evm_verify_current_integrity(dentry); +		if ((evm_status == INTEGRITY_PASS) || +		    (evm_status == INTEGRITY_NOXATTRS)) +			return 0; +		return -EPERM; +	} +	evm_status = evm_verify_current_integrity(dentry); +	return evm_status == INTEGRITY_PASS ? 0 : -EPERM; +} +  /**   * evm_inode_setxattr - protect the EVM extended attribute   * @dentry: pointer to the affected dentry @@ -202,16 +213,8 @@ static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)  int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name,  		       const void *xattr_value, size_t xattr_value_len)  { - -	enum integrity_status evm_status; -	int ret; - -	ret = evm_protect_xattr(dentry, xattr_name, xattr_value, -				xattr_value_len); -	if (ret) -		return ret; -	evm_status = evm_verify_current_integrity(dentry); -	return evm_status == INTEGRITY_PASS ? 0 : -EPERM; +	return evm_protect_xattr(dentry, xattr_name, xattr_value, +				 xattr_value_len);  }  /** @@ -224,14 +227,7 @@ int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name,   */  int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name)  { -	enum integrity_status evm_status; -	int ret; - -	ret = evm_protect_xattr(dentry, xattr_name, NULL, 0); -	if (ret) -		return ret; -	evm_status = evm_verify_current_integrity(dentry); -	return evm_status == INTEGRITY_PASS ? 0 : -EPERM; +	return evm_protect_xattr(dentry, xattr_name, NULL, 0);  }  /** @@ -250,7 +246,8 @@ int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name)  void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,  			     const void *xattr_value, size_t xattr_value_len)  { -	if (!evm_initialized || !evm_protected_xattr(xattr_name)) +	if (!evm_initialized || (!evm_protected_xattr(xattr_name) +				 && !posix_xattr_acl(xattr_name)))  		return;  	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)  	unsigned int ia_valid = attr->ia_valid;  	enum integrity_status evm_status; -	if (ia_valid & ~(ATTR_MODE | ATTR_UID | ATTR_GID)) +	if (!(ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)))  		return 0;  	evm_status = evm_verify_current_integrity(dentry); -	return evm_status == INTEGRITY_PASS ? 0 : -EPERM; +	if ((evm_status == INTEGRITY_PASS) || +	    (evm_status == INTEGRITY_NOXATTRS)) +		return 0; +	return -EPERM;  }  /** 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 @@ +/* + * Copyright (C) 2011 IBM Corporation + * + * Author: + * Mimi Zohar <zohar@us.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + */ + +#include <linux/module.h> +#include <linux/xattr.h> + +int posix_xattr_acl(char *xattr) +{ +	int xattr_len = strlen(xattr); + +	if ((strlen(XATTR_NAME_POSIX_ACL_ACCESS) == xattr_len) +	     && (strncmp(XATTR_NAME_POSIX_ACL_ACCESS, xattr, xattr_len) == 0)) +		return 1; +	if ((strlen(XATTR_NAME_POSIX_ACL_DEFAULT) == xattr_len) +	     && (strncmp(XATTR_NAME_POSIX_ACL_DEFAULT, xattr, xattr_len) == 0)) +		return 1; +	return 0; +} 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)  {  	iint->version = 0;  	iint->flags = 0UL; +	iint->evm_status = INTEGRITY_UNKNOWN;  	kmem_cache_free(iint_cache, iint);  } 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 := \  	user_defined.o  obj-$(CONFIG_TRUSTED_KEYS) += trusted.o -obj-$(CONFIG_ENCRYPTED_KEYS) += ecryptfs_format.o encrypted.o +obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/  obj-$(CONFIG_KEYS_COMPAT) += compat.o  obj-$(CONFIG_PROC_FS) += proc.o  obj-$(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 @@ +# +# Makefile for encrypted keys +# + +obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted.o ecryptfs_format.o +obj-$(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:  }  /* - * request_trusted_key - request the trusted key - * - * Trusted keys are sealed to PCRs and other metadata. Although userspace - * manages both trusted/encrypted key-types, like the encrypted key type - * data, trusted key type data is not visible decrypted from userspace. - */ -static struct key *request_trusted_key(const char *trusted_desc, -				       u8 **master_key, size_t *master_keylen) -{ -	struct trusted_key_payload *tpayload; -	struct key *tkey; - -	tkey = request_key(&key_type_trusted, trusted_desc, NULL); -	if (IS_ERR(tkey)) -		goto error; - -	down_read(&tkey->sem); -	tpayload = rcu_dereference(tkey->payload.data); -	*master_key = tpayload->key; -	*master_keylen = tpayload->key_len; -error: -	return tkey; -} - -/*   * request_user_key - request the user key   *   * 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,  		goto out;  	if (IS_ERR(mkey)) { -		pr_info("encrypted_key: key %s not found", -			epayload->master_desc); +		int ret = PTR_ERR(epayload); + +		if (ret == -ENOTSUPP) +			pr_info("encrypted_key: key %s not supported", +				epayload->master_desc); +		else +			pr_info("encrypted_key: key %s not found", +				epayload->master_desc);  		goto out;  	} 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 @@  #define __ENCRYPTED_KEY_H  #define ENCRYPTED_DEBUG 0 +#ifdef CONFIG_TRUSTED_KEYS +extern struct key *request_trusted_key(const char *trusted_desc, +				       u8 **master_key, size_t *master_keylen); +#else +static inline struct key *request_trusted_key(const char *trusted_desc, +					      u8 **master_key, +					      size_t *master_keylen) +{ +	return ERR_PTR(-EOPNOTSUPP); +} +#endif  #if ENCRYPTED_DEBUG  static 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 @@ +/* + * Copyright (C) 2010 IBM Corporation + * Copyright (C) 2010 Politecnico di Torino, Italy + *                    TORSEC group -- http://security.polito.it + * + * Authors: + * Mimi Zohar <zohar@us.ibm.com> + * Roberto Sassu <roberto.sassu@polito.it> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * See Documentation/security/keys-trusted-encrypted.txt + */ + +#include <linux/uaccess.h> +#include <linux/module.h> +#include <keys/trusted-type.h> + +/* + * request_trusted_key - request the trusted key + * + * Trusted keys are sealed to PCRs and other metadata. Although userspace + * manages both trusted/encrypted key-types, like the encrypted key type + * data, trusted key type data is not visible decrypted from userspace. + */ +struct key *request_trusted_key(const char *trusted_desc, +				u8 **master_key, size_t *master_keylen) +{ +	struct trusted_key_payload *tpayload; +	struct key *tkey; + +	tkey = request_key(&key_type_trusted, trusted_desc, NULL); +	if (IS_ERR(tkey)) +		goto error; + +	down_read(&tkey->sem); +	tpayload = rcu_dereference(tkey->payload.data); +	*master_key = tpayload->key; +	*master_keylen = tpayload->key_len; +error: +	return tkey; +} 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,  	int ret;  	if (unlikely(IS_PRIVATE(inode))) -		return -EOPNOTSUPP; +		return 0;  	memset(new_xattrs, 0, sizeof new_xattrs);  	if (!initxattrs) @@ -381,7 +381,7 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir,  				     void **value, size_t *len)  {  	if (unlikely(IS_PRIVATE(inode))) -		return -EOPNOTSUPP; +		return 0;  	return security_ops->inode_init_security(inode, dir, qstr, name, value,  						 len);  } | 
