1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 266dbc325SMimi Zohar /* 366dbc325SMimi Zohar * Copyright (C) 2005-2010 IBM Corporation 466dbc325SMimi Zohar * 566dbc325SMimi Zohar * Author: 666dbc325SMimi Zohar * Mimi Zohar <zohar@us.ibm.com> 766dbc325SMimi Zohar * Kylene Hall <kjhall@us.ibm.com> 866dbc325SMimi Zohar * 966dbc325SMimi Zohar * File: evm_main.c 1066dbc325SMimi Zohar * implements evm_inode_setxattr, evm_inode_post_setxattr, 1166dbc325SMimi Zohar * evm_inode_removexattr, and evm_verifyxattr 1266dbc325SMimi Zohar */ 1366dbc325SMimi Zohar 143aafb1fbSPaul Gortmaker #include <linux/init.h> 1566dbc325SMimi Zohar #include <linux/crypto.h> 169b97b6cdSMimi Zohar #include <linux/audit.h> 1766dbc325SMimi Zohar #include <linux/xattr.h> 1866dbc325SMimi Zohar #include <linux/integrity.h> 193e1be52dSMimi Zohar #include <linux/evm.h> 2050d34394SIngo Molnar #include <linux/magic.h> 2150d34394SIngo Molnar 22d46eb369SDmitry Kasatkin #include <crypto/hash.h> 235feeb611SMatthew Garrett #include <crypto/hash_info.h> 24613317bdSRyan Ware #include <crypto/algapi.h> 2566dbc325SMimi Zohar #include "evm.h" 2666dbc325SMimi Zohar 2766dbc325SMimi Zohar int evm_initialized; 2866dbc325SMimi Zohar 2917d7b0afSHernán Gonzalez static const char * const integrity_status_msg[] = { 3050b97748SMatthew Garrett "pass", "pass_immutable", "fail", "no_label", "no_xattrs", "unknown" 319b97b6cdSMimi Zohar }; 32d3b33679SDmitry Kasatkin int evm_hmac_attrs; 3366dbc325SMimi Zohar 34fa516b66SMatthew Garrett static struct xattr_list evm_config_default_xattrnames[] = { 3566dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SELINUX 3621af7663SMatthew Garrett {.name = XATTR_NAME_SELINUX}, 3766dbc325SMimi Zohar #endif 3866dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SMACK 3921af7663SMatthew Garrett {.name = XATTR_NAME_SMACK}, 403e38df56SDmitry Kasatkin #ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS 4121af7663SMatthew Garrett {.name = XATTR_NAME_SMACKEXEC}, 4221af7663SMatthew Garrett {.name = XATTR_NAME_SMACKTRANSMUTE}, 4321af7663SMatthew Garrett {.name = XATTR_NAME_SMACKMMAP}, 443e38df56SDmitry Kasatkin #endif 4566dbc325SMimi Zohar #endif 46096b8546SMatthew Garrett #ifdef CONFIG_SECURITY_APPARMOR 4721af7663SMatthew Garrett {.name = XATTR_NAME_APPARMOR}, 48096b8546SMatthew Garrett #endif 492fe5d6deSMimi Zohar #ifdef CONFIG_IMA_APPRAISE 5021af7663SMatthew Garrett {.name = XATTR_NAME_IMA}, 512fe5d6deSMimi Zohar #endif 5221af7663SMatthew Garrett {.name = XATTR_NAME_CAPS}, 5366dbc325SMimi Zohar }; 5466dbc325SMimi Zohar 5521af7663SMatthew Garrett LIST_HEAD(evm_config_xattrnames); 5621af7663SMatthew Garrett 577102ebcdSMimi Zohar static int evm_fixmode; 587102ebcdSMimi Zohar static int __init evm_set_fixmode(char *str) 597102ebcdSMimi Zohar { 607102ebcdSMimi Zohar if (strncmp(str, "fix", 3) == 0) 617102ebcdSMimi Zohar evm_fixmode = 1; 627fe2bb7eSBruno Meneguele else 637fe2bb7eSBruno Meneguele pr_err("invalid \"%s\" mode", str); 647fe2bb7eSBruno Meneguele 657102ebcdSMimi Zohar return 0; 667102ebcdSMimi Zohar } 677102ebcdSMimi Zohar __setup("evm=", evm_set_fixmode); 687102ebcdSMimi Zohar 69d3b33679SDmitry Kasatkin static void __init evm_init_config(void) 70d3b33679SDmitry Kasatkin { 7121af7663SMatthew Garrett int i, xattrs; 7221af7663SMatthew Garrett 7321af7663SMatthew Garrett xattrs = ARRAY_SIZE(evm_config_default_xattrnames); 7421af7663SMatthew Garrett 7521af7663SMatthew Garrett pr_info("Initialising EVM extended attributes:\n"); 7621af7663SMatthew Garrett for (i = 0; i < xattrs; i++) { 7721af7663SMatthew Garrett pr_info("%s\n", evm_config_default_xattrnames[i].name); 7821af7663SMatthew Garrett list_add_tail(&evm_config_default_xattrnames[i].list, 7921af7663SMatthew Garrett &evm_config_xattrnames); 8021af7663SMatthew Garrett } 8121af7663SMatthew Garrett 82d3b33679SDmitry Kasatkin #ifdef CONFIG_EVM_ATTR_FSUUID 83d3b33679SDmitry Kasatkin evm_hmac_attrs |= EVM_ATTR_FSUUID; 84d3b33679SDmitry Kasatkin #endif 85d3b33679SDmitry Kasatkin pr_info("HMAC attrs: 0x%x\n", evm_hmac_attrs); 86d3b33679SDmitry Kasatkin } 87d3b33679SDmitry Kasatkin 88ae1ba167SMatthew Garrett static bool evm_key_loaded(void) 89ae1ba167SMatthew Garrett { 90ae1ba167SMatthew Garrett return (bool)(evm_initialized & EVM_KEY_MASK); 91ae1ba167SMatthew Garrett } 92ae1ba167SMatthew Garrett 93*4a804b8aSRoberto Sassu /* 94*4a804b8aSRoberto Sassu * This function determines whether or not it is safe to ignore verification 95*4a804b8aSRoberto Sassu * errors, based on the ability of EVM to calculate HMACs. If the HMAC key 96*4a804b8aSRoberto Sassu * is not loaded, and it cannot be loaded in the future due to the 97*4a804b8aSRoberto Sassu * EVM_SETUP_COMPLETE initialization flag, allowing an operation despite the 98*4a804b8aSRoberto Sassu * attrs/xattrs being found invalid will not make them valid. 99*4a804b8aSRoberto Sassu */ 100*4a804b8aSRoberto Sassu static bool evm_hmac_disabled(void) 101*4a804b8aSRoberto Sassu { 102*4a804b8aSRoberto Sassu if (evm_initialized & EVM_INIT_HMAC) 103*4a804b8aSRoberto Sassu return false; 104*4a804b8aSRoberto Sassu 105*4a804b8aSRoberto Sassu if (!(evm_initialized & EVM_SETUP_COMPLETE)) 106*4a804b8aSRoberto Sassu return false; 107*4a804b8aSRoberto Sassu 108*4a804b8aSRoberto Sassu return true; 109*4a804b8aSRoberto Sassu } 110*4a804b8aSRoberto Sassu 11115647eb3SDmitry Kasatkin static int evm_find_protected_xattrs(struct dentry *dentry) 11215647eb3SDmitry Kasatkin { 113c6f493d6SDavid Howells struct inode *inode = d_backing_inode(dentry); 11421af7663SMatthew Garrett struct xattr_list *xattr; 11515647eb3SDmitry Kasatkin int error; 11615647eb3SDmitry Kasatkin int count = 0; 11715647eb3SDmitry Kasatkin 1185d6c3191SAndreas Gruenbacher if (!(inode->i_opflags & IOP_XATTR)) 11915647eb3SDmitry Kasatkin return -EOPNOTSUPP; 12015647eb3SDmitry Kasatkin 121770f6058SMadhuparna Bhowmik list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) { 12221af7663SMatthew Garrett error = __vfs_getxattr(dentry, inode, xattr->name, NULL, 0); 12315647eb3SDmitry Kasatkin if (error < 0) { 12415647eb3SDmitry Kasatkin if (error == -ENODATA) 12515647eb3SDmitry Kasatkin continue; 12615647eb3SDmitry Kasatkin return error; 12715647eb3SDmitry Kasatkin } 12815647eb3SDmitry Kasatkin count++; 12915647eb3SDmitry Kasatkin } 13015647eb3SDmitry Kasatkin 13115647eb3SDmitry Kasatkin return count; 13215647eb3SDmitry Kasatkin } 13315647eb3SDmitry Kasatkin 13466dbc325SMimi Zohar /* 13566dbc325SMimi Zohar * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr 13666dbc325SMimi Zohar * 13766dbc325SMimi Zohar * Compute the HMAC on the dentry's protected set of extended attributes 1387102ebcdSMimi Zohar * and compare it against the stored security.evm xattr. 1397102ebcdSMimi Zohar * 1407102ebcdSMimi Zohar * For performance: 1417102ebcdSMimi Zohar * - use the previoulsy retrieved xattr value and length to calculate the 14266dbc325SMimi Zohar * HMAC.) 1437102ebcdSMimi Zohar * - cache the verification result in the iint, when available. 14466dbc325SMimi Zohar * 14566dbc325SMimi Zohar * Returns integrity status 14666dbc325SMimi Zohar */ 14766dbc325SMimi Zohar static enum integrity_status evm_verify_hmac(struct dentry *dentry, 14866dbc325SMimi Zohar const char *xattr_name, 14966dbc325SMimi Zohar char *xattr_value, 15066dbc325SMimi Zohar size_t xattr_value_len, 15166dbc325SMimi Zohar struct integrity_iint_cache *iint) 15266dbc325SMimi Zohar { 15315647eb3SDmitry Kasatkin struct evm_ima_xattr_data *xattr_data = NULL; 1545feeb611SMatthew Garrett struct signature_v2_hdr *hdr; 155566be59aSMimi Zohar enum integrity_status evm_status = INTEGRITY_PASS; 1565feeb611SMatthew Garrett struct evm_digest digest; 15770946c4aSSascha Hauer struct inode *inode; 15815647eb3SDmitry Kasatkin int rc, xattr_len; 15966dbc325SMimi Zohar 16050b97748SMatthew Garrett if (iint && (iint->evm_status == INTEGRITY_PASS || 16150b97748SMatthew Garrett iint->evm_status == INTEGRITY_PASS_IMMUTABLE)) 16224e0198eSDmitry Kasatkin return iint->evm_status; 16366dbc325SMimi Zohar 1646d38ca01SDmitry Kasatkin /* if status is not PASS, try to check again - against -ENOMEM */ 1656d38ca01SDmitry Kasatkin 16615647eb3SDmitry Kasatkin /* first need to know the sig type */ 167c7c7a1a1STycho Andersen rc = vfs_getxattr_alloc(&init_user_ns, dentry, XATTR_NAME_EVM, 168c7c7a1a1STycho Andersen (char **)&xattr_data, 0, GFP_NOFS); 16915647eb3SDmitry Kasatkin if (rc <= 0) { 1701f100979SDmitry Kasatkin evm_status = INTEGRITY_FAIL; 1711f100979SDmitry Kasatkin if (rc == -ENODATA) { 17215647eb3SDmitry Kasatkin rc = evm_find_protected_xattrs(dentry); 17315647eb3SDmitry Kasatkin if (rc > 0) 17415647eb3SDmitry Kasatkin evm_status = INTEGRITY_NOLABEL; 17515647eb3SDmitry Kasatkin else if (rc == 0) 17615647eb3SDmitry Kasatkin evm_status = INTEGRITY_NOXATTRS; /* new file */ 1771f100979SDmitry Kasatkin } else if (rc == -EOPNOTSUPP) { 1781f100979SDmitry Kasatkin evm_status = INTEGRITY_UNKNOWN; 17915647eb3SDmitry Kasatkin } 180566be59aSMimi Zohar goto out; 181566be59aSMimi Zohar } 18266dbc325SMimi Zohar 183b1aaab22SDmitry Kasatkin xattr_len = rc; 18415647eb3SDmitry Kasatkin 18515647eb3SDmitry Kasatkin /* check value type */ 18615647eb3SDmitry Kasatkin switch (xattr_data->type) { 18715647eb3SDmitry Kasatkin case EVM_XATTR_HMAC: 188650b29dbSThiago Jung Bauermann if (xattr_len != sizeof(struct evm_xattr)) { 189b4bfec7fSSeth Forshee evm_status = INTEGRITY_FAIL; 190b4bfec7fSSeth Forshee goto out; 191b4bfec7fSSeth Forshee } 1925feeb611SMatthew Garrett 1935feeb611SMatthew Garrett digest.hdr.algo = HASH_ALGO_SHA1; 19415647eb3SDmitry Kasatkin rc = evm_calc_hmac(dentry, xattr_name, xattr_value, 1955feeb611SMatthew Garrett xattr_value_len, &digest); 19615647eb3SDmitry Kasatkin if (rc) 19715647eb3SDmitry Kasatkin break; 198650b29dbSThiago Jung Bauermann rc = crypto_memneq(xattr_data->data, digest.digest, 1995feeb611SMatthew Garrett SHA1_DIGEST_SIZE); 20015647eb3SDmitry Kasatkin if (rc) 20115647eb3SDmitry Kasatkin rc = -EINVAL; 20215647eb3SDmitry Kasatkin break; 20315647eb3SDmitry Kasatkin case EVM_IMA_XATTR_DIGSIG: 20450b97748SMatthew Garrett case EVM_XATTR_PORTABLE_DIGSIG: 205455b6c91SRoberto Sassu /* accept xattr with non-empty signature field */ 206455b6c91SRoberto Sassu if (xattr_len <= sizeof(struct signature_v2_hdr)) { 207455b6c91SRoberto Sassu evm_status = INTEGRITY_FAIL; 208455b6c91SRoberto Sassu goto out; 209455b6c91SRoberto Sassu } 210455b6c91SRoberto Sassu 2115feeb611SMatthew Garrett hdr = (struct signature_v2_hdr *)xattr_data; 2125feeb611SMatthew Garrett digest.hdr.algo = hdr->hash_algo; 21315647eb3SDmitry Kasatkin rc = evm_calc_hash(dentry, xattr_name, xattr_value, 2145feeb611SMatthew Garrett xattr_value_len, xattr_data->type, &digest); 21515647eb3SDmitry Kasatkin if (rc) 21615647eb3SDmitry Kasatkin break; 21715647eb3SDmitry Kasatkin rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM, 218b1aaab22SDmitry Kasatkin (const char *)xattr_data, xattr_len, 2195feeb611SMatthew Garrett digest.digest, digest.hdr.length); 22015647eb3SDmitry Kasatkin if (!rc) { 22170946c4aSSascha Hauer inode = d_backing_inode(dentry); 22270946c4aSSascha Hauer 22350b97748SMatthew Garrett if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) { 22450b97748SMatthew Garrett if (iint) 22550b97748SMatthew Garrett iint->flags |= EVM_IMMUTABLE_DIGSIG; 22650b97748SMatthew Garrett evm_status = INTEGRITY_PASS_IMMUTABLE; 22770946c4aSSascha Hauer } else if (!IS_RDONLY(inode) && 22870946c4aSSascha Hauer !(inode->i_sb->s_readonly_remount) && 22970946c4aSSascha Hauer !IS_IMMUTABLE(inode)) { 230c2baec7fSDmitry Kasatkin evm_update_evmxattr(dentry, xattr_name, 231c2baec7fSDmitry Kasatkin xattr_value, 23215647eb3SDmitry Kasatkin xattr_value_len); 23315647eb3SDmitry Kasatkin } 23450b97748SMatthew Garrett } 23515647eb3SDmitry Kasatkin break; 23615647eb3SDmitry Kasatkin default: 23715647eb3SDmitry Kasatkin rc = -EINVAL; 23815647eb3SDmitry Kasatkin break; 23915647eb3SDmitry Kasatkin } 24015647eb3SDmitry Kasatkin 24115647eb3SDmitry Kasatkin if (rc) 24215647eb3SDmitry Kasatkin evm_status = (rc == -ENODATA) ? 24315647eb3SDmitry Kasatkin INTEGRITY_NOXATTRS : INTEGRITY_FAIL; 2447102ebcdSMimi Zohar out: 2457102ebcdSMimi Zohar if (iint) 2467102ebcdSMimi Zohar iint->evm_status = evm_status; 24715647eb3SDmitry Kasatkin kfree(xattr_data); 2487102ebcdSMimi Zohar return evm_status; 24966dbc325SMimi Zohar } 25066dbc325SMimi Zohar 25166dbc325SMimi Zohar static int evm_protected_xattr(const char *req_xattr_name) 25266dbc325SMimi Zohar { 25366dbc325SMimi Zohar int namelen; 25466dbc325SMimi Zohar int found = 0; 25521af7663SMatthew Garrett struct xattr_list *xattr; 25666dbc325SMimi Zohar 25766dbc325SMimi Zohar namelen = strlen(req_xattr_name); 258770f6058SMadhuparna Bhowmik list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) { 25921af7663SMatthew Garrett if ((strlen(xattr->name) == namelen) 26021af7663SMatthew Garrett && (strncmp(req_xattr_name, xattr->name, namelen) == 0)) { 26166dbc325SMimi Zohar found = 1; 26266dbc325SMimi Zohar break; 26366dbc325SMimi Zohar } 264cb723180SMimi Zohar if (strncmp(req_xattr_name, 26521af7663SMatthew Garrett xattr->name + XATTR_SECURITY_PREFIX_LEN, 266cb723180SMimi Zohar strlen(req_xattr_name)) == 0) { 267cb723180SMimi Zohar found = 1; 268cb723180SMimi Zohar break; 269cb723180SMimi Zohar } 27066dbc325SMimi Zohar } 27121af7663SMatthew Garrett 27266dbc325SMimi Zohar return found; 27366dbc325SMimi Zohar } 27466dbc325SMimi Zohar 27566dbc325SMimi Zohar /** 27666dbc325SMimi Zohar * evm_verifyxattr - verify the integrity of the requested xattr 27766dbc325SMimi Zohar * @dentry: object of the verify xattr 27866dbc325SMimi Zohar * @xattr_name: requested xattr 27966dbc325SMimi Zohar * @xattr_value: requested xattr value 28066dbc325SMimi Zohar * @xattr_value_len: requested xattr value length 28166dbc325SMimi Zohar * 28266dbc325SMimi Zohar * Calculate the HMAC for the given dentry and verify it against the stored 28366dbc325SMimi Zohar * security.evm xattr. For performance, use the xattr value and length 28466dbc325SMimi Zohar * previously retrieved to calculate the HMAC. 28566dbc325SMimi Zohar * 28666dbc325SMimi Zohar * Returns the xattr integrity status. 28766dbc325SMimi Zohar * 28866dbc325SMimi Zohar * This function requires the caller to lock the inode's i_mutex before it 28966dbc325SMimi Zohar * is executed. 29066dbc325SMimi Zohar */ 29166dbc325SMimi Zohar enum integrity_status evm_verifyxattr(struct dentry *dentry, 29266dbc325SMimi Zohar const char *xattr_name, 2932960e6cbSDmitry Kasatkin void *xattr_value, size_t xattr_value_len, 2942960e6cbSDmitry Kasatkin struct integrity_iint_cache *iint) 29566dbc325SMimi Zohar { 296ae1ba167SMatthew Garrett if (!evm_key_loaded() || !evm_protected_xattr(xattr_name)) 29766dbc325SMimi Zohar return INTEGRITY_UNKNOWN; 29866dbc325SMimi Zohar 2992960e6cbSDmitry Kasatkin if (!iint) { 300c6f493d6SDavid Howells iint = integrity_iint_find(d_backing_inode(dentry)); 30166dbc325SMimi Zohar if (!iint) 30266dbc325SMimi Zohar return INTEGRITY_UNKNOWN; 3032960e6cbSDmitry Kasatkin } 3042960e6cbSDmitry Kasatkin return evm_verify_hmac(dentry, xattr_name, xattr_value, 30566dbc325SMimi Zohar xattr_value_len, iint); 30666dbc325SMimi Zohar } 30766dbc325SMimi Zohar EXPORT_SYMBOL_GPL(evm_verifyxattr); 30866dbc325SMimi Zohar 30966dbc325SMimi Zohar /* 3107102ebcdSMimi Zohar * evm_verify_current_integrity - verify the dentry's metadata integrity 3117102ebcdSMimi Zohar * @dentry: pointer to the affected dentry 3127102ebcdSMimi Zohar * 3137102ebcdSMimi Zohar * Verify and return the dentry's metadata integrity. The exceptions are 3147102ebcdSMimi Zohar * before EVM is initialized or in 'fix' mode. 3157102ebcdSMimi Zohar */ 3167102ebcdSMimi Zohar static enum integrity_status evm_verify_current_integrity(struct dentry *dentry) 3177102ebcdSMimi Zohar { 318c6f493d6SDavid Howells struct inode *inode = d_backing_inode(dentry); 3197102ebcdSMimi Zohar 320ae1ba167SMatthew Garrett if (!evm_key_loaded() || !S_ISREG(inode->i_mode) || evm_fixmode) 3217102ebcdSMimi Zohar return 0; 3227102ebcdSMimi Zohar return evm_verify_hmac(dentry, NULL, NULL, 0, NULL); 3237102ebcdSMimi Zohar } 3247102ebcdSMimi Zohar 325a924ce0bSMimi Zohar /* 326a924ce0bSMimi Zohar * evm_protect_xattr - protect the EVM extended attribute 327a924ce0bSMimi Zohar * 328bf6d0f5dSMimi Zohar * Prevent security.evm from being modified or removed without the 329bf6d0f5dSMimi Zohar * necessary permissions or when the existing value is invalid. 330bf6d0f5dSMimi Zohar * 331bf6d0f5dSMimi Zohar * The posix xattr acls are 'system' prefixed, which normally would not 332bf6d0f5dSMimi Zohar * affect security.evm. An interesting side affect of writing posix xattr 333bf6d0f5dSMimi Zohar * acls is their modifying of the i_mode, which is included in security.evm. 334bf6d0f5dSMimi Zohar * For posix xattr acls only, permit security.evm, even if it currently 33550b97748SMatthew Garrett * doesn't exist, to be updated unless the EVM signature is immutable. 336a924ce0bSMimi Zohar */ 337a924ce0bSMimi Zohar static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, 338a924ce0bSMimi Zohar const void *xattr_value, size_t xattr_value_len) 339a924ce0bSMimi Zohar { 340a924ce0bSMimi Zohar enum integrity_status evm_status; 341a924ce0bSMimi Zohar 342a924ce0bSMimi Zohar if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { 343a924ce0bSMimi Zohar if (!capable(CAP_SYS_ADMIN)) 344a924ce0bSMimi Zohar return -EPERM; 345bf6d0f5dSMimi Zohar } else if (!evm_protected_xattr(xattr_name)) { 346bf6d0f5dSMimi Zohar if (!posix_xattr_acl(xattr_name)) 347a924ce0bSMimi Zohar return 0; 348bf6d0f5dSMimi Zohar evm_status = evm_verify_current_integrity(dentry); 349bf6d0f5dSMimi Zohar if ((evm_status == INTEGRITY_PASS) || 350566be59aSMimi Zohar (evm_status == INTEGRITY_NOXATTRS)) 351bf6d0f5dSMimi Zohar return 0; 3529b97b6cdSMimi Zohar goto out; 353bf6d0f5dSMimi Zohar } 354ae1ba167SMatthew Garrett 355a924ce0bSMimi Zohar evm_status = evm_verify_current_integrity(dentry); 3563dcbad52SDmitry Kasatkin if (evm_status == INTEGRITY_NOXATTRS) { 3573dcbad52SDmitry Kasatkin struct integrity_iint_cache *iint; 3583dcbad52SDmitry Kasatkin 359*4a804b8aSRoberto Sassu /* Exception if the HMAC is not going to be calculated. */ 360*4a804b8aSRoberto Sassu if (evm_hmac_disabled()) 361*4a804b8aSRoberto Sassu return 0; 362*4a804b8aSRoberto Sassu 363c6f493d6SDavid Howells iint = integrity_iint_find(d_backing_inode(dentry)); 3643dcbad52SDmitry Kasatkin if (iint && (iint->flags & IMA_NEW_FILE)) 3653dcbad52SDmitry Kasatkin return 0; 3665101a185SMimi Zohar 3675101a185SMimi Zohar /* exception for pseudo filesystems */ 368fc64005cSAl Viro if (dentry->d_sb->s_magic == TMPFS_MAGIC 369fc64005cSAl Viro || dentry->d_sb->s_magic == SYSFS_MAGIC) 3705101a185SMimi Zohar return 0; 3715101a185SMimi Zohar 3725101a185SMimi Zohar integrity_audit_msg(AUDIT_INTEGRITY_METADATA, 3735101a185SMimi Zohar dentry->d_inode, dentry->d_name.name, 3745101a185SMimi Zohar "update_metadata", 3755101a185SMimi Zohar integrity_status_msg[evm_status], 3765101a185SMimi Zohar -EPERM, 0); 3773dcbad52SDmitry Kasatkin } 3789b97b6cdSMimi Zohar out: 379*4a804b8aSRoberto Sassu /* Exception if the HMAC is not going to be calculated. */ 380*4a804b8aSRoberto Sassu if (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL || 381*4a804b8aSRoberto Sassu evm_status == INTEGRITY_UNKNOWN)) 382*4a804b8aSRoberto Sassu return 0; 3839b97b6cdSMimi Zohar if (evm_status != INTEGRITY_PASS) 384c6f493d6SDavid Howells integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry), 3859b97b6cdSMimi Zohar dentry->d_name.name, "appraise_metadata", 3869b97b6cdSMimi Zohar integrity_status_msg[evm_status], 3879b97b6cdSMimi Zohar -EPERM, 0); 388a924ce0bSMimi Zohar return evm_status == INTEGRITY_PASS ? 0 : -EPERM; 389a924ce0bSMimi Zohar } 390a924ce0bSMimi Zohar 39166dbc325SMimi Zohar /** 39266dbc325SMimi Zohar * evm_inode_setxattr - protect the EVM extended attribute 39366dbc325SMimi Zohar * @dentry: pointer to the affected dentry 39466dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 39566dbc325SMimi Zohar * @xattr_value: pointer to the new extended attribute value 39666dbc325SMimi Zohar * @xattr_value_len: pointer to the new extended attribute value length 39766dbc325SMimi Zohar * 3982fb1c9a4SMimi Zohar * Before allowing the 'security.evm' protected xattr to be updated, 3992fb1c9a4SMimi Zohar * verify the existing value is valid. As only the kernel should have 4002fb1c9a4SMimi Zohar * access to the EVM encrypted key needed to calculate the HMAC, prevent 4012fb1c9a4SMimi Zohar * userspace from writing HMAC value. Writing 'security.evm' requires 4022fb1c9a4SMimi Zohar * requires CAP_SYS_ADMIN privileges. 40366dbc325SMimi Zohar */ 40466dbc325SMimi Zohar int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name, 40566dbc325SMimi Zohar const void *xattr_value, size_t xattr_value_len) 40666dbc325SMimi Zohar { 4072fb1c9a4SMimi Zohar const struct evm_ima_xattr_data *xattr_data = xattr_value; 4082fb1c9a4SMimi Zohar 409ae1ba167SMatthew Garrett /* Policy permits modification of the protected xattrs even though 410ae1ba167SMatthew Garrett * there's no HMAC key loaded 411ae1ba167SMatthew Garrett */ 412ae1ba167SMatthew Garrett if (evm_initialized & EVM_ALLOW_METADATA_WRITES) 413ae1ba167SMatthew Garrett return 0; 414ae1ba167SMatthew Garrett 4153b1deef6SDmitry Kasatkin if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { 4163b1deef6SDmitry Kasatkin if (!xattr_value_len) 4173b1deef6SDmitry Kasatkin return -EINVAL; 41850b97748SMatthew Garrett if (xattr_data->type != EVM_IMA_XATTR_DIGSIG && 41950b97748SMatthew Garrett xattr_data->type != EVM_XATTR_PORTABLE_DIGSIG) 4202fb1c9a4SMimi Zohar return -EPERM; 4213b1deef6SDmitry Kasatkin } 422a924ce0bSMimi Zohar return evm_protect_xattr(dentry, xattr_name, xattr_value, 42366dbc325SMimi Zohar xattr_value_len); 42466dbc325SMimi Zohar } 42566dbc325SMimi Zohar 42666dbc325SMimi Zohar /** 42766dbc325SMimi Zohar * evm_inode_removexattr - protect the EVM extended attribute 42866dbc325SMimi Zohar * @dentry: pointer to the affected dentry 42966dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 43066dbc325SMimi Zohar * 4317102ebcdSMimi Zohar * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that 4327102ebcdSMimi Zohar * the current value is valid. 43366dbc325SMimi Zohar */ 43466dbc325SMimi Zohar int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name) 43566dbc325SMimi Zohar { 436ae1ba167SMatthew Garrett /* Policy permits modification of the protected xattrs even though 437ae1ba167SMatthew Garrett * there's no HMAC key loaded 438ae1ba167SMatthew Garrett */ 439ae1ba167SMatthew Garrett if (evm_initialized & EVM_ALLOW_METADATA_WRITES) 440ae1ba167SMatthew Garrett return 0; 441ae1ba167SMatthew Garrett 442a924ce0bSMimi Zohar return evm_protect_xattr(dentry, xattr_name, NULL, 0); 44366dbc325SMimi Zohar } 44466dbc325SMimi Zohar 445523b74b1SDmitry Kasatkin static void evm_reset_status(struct inode *inode) 446523b74b1SDmitry Kasatkin { 447523b74b1SDmitry Kasatkin struct integrity_iint_cache *iint; 448523b74b1SDmitry Kasatkin 449523b74b1SDmitry Kasatkin iint = integrity_iint_find(inode); 450523b74b1SDmitry Kasatkin if (iint) 451523b74b1SDmitry Kasatkin iint->evm_status = INTEGRITY_UNKNOWN; 452523b74b1SDmitry Kasatkin } 453523b74b1SDmitry Kasatkin 45466dbc325SMimi Zohar /** 455e3ccfe1aSRoberto Sassu * evm_revalidate_status - report whether EVM status re-validation is necessary 456e3ccfe1aSRoberto Sassu * @xattr_name: pointer to the affected extended attribute name 457e3ccfe1aSRoberto Sassu * 458e3ccfe1aSRoberto Sassu * Report whether callers of evm_verifyxattr() should re-validate the 459e3ccfe1aSRoberto Sassu * EVM status. 460e3ccfe1aSRoberto Sassu * 461e3ccfe1aSRoberto Sassu * Return true if re-validation is necessary, false otherwise. 462e3ccfe1aSRoberto Sassu */ 463e3ccfe1aSRoberto Sassu bool evm_revalidate_status(const char *xattr_name) 464e3ccfe1aSRoberto Sassu { 465e3ccfe1aSRoberto Sassu if (!evm_key_loaded()) 466e3ccfe1aSRoberto Sassu return false; 467e3ccfe1aSRoberto Sassu 468e3ccfe1aSRoberto Sassu /* evm_inode_post_setattr() passes NULL */ 469e3ccfe1aSRoberto Sassu if (!xattr_name) 470e3ccfe1aSRoberto Sassu return true; 471e3ccfe1aSRoberto Sassu 472e3ccfe1aSRoberto Sassu if (!evm_protected_xattr(xattr_name) && !posix_xattr_acl(xattr_name) && 473e3ccfe1aSRoberto Sassu strcmp(xattr_name, XATTR_NAME_EVM)) 474e3ccfe1aSRoberto Sassu return false; 475e3ccfe1aSRoberto Sassu 476e3ccfe1aSRoberto Sassu return true; 477e3ccfe1aSRoberto Sassu } 478e3ccfe1aSRoberto Sassu 479e3ccfe1aSRoberto Sassu /** 48066dbc325SMimi Zohar * evm_inode_post_setxattr - update 'security.evm' to reflect the changes 48166dbc325SMimi Zohar * @dentry: pointer to the affected dentry 48266dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 48366dbc325SMimi Zohar * @xattr_value: pointer to the new extended attribute value 48466dbc325SMimi Zohar * @xattr_value_len: pointer to the new extended attribute value length 48566dbc325SMimi Zohar * 48666dbc325SMimi Zohar * Update the HMAC stored in 'security.evm' to reflect the change. 48766dbc325SMimi Zohar * 48866dbc325SMimi Zohar * No need to take the i_mutex lock here, as this function is called from 48966dbc325SMimi Zohar * __vfs_setxattr_noperm(). The caller of which has taken the inode's 49066dbc325SMimi Zohar * i_mutex lock. 49166dbc325SMimi Zohar */ 49266dbc325SMimi Zohar void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, 49366dbc325SMimi Zohar const void *xattr_value, size_t xattr_value_len) 49466dbc325SMimi Zohar { 495e3ccfe1aSRoberto Sassu if (!evm_revalidate_status(xattr_name)) 49666dbc325SMimi Zohar return; 49766dbc325SMimi Zohar 498523b74b1SDmitry Kasatkin evm_reset_status(dentry->d_inode); 499523b74b1SDmitry Kasatkin 500e3ccfe1aSRoberto Sassu if (!strcmp(xattr_name, XATTR_NAME_EVM)) 501e3ccfe1aSRoberto Sassu return; 502e3ccfe1aSRoberto Sassu 503*4a804b8aSRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC)) 504*4a804b8aSRoberto Sassu return; 505*4a804b8aSRoberto Sassu 50666dbc325SMimi Zohar evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len); 50766dbc325SMimi Zohar } 50866dbc325SMimi Zohar 50966dbc325SMimi Zohar /** 51066dbc325SMimi Zohar * evm_inode_post_removexattr - update 'security.evm' after removing the xattr 51166dbc325SMimi Zohar * @dentry: pointer to the affected dentry 51266dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 51366dbc325SMimi Zohar * 51466dbc325SMimi Zohar * Update the HMAC stored in 'security.evm' to reflect removal of the xattr. 5157c51bb00SDmitry Kasatkin * 5167c51bb00SDmitry Kasatkin * No need to take the i_mutex lock here, as this function is called from 5177c51bb00SDmitry Kasatkin * vfs_removexattr() which takes the i_mutex. 51866dbc325SMimi Zohar */ 51966dbc325SMimi Zohar void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) 52066dbc325SMimi Zohar { 521e3ccfe1aSRoberto Sassu if (!evm_revalidate_status(xattr_name)) 52266dbc325SMimi Zohar return; 52366dbc325SMimi Zohar 524523b74b1SDmitry Kasatkin evm_reset_status(dentry->d_inode); 525523b74b1SDmitry Kasatkin 526e3ccfe1aSRoberto Sassu if (!strcmp(xattr_name, XATTR_NAME_EVM)) 527e3ccfe1aSRoberto Sassu return; 528e3ccfe1aSRoberto Sassu 529*4a804b8aSRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC)) 530*4a804b8aSRoberto Sassu return; 531*4a804b8aSRoberto Sassu 53266dbc325SMimi Zohar evm_update_evmxattr(dentry, xattr_name, NULL, 0); 53366dbc325SMimi Zohar } 53466dbc325SMimi Zohar 53566dbc325SMimi Zohar /** 536817b54aaSMimi Zohar * evm_inode_setattr - prevent updating an invalid EVM extended attribute 537817b54aaSMimi Zohar * @dentry: pointer to the affected dentry 53850b97748SMatthew Garrett * 53950b97748SMatthew Garrett * Permit update of file attributes when files have a valid EVM signature, 54050b97748SMatthew Garrett * except in the case of them having an immutable portable signature. 541817b54aaSMimi Zohar */ 542817b54aaSMimi Zohar int evm_inode_setattr(struct dentry *dentry, struct iattr *attr) 543817b54aaSMimi Zohar { 544817b54aaSMimi Zohar unsigned int ia_valid = attr->ia_valid; 545817b54aaSMimi Zohar enum integrity_status evm_status; 546817b54aaSMimi Zohar 547ae1ba167SMatthew Garrett /* Policy permits modification of the protected attrs even though 548ae1ba167SMatthew Garrett * there's no HMAC key loaded 549ae1ba167SMatthew Garrett */ 550ae1ba167SMatthew Garrett if (evm_initialized & EVM_ALLOW_METADATA_WRITES) 551ae1ba167SMatthew Garrett return 0; 552ae1ba167SMatthew Garrett 553a924ce0bSMimi Zohar if (!(ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))) 554817b54aaSMimi Zohar return 0; 555817b54aaSMimi Zohar evm_status = evm_verify_current_integrity(dentry); 556566be59aSMimi Zohar if ((evm_status == INTEGRITY_PASS) || 557*4a804b8aSRoberto Sassu (evm_status == INTEGRITY_NOXATTRS) || 558*4a804b8aSRoberto Sassu (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL || 559*4a804b8aSRoberto Sassu evm_status == INTEGRITY_UNKNOWN))) 560566be59aSMimi Zohar return 0; 561c6f493d6SDavid Howells integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry), 5629b97b6cdSMimi Zohar dentry->d_name.name, "appraise_metadata", 5639b97b6cdSMimi Zohar integrity_status_msg[evm_status], -EPERM, 0); 564566be59aSMimi Zohar return -EPERM; 565817b54aaSMimi Zohar } 566817b54aaSMimi Zohar 567817b54aaSMimi Zohar /** 56866dbc325SMimi Zohar * evm_inode_post_setattr - update 'security.evm' after modifying metadata 56966dbc325SMimi Zohar * @dentry: pointer to the affected dentry 57066dbc325SMimi Zohar * @ia_valid: for the UID and GID status 57166dbc325SMimi Zohar * 57266dbc325SMimi Zohar * For now, update the HMAC stored in 'security.evm' to reflect UID/GID 57366dbc325SMimi Zohar * changes. 57466dbc325SMimi Zohar * 57566dbc325SMimi Zohar * This function is called from notify_change(), which expects the caller 57666dbc325SMimi Zohar * to lock the inode's i_mutex. 57766dbc325SMimi Zohar */ 57866dbc325SMimi Zohar void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) 57966dbc325SMimi Zohar { 580e3ccfe1aSRoberto Sassu if (!evm_revalidate_status(NULL)) 58166dbc325SMimi Zohar return; 58266dbc325SMimi Zohar 583e3ccfe1aSRoberto Sassu evm_reset_status(dentry->d_inode); 584e3ccfe1aSRoberto Sassu 585*4a804b8aSRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC)) 586*4a804b8aSRoberto Sassu return; 587*4a804b8aSRoberto Sassu 58866dbc325SMimi Zohar if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) 58966dbc325SMimi Zohar evm_update_evmxattr(dentry, NULL, NULL, 0); 59066dbc325SMimi Zohar } 59166dbc325SMimi Zohar 592cb723180SMimi Zohar /* 5939eea2904SRoberto Sassu * evm_inode_init_security - initializes security.evm HMAC value 594cb723180SMimi Zohar */ 595cb723180SMimi Zohar int evm_inode_init_security(struct inode *inode, 596cb723180SMimi Zohar const struct xattr *lsm_xattr, 597cb723180SMimi Zohar struct xattr *evm_xattr) 598cb723180SMimi Zohar { 599650b29dbSThiago Jung Bauermann struct evm_xattr *xattr_data; 600cb723180SMimi Zohar int rc; 601cb723180SMimi Zohar 6029eea2904SRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC) || 6039eea2904SRoberto Sassu !evm_protected_xattr(lsm_xattr->name)) 6045a4730baSMimi Zohar return 0; 605cb723180SMimi Zohar 606cb723180SMimi Zohar xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS); 607cb723180SMimi Zohar if (!xattr_data) 608cb723180SMimi Zohar return -ENOMEM; 609cb723180SMimi Zohar 610650b29dbSThiago Jung Bauermann xattr_data->data.type = EVM_XATTR_HMAC; 611cb723180SMimi Zohar rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest); 612cb723180SMimi Zohar if (rc < 0) 613cb723180SMimi Zohar goto out; 614cb723180SMimi Zohar 615cb723180SMimi Zohar evm_xattr->value = xattr_data; 616cb723180SMimi Zohar evm_xattr->value_len = sizeof(*xattr_data); 6179548906bSTetsuo Handa evm_xattr->name = XATTR_EVM_SUFFIX; 618cb723180SMimi Zohar return 0; 619cb723180SMimi Zohar out: 620cb723180SMimi Zohar kfree(xattr_data); 621cb723180SMimi Zohar return rc; 622cb723180SMimi Zohar } 623cb723180SMimi Zohar EXPORT_SYMBOL_GPL(evm_inode_init_security); 624cb723180SMimi Zohar 6252ce523ebSDmitry Kasatkin #ifdef CONFIG_EVM_LOAD_X509 6262ce523ebSDmitry Kasatkin void __init evm_load_x509(void) 6272ce523ebSDmitry Kasatkin { 62826ddabfeSDmitry Kasatkin int rc; 62926ddabfeSDmitry Kasatkin 63026ddabfeSDmitry Kasatkin rc = integrity_load_x509(INTEGRITY_KEYRING_EVM, CONFIG_EVM_X509_PATH); 63126ddabfeSDmitry Kasatkin if (!rc) 63226ddabfeSDmitry Kasatkin evm_initialized |= EVM_INIT_X509; 6332ce523ebSDmitry Kasatkin } 6342ce523ebSDmitry Kasatkin #endif 6352ce523ebSDmitry Kasatkin 63666dbc325SMimi Zohar static int __init init_evm(void) 63766dbc325SMimi Zohar { 63866dbc325SMimi Zohar int error; 63921af7663SMatthew Garrett struct list_head *pos, *q; 64066dbc325SMimi Zohar 641d3b33679SDmitry Kasatkin evm_init_config(); 642d3b33679SDmitry Kasatkin 643f4dc3778SDmitry Kasatkin error = integrity_init_keyring(INTEGRITY_KEYRING_EVM); 644f4dc3778SDmitry Kasatkin if (error) 64521af7663SMatthew Garrett goto error; 646f4dc3778SDmitry Kasatkin 64766dbc325SMimi Zohar error = evm_init_secfs(); 64866dbc325SMimi Zohar if (error < 0) { 64920ee451fSJoe Perches pr_info("Error registering secfs\n"); 65021af7663SMatthew Garrett goto error; 65121af7663SMatthew Garrett } 65221af7663SMatthew Garrett 65321af7663SMatthew Garrett error: 65421af7663SMatthew Garrett if (error != 0) { 65521af7663SMatthew Garrett if (!list_empty(&evm_config_xattrnames)) { 656c8b37524SYueHaibing list_for_each_safe(pos, q, &evm_config_xattrnames) 65721af7663SMatthew Garrett list_del(pos); 65821af7663SMatthew Garrett } 65921af7663SMatthew Garrett } 66021af7663SMatthew Garrett 661f4dc3778SDmitry Kasatkin return error; 66266dbc325SMimi Zohar } 66315647eb3SDmitry Kasatkin 66466dbc325SMimi Zohar late_initcall(init_evm); 665