Commit 8de6ac7f authored by James Morris's avatar James Morris

Merge branch 'next-evm' of git://github.com/mzohar/linux-evm into next

parents 843d183c fb788d8b
......@@ -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,
......
......@@ -16,6 +16,7 @@ enum integrity_status {
INTEGRITY_PASS = 0,
INTEGRITY_FAIL,
INTEGRITY_NOLABEL,
INTEGRITY_NOXATTRS,
INTEGRITY_UNKNOWN,
};
......
......@@ -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>
......
......@@ -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
......
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
......
......@@ -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
......@@ -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;
......@@ -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
......@@ -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,
return 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;
}
/**
......@@ -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;
}
/**
......
/*
* 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;
}
......@@ -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);
}
......
......@@ -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
#
# Makefile for encrypted keys
#
obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted.o ecryptfs_format.o
obj-$(CONFIG_TRUSTED_KEYS) += masterkey_trusted.o
......@@ -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
*
......@@ -469,6 +444,12 @@ static struct key *request_master_key(struct encrypted_key_payload *epayload,
goto out;
if (IS_ERR(mkey)) {
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;
......
......@@ -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)
......
/*
* 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;
}
......@@ -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);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment