mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 22:02:28 +00:00
Merge branch 'next-evm' of git://github.com/mzohar/linux-evm into next
This commit is contained in:
commit
8de6ac7f58
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
26
security/integrity/evm/evm_posix_acl.c
Normal file
26
security/integrity/evm/evm_posix_acl.c
Normal file
@ -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;
|
||||
}
|
@ -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
|
||||
|
6
security/keys/encrypted-keys/Makefile
Normal file
6
security/keys/encrypted-keys/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for encrypted keys
|
||||
#
|
||||
|
||||
obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted.o ecryptfs_format.o
|
||||
obj-$(CONFIG_TRUSTED_KEYS) += masterkey_trusted.o
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
44
security/keys/encrypted-keys/masterkey_trusted.c
Normal file
44
security/keys/encrypted-keys/masterkey_trusted.c
Normal file
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user