summaryrefslogtreecommitdiff
path: root/security/integrity/evm/evm_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/integrity/evm/evm_main.c')
-rw-r--r--security/integrity/evm/evm_main.c78
1 files changed, 65 insertions, 13 deletions
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 377e57e9084f..b59e3f121b8a 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -72,17 +72,25 @@ static struct xattr_list evm_config_default_xattrnames[] = {
LIST_HEAD(evm_config_xattrnames);
+static char *evm_cmdline __initdata;
+core_param(evm, evm_cmdline, charp, 0);
+
static int evm_fixmode __ro_after_init;
-static int __init evm_set_fixmode(char *str)
+static void __init evm_set_fixmode(void)
{
- if (strncmp(str, "fix", 3) == 0)
- evm_fixmode = 1;
- else
- pr_err("invalid \"%s\" mode", str);
+ if (!evm_cmdline)
+ return;
- return 1;
+ if (strncmp(evm_cmdline, "fix", 3) == 0) {
+ if (arch_get_secureboot()) {
+ pr_info("Secure boot enabled: ignoring evm=fix");
+ return;
+ }
+ evm_fixmode = 1;
+ } else {
+ pr_err("invalid \"%s\" mode", evm_cmdline);
+ }
}
-__setup("evm=", evm_set_fixmode);
static void __init evm_init_config(void)
{
@@ -128,6 +136,14 @@ static bool evm_hmac_disabled(void)
return true;
}
+static bool evm_sigv3_required(void)
+{
+ if (evm_initialized & EVM_SIGV3_REQUIRED)
+ return true;
+
+ return false;
+}
+
static int evm_find_protected_xattrs(struct dentry *dentry)
{
struct inode *inode = d_backing_inode(dentry);
@@ -169,7 +185,7 @@ static int is_unsupported_hmac_fs(struct dentry *dentry)
* and compare it against the stored security.evm xattr.
*
* For performance:
- * - use the previoulsy retrieved xattr value and length to calculate the
+ * - use the previously retrieved xattr value and length to calculate the
* HMAC.)
* - cache the verification result in the iint, when available.
*
@@ -250,6 +266,12 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
}
hdr = (struct signature_v2_hdr *)xattr_data;
+
+ if (evm_sigv3_required() && hdr->version != 3) {
+ evm_status = INTEGRITY_FAIL;
+ goto out;
+ }
+
digest.hdr.algo = hdr->hash_algo;
rc = evm_calc_hash(dentry, xattr_name, xattr_value,
xattr_value_len, xattr_data->type, &digest,
@@ -258,7 +280,8 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
break;
rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
(const char *)xattr_data, xattr_len,
- digest.digest, digest.hdr.length);
+ digest.digest, digest.hdr.length,
+ digest.hdr.algo);
if (!rc) {
if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) {
if (iint)
@@ -788,6 +811,34 @@ bool evm_revalidate_status(const char *xattr_name)
}
/**
+ * evm_fix_hmac - Calculate the HMAC and add it to security.evm for fix mode
+ * @dentry: pointer to the affected dentry which doesn't yet have security.evm
+ * xattr
+ * @xattr_name: pointer to the affected extended attribute name
+ * @xattr_value: pointer to the new extended attribute value
+ * @xattr_value_len: pointer to the new extended attribute value length
+ *
+ * Expects to be called with i_mutex locked.
+ *
+ * Return: 0 on success, -EPERM/-ENOMEM/-EOPNOTSUPP on failure
+ */
+int evm_fix_hmac(struct dentry *dentry, const char *xattr_name,
+ const char *xattr_value, size_t xattr_value_len)
+
+{
+ if (!evm_fixmode || !evm_revalidate_status((xattr_name)))
+ return -EPERM;
+
+ if (!(evm_initialized & EVM_INIT_HMAC))
+ return -EPERM;
+
+ if (is_unsupported_hmac_fs(dentry))
+ return -EOPNOTSUPP;
+
+ return evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len);
+}
+
+/**
* evm_inode_post_setxattr - update 'security.evm' to reflect the changes
* @dentry: pointer to the affected dentry
* @xattr_name: pointer to the affected extended attribute name
@@ -1045,7 +1096,7 @@ int evm_inode_init_security(struct inode *inode, struct inode *dir,
"%s: xattrs terminator is not the first non-filled slot\n",
__func__);
- xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS);
+ xattr_data = kzalloc_obj(*xattr_data, GFP_NOFS);
if (!xattr_data)
return -ENOMEM;
@@ -1119,6 +1170,8 @@ static int __init init_evm(void)
evm_init_config();
+ evm_set_fixmode();
+
error = integrity_init_keyring(INTEGRITY_KEYRING_EVM);
if (error)
goto error;
@@ -1175,10 +1228,9 @@ struct lsm_blob_sizes evm_blob_sizes __ro_after_init = {
};
DEFINE_LSM(evm) = {
- .name = "evm",
+ .id = &evm_lsmid,
.init = init_evm_lsm,
.order = LSM_ORDER_LAST,
.blobs = &evm_blob_sizes,
+ .initcall_late = init_evm,
};
-
-late_initcall(init_evm);