From 61cf45d0199041df1a8ba334b6bf4a3a13b7f904 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Wed, 14 Sep 2011 15:06:00 -0400 Subject: [PATCH 1/8] encrypted-keys: create encrypted-keys directory Move all files associated with encrypted keys to keys/encrypted-keys. Signed-off-by: Mimi Zohar --- security/keys/Makefile | 2 +- security/keys/encrypted-keys/Makefile | 5 +++++ security/keys/{ => encrypted-keys}/ecryptfs_format.c | 0 security/keys/{ => encrypted-keys}/ecryptfs_format.h | 0 security/keys/{ => encrypted-keys}/encrypted.c | 0 security/keys/{ => encrypted-keys}/encrypted.h | 0 6 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 security/keys/encrypted-keys/Makefile rename security/keys/{ => encrypted-keys}/ecryptfs_format.c (100%) rename security/keys/{ => encrypted-keys}/ecryptfs_format.h (100%) rename security/keys/{ => encrypted-keys}/encrypted.c (100%) rename security/keys/{ => encrypted-keys}/encrypted.h (100%) 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..cbd3f8de37bb --- /dev/null +++ b/security/keys/encrypted-keys/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for encrypted keys +# + +obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted.o ecryptfs_format.o diff --git a/security/keys/ecryptfs_format.c b/security/keys/encrypted-keys/ecryptfs_format.c similarity index 100% rename from security/keys/ecryptfs_format.c rename to security/keys/encrypted-keys/ecryptfs_format.c diff --git a/security/keys/ecryptfs_format.h b/security/keys/encrypted-keys/ecryptfs_format.h similarity index 100% rename from security/keys/ecryptfs_format.h rename to security/keys/encrypted-keys/ecryptfs_format.h diff --git a/security/keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c similarity index 100% rename from security/keys/encrypted.c rename to security/keys/encrypted-keys/encrypted.c diff --git a/security/keys/encrypted.h b/security/keys/encrypted-keys/encrypted.h similarity index 100% rename from security/keys/encrypted.h rename to security/keys/encrypted-keys/encrypted.h From 982e617a313b57abee3bcfa53381c356d00fd64a Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Sat, 27 Aug 2011 22:21:26 -0400 Subject: [PATCH 2/8] encrypted-keys: remove trusted-keys dependency Encrypted keys are decrypted/encrypted using either a trusted-key or, for those systems without a TPM, a user-defined key. This patch removes the trusted-keys and TCG_TPM dependencies. Signed-off-by: Mimi Zohar --- security/Kconfig | 4 +- security/keys/encrypted-keys/Makefile | 1 + security/keys/encrypted-keys/encrypted.c | 35 ++++----------- security/keys/encrypted-keys/encrypted.h | 11 +++++ .../keys/encrypted-keys/masterkey_trusted.c | 44 +++++++++++++++++++ 5 files changed, 67 insertions(+), 28 deletions(-) create mode 100644 security/keys/encrypted-keys/masterkey_trusted.c 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/keys/encrypted-keys/Makefile b/security/keys/encrypted-keys/Makefile index cbd3f8de37bb..6bc7a86d1027 100644 --- a/security/keys/encrypted-keys/Makefile +++ b/security/keys/encrypted-keys/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted.o ecryptfs_format.o +obj-$(CONFIG_TRUSTED_KEYS) += masterkey_trusted.o diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index e7eca9ec4c65..3f577954b85a 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -298,31 +298,6 @@ out: return ascii_buf; } -/* - * 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 * @@ -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-keys/encrypted.h b/security/keys/encrypted-keys/encrypted.h index cef5e2f2b7d1..b6ade8945250 100644 --- a/security/keys/encrypted-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 + * Roberto Sassu + * + * 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 +#include +#include + +/* + * 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; +} From 1d714057ef8f6348eba7b28ace6d307513e57cef Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Sun, 28 Aug 2011 08:57:11 -0400 Subject: [PATCH 3/8] evm: remove TCG_TPM dependency All tristates selected by EVM(boolean) are forced to be builtin, except in the TCG_TPM(tristate) dependency case. Arnaud Lacombe summarizes the Kconfig bug as, "So it would seem direct dependency state influence the state of reverse dependencies.." For a detailed explanation, refer to Arnaud Lacombe's posting http://lkml.org/lkml/2011/8/23/498. With the "encrypted-keys: remove trusted-keys dependency" patch, EVM can now be built without a dependency on TCG_TPM. The trusted-keys dependency requires trusted-keys to either be builtin or not selected. This dependency will prevent the boolean/tristate mismatch from occuring. Reported-by: Stephen Rothwell , Randy Dunlap Signed-off-by: Mimi Zohar --- security/integrity/evm/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 From fb88c2b6cbb1265a8bef60694699b37f5cd4ba76 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Mon, 15 Aug 2011 10:13:18 -0400 Subject: [PATCH 4/8] evm: fix security/security_old_init_security return code security_inode_init_security previously returned -EOPNOTSUPP, for S_PRIVATE inodes, and relied on the callers to change it to 0. As the callers do not change the return code anymore, return 0, intead of -EOPNOTSUPP. Signed-off-by: Mimi Zohar --- security/security.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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); } From a924ce0b35875ef9512135b46a32f4150fd700b2 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Thu, 11 Aug 2011 01:22:30 -0400 Subject: [PATCH 5/8] evm: limit verifying current security.evm integrity evm_protect_xattr unnecessarily validates the current security.evm integrity, before updating non-evm protected extended attributes and other file metadata. This patch limits validating the current security.evm integrity to evm protected metadata. Signed-off-by: Mimi Zohar --- security/integrity/evm/evm_main.c | 58 +++++++++++++------------------ 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index f0127e536f84..7d4247535f9e 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -158,21 +158,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 +174,26 @@ 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. + */ +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)) + return 0; + + 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 +207,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 +221,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); } /** @@ -286,7 +276,7 @@ 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; From bf6d0f5dcda17df3cc5577e203d0f8ea1c2ad6aa Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Thu, 18 Aug 2011 18:07:44 -0400 Subject: [PATCH 6/8] evm: posix acls modify i_mode 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. This patch updates security.evm when posix xattr acls are written. Signed-off-by: Mimi Zohar --- include/linux/evm.h | 8 ++++++++ include/linux/xattr.h | 5 +++++ security/integrity/evm/Makefile | 1 + security/integrity/evm/evm_main.c | 24 +++++++++++++++++++----- security/integrity/evm/evm_posix_acl.c | 26 ++++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 security/integrity/evm/evm_posix_acl.c 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/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 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 7d4247535f9e..73c008d047c7 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -177,7 +177,14 @@ static enum integrity_status evm_verify_current_integrity(struct dentry *dentry) /* * evm_protect_xattr - protect the EVM extended attribute * - * Prevent security.evm from being modified or removed. + * 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) @@ -187,9 +194,15 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { if (!capable(CAP_SYS_ADMIN)) return -EPERM; - } else if (!evm_protected_xattr(xattr_name)) - return 0; - + } 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_NOLABEL)) + return 0; + return -EPERM; + } evm_status = evm_verify_current_integrity(dentry); return evm_status == INTEGRITY_PASS ? 0 : -EPERM; } @@ -240,7 +253,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); 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 + * + * 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 +#include + +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; +} From 566be59ab86c0e030b980645a580d683a015a483 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Mon, 22 Aug 2011 09:14:18 -0400 Subject: [PATCH 7/8] evm: permit mode bits to be updated Before permitting 'security.evm' to be updated, 'security.evm' must exist and be valid. In the case that there are no existing EVM protected xattrs, it is safe for posix acls to update the mode bits. To differentiate between no 'security.evm' xattr and no xattrs used to calculate 'security.evm', this patch defines INTEGRITY_NOXATTR. Signed-off-by: Mimi Zohar --- include/linux/integrity.h | 1 + security/integrity/evm/evm_main.c | 30 +++++++++++++----------------- 2 files changed, 14 insertions(+), 17 deletions(-) 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/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 73c008d047c7..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; @@ -199,7 +192,7 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, return 0; evm_status = evm_verify_current_integrity(dentry); if ((evm_status == INTEGRITY_PASS) || - (evm_status == INTEGRITY_NOLABEL)) + (evm_status == INTEGRITY_NOXATTRS)) return 0; return -EPERM; } @@ -293,7 +286,10 @@ int evm_inode_setattr(struct dentry *dentry, struct iattr *attr) 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; } /** From fb788d8b981fa55603873416882f8dcf835e7924 Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Mon, 15 Aug 2011 15:30:11 +0300 Subject: [PATCH 8/8] evm: clean verification status When allocating from slab, initialization is done the first time in init_once() and subsequently on free. Because evm_status was not re-initialized on free, evm_verify_hmac() skipped verifications. This patch re-initializes evm_status. Signed-off-by: Dmitry Kasatkin Signed-off-by: Mimi Zohar --- security/integrity/iint.c | 1 + 1 file changed, 1 insertion(+) 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); }