diff options
Diffstat (limited to 'security/integrity/evm/evm_main.c')
| -rw-r--r-- | security/integrity/evm/evm_main.c | 78 |
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); |
