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[] = { 30*cdef685bSRoberto Sassu "pass", "pass_immutable", "fail", "fail_immutable", "no_label", 31*cdef685bSRoberto Sassu "no_xattrs", "unknown" 329b97b6cdSMimi Zohar }; 33d3b33679SDmitry Kasatkin int evm_hmac_attrs; 3466dbc325SMimi Zohar 35fa516b66SMatthew Garrett static struct xattr_list evm_config_default_xattrnames[] = { 3666dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SELINUX 3721af7663SMatthew Garrett {.name = XATTR_NAME_SELINUX}, 3866dbc325SMimi Zohar #endif 3966dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SMACK 4021af7663SMatthew Garrett {.name = XATTR_NAME_SMACK}, 413e38df56SDmitry Kasatkin #ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS 4221af7663SMatthew Garrett {.name = XATTR_NAME_SMACKEXEC}, 4321af7663SMatthew Garrett {.name = XATTR_NAME_SMACKTRANSMUTE}, 4421af7663SMatthew Garrett {.name = XATTR_NAME_SMACKMMAP}, 453e38df56SDmitry Kasatkin #endif 4666dbc325SMimi Zohar #endif 47096b8546SMatthew Garrett #ifdef CONFIG_SECURITY_APPARMOR 4821af7663SMatthew Garrett {.name = XATTR_NAME_APPARMOR}, 49096b8546SMatthew Garrett #endif 502fe5d6deSMimi Zohar #ifdef CONFIG_IMA_APPRAISE 5121af7663SMatthew Garrett {.name = XATTR_NAME_IMA}, 522fe5d6deSMimi Zohar #endif 5321af7663SMatthew Garrett {.name = XATTR_NAME_CAPS}, 5466dbc325SMimi Zohar }; 5566dbc325SMimi Zohar 5621af7663SMatthew Garrett LIST_HEAD(evm_config_xattrnames); 5721af7663SMatthew Garrett 587102ebcdSMimi Zohar static int evm_fixmode; 597102ebcdSMimi Zohar static int __init evm_set_fixmode(char *str) 607102ebcdSMimi Zohar { 617102ebcdSMimi Zohar if (strncmp(str, "fix", 3) == 0) 627102ebcdSMimi Zohar evm_fixmode = 1; 637fe2bb7eSBruno Meneguele else 647fe2bb7eSBruno Meneguele pr_err("invalid \"%s\" mode", str); 657fe2bb7eSBruno Meneguele 667102ebcdSMimi Zohar return 0; 677102ebcdSMimi Zohar } 687102ebcdSMimi Zohar __setup("evm=", evm_set_fixmode); 697102ebcdSMimi Zohar 70d3b33679SDmitry Kasatkin static void __init evm_init_config(void) 71d3b33679SDmitry Kasatkin { 7221af7663SMatthew Garrett int i, xattrs; 7321af7663SMatthew Garrett 7421af7663SMatthew Garrett xattrs = ARRAY_SIZE(evm_config_default_xattrnames); 7521af7663SMatthew Garrett 7621af7663SMatthew Garrett pr_info("Initialising EVM extended attributes:\n"); 7721af7663SMatthew Garrett for (i = 0; i < xattrs; i++) { 7821af7663SMatthew Garrett pr_info("%s\n", evm_config_default_xattrnames[i].name); 7921af7663SMatthew Garrett list_add_tail(&evm_config_default_xattrnames[i].list, 8021af7663SMatthew Garrett &evm_config_xattrnames); 8121af7663SMatthew Garrett } 8221af7663SMatthew Garrett 83d3b33679SDmitry Kasatkin #ifdef CONFIG_EVM_ATTR_FSUUID 84d3b33679SDmitry Kasatkin evm_hmac_attrs |= EVM_ATTR_FSUUID; 85d3b33679SDmitry Kasatkin #endif 86d3b33679SDmitry Kasatkin pr_info("HMAC attrs: 0x%x\n", evm_hmac_attrs); 87d3b33679SDmitry Kasatkin } 88d3b33679SDmitry Kasatkin 89ae1ba167SMatthew Garrett static bool evm_key_loaded(void) 90ae1ba167SMatthew Garrett { 91ae1ba167SMatthew Garrett return (bool)(evm_initialized & EVM_KEY_MASK); 92ae1ba167SMatthew Garrett } 93ae1ba167SMatthew Garrett 944a804b8aSRoberto Sassu /* 954a804b8aSRoberto Sassu * This function determines whether or not it is safe to ignore verification 964a804b8aSRoberto Sassu * errors, based on the ability of EVM to calculate HMACs. If the HMAC key 974a804b8aSRoberto Sassu * is not loaded, and it cannot be loaded in the future due to the 984a804b8aSRoberto Sassu * EVM_SETUP_COMPLETE initialization flag, allowing an operation despite the 994a804b8aSRoberto Sassu * attrs/xattrs being found invalid will not make them valid. 1004a804b8aSRoberto Sassu */ 1014a804b8aSRoberto Sassu static bool evm_hmac_disabled(void) 1024a804b8aSRoberto Sassu { 1034a804b8aSRoberto Sassu if (evm_initialized & EVM_INIT_HMAC) 1044a804b8aSRoberto Sassu return false; 1054a804b8aSRoberto Sassu 1064a804b8aSRoberto Sassu if (!(evm_initialized & EVM_SETUP_COMPLETE)) 1074a804b8aSRoberto Sassu return false; 1084a804b8aSRoberto Sassu 1094a804b8aSRoberto Sassu return true; 1104a804b8aSRoberto Sassu } 1114a804b8aSRoberto Sassu 11215647eb3SDmitry Kasatkin static int evm_find_protected_xattrs(struct dentry *dentry) 11315647eb3SDmitry Kasatkin { 114c6f493d6SDavid Howells struct inode *inode = d_backing_inode(dentry); 11521af7663SMatthew Garrett struct xattr_list *xattr; 11615647eb3SDmitry Kasatkin int error; 11715647eb3SDmitry Kasatkin int count = 0; 11815647eb3SDmitry Kasatkin 1195d6c3191SAndreas Gruenbacher if (!(inode->i_opflags & IOP_XATTR)) 12015647eb3SDmitry Kasatkin return -EOPNOTSUPP; 12115647eb3SDmitry Kasatkin 122770f6058SMadhuparna Bhowmik list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) { 12321af7663SMatthew Garrett error = __vfs_getxattr(dentry, inode, xattr->name, NULL, 0); 12415647eb3SDmitry Kasatkin if (error < 0) { 12515647eb3SDmitry Kasatkin if (error == -ENODATA) 12615647eb3SDmitry Kasatkin continue; 12715647eb3SDmitry Kasatkin return error; 12815647eb3SDmitry Kasatkin } 12915647eb3SDmitry Kasatkin count++; 13015647eb3SDmitry Kasatkin } 13115647eb3SDmitry Kasatkin 13215647eb3SDmitry Kasatkin return count; 13315647eb3SDmitry Kasatkin } 13415647eb3SDmitry Kasatkin 13566dbc325SMimi Zohar /* 13666dbc325SMimi Zohar * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr 13766dbc325SMimi Zohar * 13866dbc325SMimi Zohar * Compute the HMAC on the dentry's protected set of extended attributes 1397102ebcdSMimi Zohar * and compare it against the stored security.evm xattr. 1407102ebcdSMimi Zohar * 1417102ebcdSMimi Zohar * For performance: 1427102ebcdSMimi Zohar * - use the previoulsy retrieved xattr value and length to calculate the 14366dbc325SMimi Zohar * HMAC.) 1447102ebcdSMimi Zohar * - cache the verification result in the iint, when available. 14566dbc325SMimi Zohar * 14666dbc325SMimi Zohar * Returns integrity status 14766dbc325SMimi Zohar */ 14866dbc325SMimi Zohar static enum integrity_status evm_verify_hmac(struct dentry *dentry, 14966dbc325SMimi Zohar const char *xattr_name, 15066dbc325SMimi Zohar char *xattr_value, 15166dbc325SMimi Zohar size_t xattr_value_len, 15266dbc325SMimi Zohar struct integrity_iint_cache *iint) 15366dbc325SMimi Zohar { 15415647eb3SDmitry Kasatkin struct evm_ima_xattr_data *xattr_data = NULL; 1555feeb611SMatthew Garrett struct signature_v2_hdr *hdr; 156566be59aSMimi Zohar enum integrity_status evm_status = INTEGRITY_PASS; 1575feeb611SMatthew Garrett struct evm_digest digest; 15870946c4aSSascha Hauer struct inode *inode; 159*cdef685bSRoberto Sassu int rc, xattr_len, evm_immutable = 0; 16066dbc325SMimi Zohar 16150b97748SMatthew Garrett if (iint && (iint->evm_status == INTEGRITY_PASS || 16250b97748SMatthew Garrett iint->evm_status == INTEGRITY_PASS_IMMUTABLE)) 16324e0198eSDmitry Kasatkin return iint->evm_status; 16466dbc325SMimi Zohar 1656d38ca01SDmitry Kasatkin /* if status is not PASS, try to check again - against -ENOMEM */ 1666d38ca01SDmitry Kasatkin 16715647eb3SDmitry Kasatkin /* first need to know the sig type */ 168c7c7a1a1STycho Andersen rc = vfs_getxattr_alloc(&init_user_ns, dentry, XATTR_NAME_EVM, 169c7c7a1a1STycho Andersen (char **)&xattr_data, 0, GFP_NOFS); 17015647eb3SDmitry Kasatkin if (rc <= 0) { 1711f100979SDmitry Kasatkin evm_status = INTEGRITY_FAIL; 1721f100979SDmitry Kasatkin if (rc == -ENODATA) { 17315647eb3SDmitry Kasatkin rc = evm_find_protected_xattrs(dentry); 17415647eb3SDmitry Kasatkin if (rc > 0) 17515647eb3SDmitry Kasatkin evm_status = INTEGRITY_NOLABEL; 17615647eb3SDmitry Kasatkin else if (rc == 0) 17715647eb3SDmitry Kasatkin evm_status = INTEGRITY_NOXATTRS; /* new file */ 1781f100979SDmitry Kasatkin } else if (rc == -EOPNOTSUPP) { 1791f100979SDmitry Kasatkin evm_status = INTEGRITY_UNKNOWN; 18015647eb3SDmitry Kasatkin } 181566be59aSMimi Zohar goto out; 182566be59aSMimi Zohar } 18366dbc325SMimi Zohar 184b1aaab22SDmitry Kasatkin xattr_len = rc; 18515647eb3SDmitry Kasatkin 18615647eb3SDmitry Kasatkin /* check value type */ 18715647eb3SDmitry Kasatkin switch (xattr_data->type) { 18815647eb3SDmitry Kasatkin case EVM_XATTR_HMAC: 189650b29dbSThiago Jung Bauermann if (xattr_len != sizeof(struct evm_xattr)) { 190b4bfec7fSSeth Forshee evm_status = INTEGRITY_FAIL; 191b4bfec7fSSeth Forshee goto out; 192b4bfec7fSSeth Forshee } 1935feeb611SMatthew Garrett 1945feeb611SMatthew Garrett digest.hdr.algo = HASH_ALGO_SHA1; 19515647eb3SDmitry Kasatkin rc = evm_calc_hmac(dentry, xattr_name, xattr_value, 1965feeb611SMatthew Garrett xattr_value_len, &digest); 19715647eb3SDmitry Kasatkin if (rc) 19815647eb3SDmitry Kasatkin break; 199650b29dbSThiago Jung Bauermann rc = crypto_memneq(xattr_data->data, digest.digest, 2005feeb611SMatthew Garrett SHA1_DIGEST_SIZE); 20115647eb3SDmitry Kasatkin if (rc) 20215647eb3SDmitry Kasatkin rc = -EINVAL; 20315647eb3SDmitry Kasatkin break; 20450b97748SMatthew Garrett case EVM_XATTR_PORTABLE_DIGSIG: 205*cdef685bSRoberto Sassu evm_immutable = 1; 206*cdef685bSRoberto Sassu fallthrough; 207*cdef685bSRoberto Sassu case EVM_IMA_XATTR_DIGSIG: 208455b6c91SRoberto Sassu /* accept xattr with non-empty signature field */ 209455b6c91SRoberto Sassu if (xattr_len <= sizeof(struct signature_v2_hdr)) { 210455b6c91SRoberto Sassu evm_status = INTEGRITY_FAIL; 211455b6c91SRoberto Sassu goto out; 212455b6c91SRoberto Sassu } 213455b6c91SRoberto Sassu 2145feeb611SMatthew Garrett hdr = (struct signature_v2_hdr *)xattr_data; 2155feeb611SMatthew Garrett digest.hdr.algo = hdr->hash_algo; 21615647eb3SDmitry Kasatkin rc = evm_calc_hash(dentry, xattr_name, xattr_value, 2175feeb611SMatthew Garrett xattr_value_len, xattr_data->type, &digest); 21815647eb3SDmitry Kasatkin if (rc) 21915647eb3SDmitry Kasatkin break; 22015647eb3SDmitry Kasatkin rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM, 221b1aaab22SDmitry Kasatkin (const char *)xattr_data, xattr_len, 2225feeb611SMatthew Garrett digest.digest, digest.hdr.length); 22315647eb3SDmitry Kasatkin if (!rc) { 22470946c4aSSascha Hauer inode = d_backing_inode(dentry); 22570946c4aSSascha Hauer 22650b97748SMatthew Garrett if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) { 22750b97748SMatthew Garrett if (iint) 22850b97748SMatthew Garrett iint->flags |= EVM_IMMUTABLE_DIGSIG; 22950b97748SMatthew Garrett evm_status = INTEGRITY_PASS_IMMUTABLE; 23070946c4aSSascha Hauer } else if (!IS_RDONLY(inode) && 23170946c4aSSascha Hauer !(inode->i_sb->s_readonly_remount) && 23270946c4aSSascha Hauer !IS_IMMUTABLE(inode)) { 233c2baec7fSDmitry Kasatkin evm_update_evmxattr(dentry, xattr_name, 234c2baec7fSDmitry Kasatkin xattr_value, 23515647eb3SDmitry Kasatkin xattr_value_len); 23615647eb3SDmitry Kasatkin } 23750b97748SMatthew Garrett } 23815647eb3SDmitry Kasatkin break; 23915647eb3SDmitry Kasatkin default: 24015647eb3SDmitry Kasatkin rc = -EINVAL; 24115647eb3SDmitry Kasatkin break; 24215647eb3SDmitry Kasatkin } 24315647eb3SDmitry Kasatkin 244*cdef685bSRoberto Sassu if (rc) { 245*cdef685bSRoberto Sassu if (rc == -ENODATA) 246*cdef685bSRoberto Sassu evm_status = INTEGRITY_NOXATTRS; 247*cdef685bSRoberto Sassu else if (evm_immutable) 248*cdef685bSRoberto Sassu evm_status = INTEGRITY_FAIL_IMMUTABLE; 249*cdef685bSRoberto Sassu else 250*cdef685bSRoberto Sassu evm_status = INTEGRITY_FAIL; 251*cdef685bSRoberto Sassu } 2527102ebcdSMimi Zohar out: 2537102ebcdSMimi Zohar if (iint) 2547102ebcdSMimi Zohar iint->evm_status = evm_status; 25515647eb3SDmitry Kasatkin kfree(xattr_data); 2567102ebcdSMimi Zohar return evm_status; 25766dbc325SMimi Zohar } 25866dbc325SMimi Zohar 25966dbc325SMimi Zohar static int evm_protected_xattr(const char *req_xattr_name) 26066dbc325SMimi Zohar { 26166dbc325SMimi Zohar int namelen; 26266dbc325SMimi Zohar int found = 0; 26321af7663SMatthew Garrett struct xattr_list *xattr; 26466dbc325SMimi Zohar 26566dbc325SMimi Zohar namelen = strlen(req_xattr_name); 266770f6058SMadhuparna Bhowmik list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) { 26721af7663SMatthew Garrett if ((strlen(xattr->name) == namelen) 26821af7663SMatthew Garrett && (strncmp(req_xattr_name, xattr->name, namelen) == 0)) { 26966dbc325SMimi Zohar found = 1; 27066dbc325SMimi Zohar break; 27166dbc325SMimi Zohar } 272cb723180SMimi Zohar if (strncmp(req_xattr_name, 27321af7663SMatthew Garrett xattr->name + XATTR_SECURITY_PREFIX_LEN, 274cb723180SMimi Zohar strlen(req_xattr_name)) == 0) { 275cb723180SMimi Zohar found = 1; 276cb723180SMimi Zohar break; 277cb723180SMimi Zohar } 27866dbc325SMimi Zohar } 27921af7663SMatthew Garrett 28066dbc325SMimi Zohar return found; 28166dbc325SMimi Zohar } 28266dbc325SMimi Zohar 28366dbc325SMimi Zohar /** 28466dbc325SMimi Zohar * evm_verifyxattr - verify the integrity of the requested xattr 28566dbc325SMimi Zohar * @dentry: object of the verify xattr 28666dbc325SMimi Zohar * @xattr_name: requested xattr 28766dbc325SMimi Zohar * @xattr_value: requested xattr value 28866dbc325SMimi Zohar * @xattr_value_len: requested xattr value length 28966dbc325SMimi Zohar * 29066dbc325SMimi Zohar * Calculate the HMAC for the given dentry and verify it against the stored 29166dbc325SMimi Zohar * security.evm xattr. For performance, use the xattr value and length 29266dbc325SMimi Zohar * previously retrieved to calculate the HMAC. 29366dbc325SMimi Zohar * 29466dbc325SMimi Zohar * Returns the xattr integrity status. 29566dbc325SMimi Zohar * 29666dbc325SMimi Zohar * This function requires the caller to lock the inode's i_mutex before it 29766dbc325SMimi Zohar * is executed. 29866dbc325SMimi Zohar */ 29966dbc325SMimi Zohar enum integrity_status evm_verifyxattr(struct dentry *dentry, 30066dbc325SMimi Zohar const char *xattr_name, 3012960e6cbSDmitry Kasatkin void *xattr_value, size_t xattr_value_len, 3022960e6cbSDmitry Kasatkin struct integrity_iint_cache *iint) 30366dbc325SMimi Zohar { 304ae1ba167SMatthew Garrett if (!evm_key_loaded() || !evm_protected_xattr(xattr_name)) 30566dbc325SMimi Zohar return INTEGRITY_UNKNOWN; 30666dbc325SMimi Zohar 3072960e6cbSDmitry Kasatkin if (!iint) { 308c6f493d6SDavid Howells iint = integrity_iint_find(d_backing_inode(dentry)); 30966dbc325SMimi Zohar if (!iint) 31066dbc325SMimi Zohar return INTEGRITY_UNKNOWN; 3112960e6cbSDmitry Kasatkin } 3122960e6cbSDmitry Kasatkin return evm_verify_hmac(dentry, xattr_name, xattr_value, 31366dbc325SMimi Zohar xattr_value_len, iint); 31466dbc325SMimi Zohar } 31566dbc325SMimi Zohar EXPORT_SYMBOL_GPL(evm_verifyxattr); 31666dbc325SMimi Zohar 31766dbc325SMimi Zohar /* 3187102ebcdSMimi Zohar * evm_verify_current_integrity - verify the dentry's metadata integrity 3197102ebcdSMimi Zohar * @dentry: pointer to the affected dentry 3207102ebcdSMimi Zohar * 3217102ebcdSMimi Zohar * Verify and return the dentry's metadata integrity. The exceptions are 3227102ebcdSMimi Zohar * before EVM is initialized or in 'fix' mode. 3237102ebcdSMimi Zohar */ 3247102ebcdSMimi Zohar static enum integrity_status evm_verify_current_integrity(struct dentry *dentry) 3257102ebcdSMimi Zohar { 326c6f493d6SDavid Howells struct inode *inode = d_backing_inode(dentry); 3277102ebcdSMimi Zohar 328ae1ba167SMatthew Garrett if (!evm_key_loaded() || !S_ISREG(inode->i_mode) || evm_fixmode) 3297102ebcdSMimi Zohar return 0; 3307102ebcdSMimi Zohar return evm_verify_hmac(dentry, NULL, NULL, 0, NULL); 3317102ebcdSMimi Zohar } 3327102ebcdSMimi Zohar 333a924ce0bSMimi Zohar /* 334a924ce0bSMimi Zohar * evm_protect_xattr - protect the EVM extended attribute 335a924ce0bSMimi Zohar * 336bf6d0f5dSMimi Zohar * Prevent security.evm from being modified or removed without the 337bf6d0f5dSMimi Zohar * necessary permissions or when the existing value is invalid. 338bf6d0f5dSMimi Zohar * 339bf6d0f5dSMimi Zohar * The posix xattr acls are 'system' prefixed, which normally would not 340bf6d0f5dSMimi Zohar * affect security.evm. An interesting side affect of writing posix xattr 341bf6d0f5dSMimi Zohar * acls is their modifying of the i_mode, which is included in security.evm. 342bf6d0f5dSMimi Zohar * For posix xattr acls only, permit security.evm, even if it currently 34350b97748SMatthew Garrett * doesn't exist, to be updated unless the EVM signature is immutable. 344a924ce0bSMimi Zohar */ 345a924ce0bSMimi Zohar static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, 346a924ce0bSMimi Zohar const void *xattr_value, size_t xattr_value_len) 347a924ce0bSMimi Zohar { 348a924ce0bSMimi Zohar enum integrity_status evm_status; 349a924ce0bSMimi Zohar 350a924ce0bSMimi Zohar if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { 351a924ce0bSMimi Zohar if (!capable(CAP_SYS_ADMIN)) 352a924ce0bSMimi Zohar return -EPERM; 353bf6d0f5dSMimi Zohar } else if (!evm_protected_xattr(xattr_name)) { 354bf6d0f5dSMimi Zohar if (!posix_xattr_acl(xattr_name)) 355a924ce0bSMimi Zohar return 0; 356bf6d0f5dSMimi Zohar evm_status = evm_verify_current_integrity(dentry); 357bf6d0f5dSMimi Zohar if ((evm_status == INTEGRITY_PASS) || 358566be59aSMimi Zohar (evm_status == INTEGRITY_NOXATTRS)) 359bf6d0f5dSMimi Zohar return 0; 3609b97b6cdSMimi Zohar goto out; 361bf6d0f5dSMimi Zohar } 362ae1ba167SMatthew Garrett 363a924ce0bSMimi Zohar evm_status = evm_verify_current_integrity(dentry); 3643dcbad52SDmitry Kasatkin if (evm_status == INTEGRITY_NOXATTRS) { 3653dcbad52SDmitry Kasatkin struct integrity_iint_cache *iint; 3663dcbad52SDmitry Kasatkin 3674a804b8aSRoberto Sassu /* Exception if the HMAC is not going to be calculated. */ 3684a804b8aSRoberto Sassu if (evm_hmac_disabled()) 3694a804b8aSRoberto Sassu return 0; 3704a804b8aSRoberto Sassu 371c6f493d6SDavid Howells iint = integrity_iint_find(d_backing_inode(dentry)); 3723dcbad52SDmitry Kasatkin if (iint && (iint->flags & IMA_NEW_FILE)) 3733dcbad52SDmitry Kasatkin return 0; 3745101a185SMimi Zohar 3755101a185SMimi Zohar /* exception for pseudo filesystems */ 376fc64005cSAl Viro if (dentry->d_sb->s_magic == TMPFS_MAGIC 377fc64005cSAl Viro || dentry->d_sb->s_magic == SYSFS_MAGIC) 3785101a185SMimi Zohar return 0; 3795101a185SMimi Zohar 3805101a185SMimi Zohar integrity_audit_msg(AUDIT_INTEGRITY_METADATA, 3815101a185SMimi Zohar dentry->d_inode, dentry->d_name.name, 3825101a185SMimi Zohar "update_metadata", 3835101a185SMimi Zohar integrity_status_msg[evm_status], 3845101a185SMimi Zohar -EPERM, 0); 3853dcbad52SDmitry Kasatkin } 3869b97b6cdSMimi Zohar out: 3874a804b8aSRoberto Sassu /* Exception if the HMAC is not going to be calculated. */ 3884a804b8aSRoberto Sassu if (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL || 3894a804b8aSRoberto Sassu evm_status == INTEGRITY_UNKNOWN)) 3904a804b8aSRoberto Sassu return 0; 391*cdef685bSRoberto Sassu 392*cdef685bSRoberto Sassu /* 393*cdef685bSRoberto Sassu * Writing other xattrs is safe for portable signatures, as portable 394*cdef685bSRoberto Sassu * signatures are immutable and can never be updated. 395*cdef685bSRoberto Sassu */ 396*cdef685bSRoberto Sassu if (evm_status == INTEGRITY_FAIL_IMMUTABLE) 397*cdef685bSRoberto Sassu return 0; 398*cdef685bSRoberto Sassu 3999b97b6cdSMimi Zohar if (evm_status != INTEGRITY_PASS) 400c6f493d6SDavid Howells integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry), 4019b97b6cdSMimi Zohar dentry->d_name.name, "appraise_metadata", 4029b97b6cdSMimi Zohar integrity_status_msg[evm_status], 4039b97b6cdSMimi Zohar -EPERM, 0); 404a924ce0bSMimi Zohar return evm_status == INTEGRITY_PASS ? 0 : -EPERM; 405a924ce0bSMimi Zohar } 406a924ce0bSMimi Zohar 40766dbc325SMimi Zohar /** 40866dbc325SMimi Zohar * evm_inode_setxattr - protect the EVM extended attribute 40966dbc325SMimi Zohar * @dentry: pointer to the affected dentry 41066dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 41166dbc325SMimi Zohar * @xattr_value: pointer to the new extended attribute value 41266dbc325SMimi Zohar * @xattr_value_len: pointer to the new extended attribute value length 41366dbc325SMimi Zohar * 4142fb1c9a4SMimi Zohar * Before allowing the 'security.evm' protected xattr to be updated, 4152fb1c9a4SMimi Zohar * verify the existing value is valid. As only the kernel should have 4162fb1c9a4SMimi Zohar * access to the EVM encrypted key needed to calculate the HMAC, prevent 4172fb1c9a4SMimi Zohar * userspace from writing HMAC value. Writing 'security.evm' requires 4182fb1c9a4SMimi Zohar * requires CAP_SYS_ADMIN privileges. 41966dbc325SMimi Zohar */ 42066dbc325SMimi Zohar int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name, 42166dbc325SMimi Zohar const void *xattr_value, size_t xattr_value_len) 42266dbc325SMimi Zohar { 4232fb1c9a4SMimi Zohar const struct evm_ima_xattr_data *xattr_data = xattr_value; 4242fb1c9a4SMimi Zohar 425ae1ba167SMatthew Garrett /* Policy permits modification of the protected xattrs even though 426ae1ba167SMatthew Garrett * there's no HMAC key loaded 427ae1ba167SMatthew Garrett */ 428ae1ba167SMatthew Garrett if (evm_initialized & EVM_ALLOW_METADATA_WRITES) 429ae1ba167SMatthew Garrett return 0; 430ae1ba167SMatthew Garrett 4313b1deef6SDmitry Kasatkin if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { 4323b1deef6SDmitry Kasatkin if (!xattr_value_len) 4333b1deef6SDmitry Kasatkin return -EINVAL; 43450b97748SMatthew Garrett if (xattr_data->type != EVM_IMA_XATTR_DIGSIG && 43550b97748SMatthew Garrett xattr_data->type != EVM_XATTR_PORTABLE_DIGSIG) 4362fb1c9a4SMimi Zohar return -EPERM; 4373b1deef6SDmitry Kasatkin } 438a924ce0bSMimi Zohar return evm_protect_xattr(dentry, xattr_name, xattr_value, 43966dbc325SMimi Zohar xattr_value_len); 44066dbc325SMimi Zohar } 44166dbc325SMimi Zohar 44266dbc325SMimi Zohar /** 44366dbc325SMimi Zohar * evm_inode_removexattr - protect the EVM extended attribute 44466dbc325SMimi Zohar * @dentry: pointer to the affected dentry 44566dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 44666dbc325SMimi Zohar * 4477102ebcdSMimi Zohar * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that 4487102ebcdSMimi Zohar * the current value is valid. 44966dbc325SMimi Zohar */ 45066dbc325SMimi Zohar int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name) 45166dbc325SMimi Zohar { 452ae1ba167SMatthew Garrett /* Policy permits modification of the protected xattrs even though 453ae1ba167SMatthew Garrett * there's no HMAC key loaded 454ae1ba167SMatthew Garrett */ 455ae1ba167SMatthew Garrett if (evm_initialized & EVM_ALLOW_METADATA_WRITES) 456ae1ba167SMatthew Garrett return 0; 457ae1ba167SMatthew Garrett 458a924ce0bSMimi Zohar return evm_protect_xattr(dentry, xattr_name, NULL, 0); 45966dbc325SMimi Zohar } 46066dbc325SMimi Zohar 461523b74b1SDmitry Kasatkin static void evm_reset_status(struct inode *inode) 462523b74b1SDmitry Kasatkin { 463523b74b1SDmitry Kasatkin struct integrity_iint_cache *iint; 464523b74b1SDmitry Kasatkin 465523b74b1SDmitry Kasatkin iint = integrity_iint_find(inode); 466523b74b1SDmitry Kasatkin if (iint) 467523b74b1SDmitry Kasatkin iint->evm_status = INTEGRITY_UNKNOWN; 468523b74b1SDmitry Kasatkin } 469523b74b1SDmitry Kasatkin 47066dbc325SMimi Zohar /** 471e3ccfe1aSRoberto Sassu * evm_revalidate_status - report whether EVM status re-validation is necessary 472e3ccfe1aSRoberto Sassu * @xattr_name: pointer to the affected extended attribute name 473e3ccfe1aSRoberto Sassu * 474e3ccfe1aSRoberto Sassu * Report whether callers of evm_verifyxattr() should re-validate the 475e3ccfe1aSRoberto Sassu * EVM status. 476e3ccfe1aSRoberto Sassu * 477e3ccfe1aSRoberto Sassu * Return true if re-validation is necessary, false otherwise. 478e3ccfe1aSRoberto Sassu */ 479e3ccfe1aSRoberto Sassu bool evm_revalidate_status(const char *xattr_name) 480e3ccfe1aSRoberto Sassu { 481e3ccfe1aSRoberto Sassu if (!evm_key_loaded()) 482e3ccfe1aSRoberto Sassu return false; 483e3ccfe1aSRoberto Sassu 484e3ccfe1aSRoberto Sassu /* evm_inode_post_setattr() passes NULL */ 485e3ccfe1aSRoberto Sassu if (!xattr_name) 486e3ccfe1aSRoberto Sassu return true; 487e3ccfe1aSRoberto Sassu 488e3ccfe1aSRoberto Sassu if (!evm_protected_xattr(xattr_name) && !posix_xattr_acl(xattr_name) && 489e3ccfe1aSRoberto Sassu strcmp(xattr_name, XATTR_NAME_EVM)) 490e3ccfe1aSRoberto Sassu return false; 491e3ccfe1aSRoberto Sassu 492e3ccfe1aSRoberto Sassu return true; 493e3ccfe1aSRoberto Sassu } 494e3ccfe1aSRoberto Sassu 495e3ccfe1aSRoberto Sassu /** 49666dbc325SMimi Zohar * evm_inode_post_setxattr - update 'security.evm' to reflect the changes 49766dbc325SMimi Zohar * @dentry: pointer to the affected dentry 49866dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 49966dbc325SMimi Zohar * @xattr_value: pointer to the new extended attribute value 50066dbc325SMimi Zohar * @xattr_value_len: pointer to the new extended attribute value length 50166dbc325SMimi Zohar * 50266dbc325SMimi Zohar * Update the HMAC stored in 'security.evm' to reflect the change. 50366dbc325SMimi Zohar * 50466dbc325SMimi Zohar * No need to take the i_mutex lock here, as this function is called from 50566dbc325SMimi Zohar * __vfs_setxattr_noperm(). The caller of which has taken the inode's 50666dbc325SMimi Zohar * i_mutex lock. 50766dbc325SMimi Zohar */ 50866dbc325SMimi Zohar void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, 50966dbc325SMimi Zohar const void *xattr_value, size_t xattr_value_len) 51066dbc325SMimi Zohar { 511e3ccfe1aSRoberto Sassu if (!evm_revalidate_status(xattr_name)) 51266dbc325SMimi Zohar return; 51366dbc325SMimi Zohar 514523b74b1SDmitry Kasatkin evm_reset_status(dentry->d_inode); 515523b74b1SDmitry Kasatkin 516e3ccfe1aSRoberto Sassu if (!strcmp(xattr_name, XATTR_NAME_EVM)) 517e3ccfe1aSRoberto Sassu return; 518e3ccfe1aSRoberto Sassu 5194a804b8aSRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC)) 5204a804b8aSRoberto Sassu return; 5214a804b8aSRoberto Sassu 52266dbc325SMimi Zohar evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len); 52366dbc325SMimi Zohar } 52466dbc325SMimi Zohar 52566dbc325SMimi Zohar /** 52666dbc325SMimi Zohar * evm_inode_post_removexattr - update 'security.evm' after removing the xattr 52766dbc325SMimi Zohar * @dentry: pointer to the affected dentry 52866dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 52966dbc325SMimi Zohar * 53066dbc325SMimi Zohar * Update the HMAC stored in 'security.evm' to reflect removal of the xattr. 5317c51bb00SDmitry Kasatkin * 5327c51bb00SDmitry Kasatkin * No need to take the i_mutex lock here, as this function is called from 5337c51bb00SDmitry Kasatkin * vfs_removexattr() which takes the i_mutex. 53466dbc325SMimi Zohar */ 53566dbc325SMimi Zohar void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) 53666dbc325SMimi Zohar { 537e3ccfe1aSRoberto Sassu if (!evm_revalidate_status(xattr_name)) 53866dbc325SMimi Zohar return; 53966dbc325SMimi Zohar 540523b74b1SDmitry Kasatkin evm_reset_status(dentry->d_inode); 541523b74b1SDmitry Kasatkin 542e3ccfe1aSRoberto Sassu if (!strcmp(xattr_name, XATTR_NAME_EVM)) 543e3ccfe1aSRoberto Sassu return; 544e3ccfe1aSRoberto Sassu 5454a804b8aSRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC)) 5464a804b8aSRoberto Sassu return; 5474a804b8aSRoberto Sassu 54866dbc325SMimi Zohar evm_update_evmxattr(dentry, xattr_name, NULL, 0); 54966dbc325SMimi Zohar } 55066dbc325SMimi Zohar 55166dbc325SMimi Zohar /** 552817b54aaSMimi Zohar * evm_inode_setattr - prevent updating an invalid EVM extended attribute 553817b54aaSMimi Zohar * @dentry: pointer to the affected dentry 55450b97748SMatthew Garrett * 55550b97748SMatthew Garrett * Permit update of file attributes when files have a valid EVM signature, 55650b97748SMatthew Garrett * except in the case of them having an immutable portable signature. 557817b54aaSMimi Zohar */ 558817b54aaSMimi Zohar int evm_inode_setattr(struct dentry *dentry, struct iattr *attr) 559817b54aaSMimi Zohar { 560817b54aaSMimi Zohar unsigned int ia_valid = attr->ia_valid; 561817b54aaSMimi Zohar enum integrity_status evm_status; 562817b54aaSMimi Zohar 563ae1ba167SMatthew Garrett /* Policy permits modification of the protected attrs even though 564ae1ba167SMatthew Garrett * there's no HMAC key loaded 565ae1ba167SMatthew Garrett */ 566ae1ba167SMatthew Garrett if (evm_initialized & EVM_ALLOW_METADATA_WRITES) 567ae1ba167SMatthew Garrett return 0; 568ae1ba167SMatthew Garrett 569a924ce0bSMimi Zohar if (!(ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))) 570817b54aaSMimi Zohar return 0; 571817b54aaSMimi Zohar evm_status = evm_verify_current_integrity(dentry); 572*cdef685bSRoberto Sassu /* 573*cdef685bSRoberto Sassu * Writing attrs is safe for portable signatures, as portable signatures 574*cdef685bSRoberto Sassu * are immutable and can never be updated. 575*cdef685bSRoberto Sassu */ 576566be59aSMimi Zohar if ((evm_status == INTEGRITY_PASS) || 5774a804b8aSRoberto Sassu (evm_status == INTEGRITY_NOXATTRS) || 578*cdef685bSRoberto Sassu (evm_status == INTEGRITY_FAIL_IMMUTABLE) || 5794a804b8aSRoberto Sassu (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL || 5804a804b8aSRoberto Sassu evm_status == INTEGRITY_UNKNOWN))) 581566be59aSMimi Zohar return 0; 582c6f493d6SDavid Howells integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry), 5839b97b6cdSMimi Zohar dentry->d_name.name, "appraise_metadata", 5849b97b6cdSMimi Zohar integrity_status_msg[evm_status], -EPERM, 0); 585566be59aSMimi Zohar return -EPERM; 586817b54aaSMimi Zohar } 587817b54aaSMimi Zohar 588817b54aaSMimi Zohar /** 58966dbc325SMimi Zohar * evm_inode_post_setattr - update 'security.evm' after modifying metadata 59066dbc325SMimi Zohar * @dentry: pointer to the affected dentry 59166dbc325SMimi Zohar * @ia_valid: for the UID and GID status 59266dbc325SMimi Zohar * 59366dbc325SMimi Zohar * For now, update the HMAC stored in 'security.evm' to reflect UID/GID 59466dbc325SMimi Zohar * changes. 59566dbc325SMimi Zohar * 59666dbc325SMimi Zohar * This function is called from notify_change(), which expects the caller 59766dbc325SMimi Zohar * to lock the inode's i_mutex. 59866dbc325SMimi Zohar */ 59966dbc325SMimi Zohar void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) 60066dbc325SMimi Zohar { 601e3ccfe1aSRoberto Sassu if (!evm_revalidate_status(NULL)) 60266dbc325SMimi Zohar return; 60366dbc325SMimi Zohar 604e3ccfe1aSRoberto Sassu evm_reset_status(dentry->d_inode); 605e3ccfe1aSRoberto Sassu 6064a804b8aSRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC)) 6074a804b8aSRoberto Sassu return; 6084a804b8aSRoberto Sassu 60966dbc325SMimi Zohar if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) 61066dbc325SMimi Zohar evm_update_evmxattr(dentry, NULL, NULL, 0); 61166dbc325SMimi Zohar } 61266dbc325SMimi Zohar 613cb723180SMimi Zohar /* 6149eea2904SRoberto Sassu * evm_inode_init_security - initializes security.evm HMAC value 615cb723180SMimi Zohar */ 616cb723180SMimi Zohar int evm_inode_init_security(struct inode *inode, 617cb723180SMimi Zohar const struct xattr *lsm_xattr, 618cb723180SMimi Zohar struct xattr *evm_xattr) 619cb723180SMimi Zohar { 620650b29dbSThiago Jung Bauermann struct evm_xattr *xattr_data; 621cb723180SMimi Zohar int rc; 622cb723180SMimi Zohar 6239eea2904SRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC) || 6249eea2904SRoberto Sassu !evm_protected_xattr(lsm_xattr->name)) 6255a4730baSMimi Zohar return 0; 626cb723180SMimi Zohar 627cb723180SMimi Zohar xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS); 628cb723180SMimi Zohar if (!xattr_data) 629cb723180SMimi Zohar return -ENOMEM; 630cb723180SMimi Zohar 631650b29dbSThiago Jung Bauermann xattr_data->data.type = EVM_XATTR_HMAC; 632cb723180SMimi Zohar rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest); 633cb723180SMimi Zohar if (rc < 0) 634cb723180SMimi Zohar goto out; 635cb723180SMimi Zohar 636cb723180SMimi Zohar evm_xattr->value = xattr_data; 637cb723180SMimi Zohar evm_xattr->value_len = sizeof(*xattr_data); 6389548906bSTetsuo Handa evm_xattr->name = XATTR_EVM_SUFFIX; 639cb723180SMimi Zohar return 0; 640cb723180SMimi Zohar out: 641cb723180SMimi Zohar kfree(xattr_data); 642cb723180SMimi Zohar return rc; 643cb723180SMimi Zohar } 644cb723180SMimi Zohar EXPORT_SYMBOL_GPL(evm_inode_init_security); 645cb723180SMimi Zohar 6462ce523ebSDmitry Kasatkin #ifdef CONFIG_EVM_LOAD_X509 6472ce523ebSDmitry Kasatkin void __init evm_load_x509(void) 6482ce523ebSDmitry Kasatkin { 64926ddabfeSDmitry Kasatkin int rc; 65026ddabfeSDmitry Kasatkin 65126ddabfeSDmitry Kasatkin rc = integrity_load_x509(INTEGRITY_KEYRING_EVM, CONFIG_EVM_X509_PATH); 65226ddabfeSDmitry Kasatkin if (!rc) 65326ddabfeSDmitry Kasatkin evm_initialized |= EVM_INIT_X509; 6542ce523ebSDmitry Kasatkin } 6552ce523ebSDmitry Kasatkin #endif 6562ce523ebSDmitry Kasatkin 65766dbc325SMimi Zohar static int __init init_evm(void) 65866dbc325SMimi Zohar { 65966dbc325SMimi Zohar int error; 66021af7663SMatthew Garrett struct list_head *pos, *q; 66166dbc325SMimi Zohar 662d3b33679SDmitry Kasatkin evm_init_config(); 663d3b33679SDmitry Kasatkin 664f4dc3778SDmitry Kasatkin error = integrity_init_keyring(INTEGRITY_KEYRING_EVM); 665f4dc3778SDmitry Kasatkin if (error) 66621af7663SMatthew Garrett goto error; 667f4dc3778SDmitry Kasatkin 66866dbc325SMimi Zohar error = evm_init_secfs(); 66966dbc325SMimi Zohar if (error < 0) { 67020ee451fSJoe Perches pr_info("Error registering secfs\n"); 67121af7663SMatthew Garrett goto error; 67221af7663SMatthew Garrett } 67321af7663SMatthew Garrett 67421af7663SMatthew Garrett error: 67521af7663SMatthew Garrett if (error != 0) { 67621af7663SMatthew Garrett if (!list_empty(&evm_config_xattrnames)) { 677c8b37524SYueHaibing list_for_each_safe(pos, q, &evm_config_xattrnames) 67821af7663SMatthew Garrett list_del(pos); 67921af7663SMatthew Garrett } 68021af7663SMatthew Garrett } 68121af7663SMatthew Garrett 682f4dc3778SDmitry Kasatkin return error; 68366dbc325SMimi Zohar } 68415647eb3SDmitry Kasatkin 68566dbc325SMimi Zohar late_initcall(init_evm); 686