Merge branch 'next-evm' of git://github.com/mzohar/linux-evm into next
James Morris [Wed, 14 Sep 2011 23:53:38 +0000 (09:53 +1000)]
17 files changed:
include/linux/evm.h
include/linux/integrity.h
include/linux/xattr.h
security/Kconfig
security/integrity/evm/Kconfig
security/integrity/evm/Makefile
security/integrity/evm/evm_main.c
security/integrity/evm/evm_posix_acl.c [new file with mode: 0644]
security/integrity/iint.c
security/keys/Makefile
security/keys/encrypted-keys/Makefile [new file with mode: 0644]
security/keys/encrypted-keys/ecryptfs_format.c [moved from security/keys/ecryptfs_format.c with 100% similarity]
security/keys/encrypted-keys/ecryptfs_format.h [moved from security/keys/ecryptfs_format.h with 100% similarity]
security/keys/encrypted-keys/encrypted.c [moved from security/keys/encrypted.c with 97% similarity]
security/keys/encrypted-keys/encrypted.h [moved from security/keys/encrypted.h with 81% similarity]
security/keys/encrypted-keys/masterkey_trusted.c [new file with mode: 0644]
security/security.c

index ea603c9..9fc13a7 100644 (file)
@@ -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,
index 9684433..a0c4125 100644 (file)
@@ -16,6 +16,7 @@ enum integrity_status {
        INTEGRITY_PASS = 0,
        INTEGRITY_FAIL,
        INTEGRITY_NOLABEL,
+       INTEGRITY_NOXATTRS,
        INTEGRITY_UNKNOWN,
 };
 
index b20cb96..e5d1220 100644 (file)
 #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>
index 22847a8..51bd5a0 100644 (file)
@@ -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
index 884617d..afbb59d 100644 (file)
@@ -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
index 0787d26..7393c41 100644 (file)
@@ -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
index f0127e5..92d3d99 100644 (file)
@@ -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 (file)
index 0000000..b1753e9
--- /dev/null
@@ -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;
+}
index 0a23e07..399641c 100644 (file)
@@ -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);
 }
 
index b34cc6e..a56f1ff 100644 (file)
@@ -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 (file)
index 0000000..6bc7a86
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for encrypted keys
+#
+
+obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted.o ecryptfs_format.o
+obj-$(CONFIG_TRUSTED_KEYS) += masterkey_trusted.o
similarity index 97%
rename from security/keys/encrypted.c
rename to security/keys/encrypted-keys/encrypted.c
index e7eca9e..3f57795 100644 (file)
@@ -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;
        }
 
similarity index 81%
rename from security/keys/encrypted.h
rename to security/keys/encrypted-keys/encrypted.h
index cef5e2f..b6ade89 100644 (file)
@@ -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 (file)
index 0000000..a5da512
--- /dev/null
@@ -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;
+}
index 9ebda05..c1d6987 100644 (file)
@@ -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);
 }