Skip to content

Commit

Permalink
Merge branch 'next-evm' of git://github.com/mzohar/linux-evm into next
Browse files Browse the repository at this point in the history
  • Loading branch information
James Morris committed Sep 14, 2011
2 parents 843d183 + fb788d8 commit 8de6ac7
Show file tree
Hide file tree
Showing 17 changed files with 169 additions and 84 deletions.
8 changes: 8 additions & 0 deletions include/linux/evm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions include/linux/integrity.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ enum integrity_status {
INTEGRITY_PASS = 0,
INTEGRITY_FAIL,
INTEGRITY_NOLABEL,
INTEGRITY_NOXATTRS,
INTEGRITY_UNKNOWN,
};

Expand Down
5 changes: 5 additions & 0 deletions include/linux/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
4 changes: 3 additions & 1 deletion security/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions security/integrity/evm/Kconfig
Original file line number Diff line number Diff line change
@@ -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
Expand Down
1 change: 1 addition & 0 deletions security/integrity/evm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
102 changes: 51 additions & 51 deletions security/integrity/evm/evm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -158,21 +151,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
Expand All @@ -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
Expand All @@ -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);
}

/**
Expand All @@ -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);
}

/**
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}

/**
Expand Down
26 changes: 26 additions & 0 deletions security/integrity/evm/evm_posix_acl.c
Original file line number Diff line number Diff line change
@@ -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;
}
1 change: 1 addition & 0 deletions security/integrity/iint.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion security/keys/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 6 additions & 0 deletions security/keys/encrypted-keys/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#
# Makefile for encrypted keys
#

obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted.o ecryptfs_format.o
obj-$(CONFIG_TRUSTED_KEYS) += masterkey_trusted.o
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -298,31 +298,6 @@ static char *datablob_format(struct encrypted_key_payload *epayload,
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
*
Expand Down Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
44 changes: 44 additions & 0 deletions security/keys/encrypted-keys/masterkey_trusted.c
Original file line number Diff line number Diff line change
@@ -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;
}
Loading

0 comments on commit 8de6ac7

Please sign in to comment.