|
From: Mikhail K. <vie...@vi...> - 2017-01-13 04:28:16
|
This patch provide "immutable" version of standard EVM digital signature, that never being converted into HMAC.
Signed-off-by: Mikhail Kurinnoi <vie...@vi...>
security/integrity/digsig.c | 1 +
security/integrity/evm/evm.h | 6 ++++++
security/integrity/evm/evm_main.c | 36 +++++++++++++++++++++++++++++++-----
3 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index 106e855..c5e6a68 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -71,6 +71,7 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
return digsig_verify(keyring[id], sig + 1, siglen - 1,
digest, digestlen);
case 2:
+ case 4:
return asymmetric_verify(keyring[id], sig, siglen,
digest, digestlen);
}
diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h
index f5f1272..159509d 100644
--- a/security/integrity/evm/evm.h
+++ b/security/integrity/evm/evm.h
@@ -38,6 +38,12 @@ extern struct crypto_shash *hash_tfm;
/* List of EVM protected security xattrs */
extern char *evm_config_xattrnames[];
+enum evm_xattr_version {
+ EVM_XATTR_VER_NOTSUPP = 0,
+ EVM_XATTR_VER_STANDARD = 2,
+ EVM_XATTR_VER_IMMUTABLE = 4
+};
+
int evm_init_key(void);
int evm_update_evmxattr(struct dentry *dentry,
const char *req_xattr_name,
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index e2ed498..88d5946 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -116,6 +116,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
struct evm_ima_xattr_data *xattr_data = NULL;
struct evm_ima_xattr_data calc;
enum integrity_status evm_status = INTEGRITY_PASS;
+ enum evm_xattr_version version;
int rc, xattr_len;
if (iint && iint->evm_status == INTEGRITY_PASS)
@@ -159,6 +160,9 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
rc = -EINVAL;
break;
case EVM_IMA_XATTR_DIGSIG:
+ if (xattr_len <= 2)
+ break;
+ version = ((const char *)xattr_data)[1];
rc = evm_calc_hash(dentry, xattr_name, xattr_value,
xattr_value_len, calc.digest);
if (rc)
@@ -171,7 +175,8 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
* not immutable
*/
if (!IS_RDONLY(d_backing_inode(dentry)) &&
- !IS_IMMUTABLE(d_backing_inode(dentry)))
+ !IS_IMMUTABLE(d_backing_inode(dentry)) &&
+ (version != EVM_XATTR_VER_IMMUTABLE))
evm_update_evmxattr(dentry, xattr_name,
xattr_value,
xattr_value_len);
@@ -372,6 +377,24 @@ static void evm_reset_status(struct inode *inode)
iint->evm_status = INTEGRITY_UNKNOWN;
}
+static bool evm_immutable_xattr(struct dentry *dentry)
+{
+ char *xattr_data = NULL;
+ bool result = true;
+ int rc;
+
+ rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, &xattr_data, 0,
+ GFP_NOFS);
+ if ((rc <= 0) ||
+ (xattr_data[0] != EVM_IMA_XATTR_DIGSIG) ||
+ ((rc >= 2) && (xattr_data[1] != EVM_XATTR_VER_IMMUTABLE)))
+ result = false;
+
+ if (xattr_data)
+ kfree(xattr_data);
+ return result;
+}
+
/**
* evm_inode_post_setxattr - update 'security.evm' to reflect the changes
* @dentry: pointer to the affected dentry
@@ -388,8 +411,9 @@ static void evm_reset_status(struct inode *inode)
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)
- && !posix_xattr_acl(xattr_name)))
+ if (!evm_initialized ||
+ (!evm_protected_xattr(xattr_name) && !posix_xattr_acl(xattr_name)) ||
+ evm_immutable_xattr(dentry))
return;
evm_reset_status(dentry->d_inode);
@@ -409,7 +433,8 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
*/
void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
{
- if (!evm_initialized || !evm_protected_xattr(xattr_name))
+ if (!evm_initialized || !evm_protected_xattr(xattr_name)
+ || evm_immutable_xattr(dentry))
return;
evm_reset_status(dentry->d_inode);
@@ -454,7 +479,8 @@ void evm_inode_post_setattr(struct dentry *dentry, int ia_valid)
if (!evm_initialized)
return;
- if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
+ if ((ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) &&
+ !evm_immutable_xattr(dentry))
evm_update_evmxattr(dentry, NULL, NULL, 0);
}
|