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> 21*1886ab01SRoberto Sassu #include <linux/posix_acl_xattr.h> 2250d34394SIngo Molnar 23d46eb369SDmitry Kasatkin #include <crypto/hash.h> 245feeb611SMatthew Garrett #include <crypto/hash_info.h> 25613317bdSRyan Ware #include <crypto/algapi.h> 2666dbc325SMimi Zohar #include "evm.h" 2766dbc325SMimi Zohar 2866dbc325SMimi Zohar int evm_initialized; 2966dbc325SMimi Zohar 3017d7b0afSHernán Gonzalez static const char * const integrity_status_msg[] = { 31cdef685bSRoberto Sassu "pass", "pass_immutable", "fail", "fail_immutable", "no_label", 32cdef685bSRoberto Sassu "no_xattrs", "unknown" 339b97b6cdSMimi Zohar }; 34d3b33679SDmitry Kasatkin int evm_hmac_attrs; 3566dbc325SMimi Zohar 36fa516b66SMatthew Garrett static struct xattr_list evm_config_default_xattrnames[] = { 3766dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SELINUX 3821af7663SMatthew Garrett {.name = XATTR_NAME_SELINUX}, 3966dbc325SMimi Zohar #endif 4066dbc325SMimi Zohar #ifdef CONFIG_SECURITY_SMACK 4121af7663SMatthew Garrett {.name = XATTR_NAME_SMACK}, 423e38df56SDmitry Kasatkin #ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS 4321af7663SMatthew Garrett {.name = XATTR_NAME_SMACKEXEC}, 4421af7663SMatthew Garrett {.name = XATTR_NAME_SMACKTRANSMUTE}, 4521af7663SMatthew Garrett {.name = XATTR_NAME_SMACKMMAP}, 463e38df56SDmitry Kasatkin #endif 4766dbc325SMimi Zohar #endif 48096b8546SMatthew Garrett #ifdef CONFIG_SECURITY_APPARMOR 4921af7663SMatthew Garrett {.name = XATTR_NAME_APPARMOR}, 50096b8546SMatthew Garrett #endif 512fe5d6deSMimi Zohar #ifdef CONFIG_IMA_APPRAISE 5221af7663SMatthew Garrett {.name = XATTR_NAME_IMA}, 532fe5d6deSMimi Zohar #endif 5421af7663SMatthew Garrett {.name = XATTR_NAME_CAPS}, 5566dbc325SMimi Zohar }; 5666dbc325SMimi Zohar 5721af7663SMatthew Garrett LIST_HEAD(evm_config_xattrnames); 5821af7663SMatthew Garrett 597102ebcdSMimi Zohar static int evm_fixmode; 607102ebcdSMimi Zohar static int __init evm_set_fixmode(char *str) 617102ebcdSMimi Zohar { 627102ebcdSMimi Zohar if (strncmp(str, "fix", 3) == 0) 637102ebcdSMimi Zohar evm_fixmode = 1; 647fe2bb7eSBruno Meneguele else 657fe2bb7eSBruno Meneguele pr_err("invalid \"%s\" mode", str); 667fe2bb7eSBruno Meneguele 677102ebcdSMimi Zohar return 0; 687102ebcdSMimi Zohar } 697102ebcdSMimi Zohar __setup("evm=", evm_set_fixmode); 707102ebcdSMimi Zohar 71d3b33679SDmitry Kasatkin static void __init evm_init_config(void) 72d3b33679SDmitry Kasatkin { 7321af7663SMatthew Garrett int i, xattrs; 7421af7663SMatthew Garrett 7521af7663SMatthew Garrett xattrs = ARRAY_SIZE(evm_config_default_xattrnames); 7621af7663SMatthew Garrett 7721af7663SMatthew Garrett pr_info("Initialising EVM extended attributes:\n"); 7821af7663SMatthew Garrett for (i = 0; i < xattrs; i++) { 7921af7663SMatthew Garrett pr_info("%s\n", evm_config_default_xattrnames[i].name); 8021af7663SMatthew Garrett list_add_tail(&evm_config_default_xattrnames[i].list, 8121af7663SMatthew Garrett &evm_config_xattrnames); 8221af7663SMatthew Garrett } 8321af7663SMatthew Garrett 84d3b33679SDmitry Kasatkin #ifdef CONFIG_EVM_ATTR_FSUUID 85d3b33679SDmitry Kasatkin evm_hmac_attrs |= EVM_ATTR_FSUUID; 86d3b33679SDmitry Kasatkin #endif 87d3b33679SDmitry Kasatkin pr_info("HMAC attrs: 0x%x\n", evm_hmac_attrs); 88d3b33679SDmitry Kasatkin } 89d3b33679SDmitry Kasatkin 90ae1ba167SMatthew Garrett static bool evm_key_loaded(void) 91ae1ba167SMatthew Garrett { 92ae1ba167SMatthew Garrett return (bool)(evm_initialized & EVM_KEY_MASK); 93ae1ba167SMatthew Garrett } 94ae1ba167SMatthew Garrett 954a804b8aSRoberto Sassu /* 964a804b8aSRoberto Sassu * This function determines whether or not it is safe to ignore verification 974a804b8aSRoberto Sassu * errors, based on the ability of EVM to calculate HMACs. If the HMAC key 984a804b8aSRoberto Sassu * is not loaded, and it cannot be loaded in the future due to the 994a804b8aSRoberto Sassu * EVM_SETUP_COMPLETE initialization flag, allowing an operation despite the 1004a804b8aSRoberto Sassu * attrs/xattrs being found invalid will not make them valid. 1014a804b8aSRoberto Sassu */ 1024a804b8aSRoberto Sassu static bool evm_hmac_disabled(void) 1034a804b8aSRoberto Sassu { 1044a804b8aSRoberto Sassu if (evm_initialized & EVM_INIT_HMAC) 1054a804b8aSRoberto Sassu return false; 1064a804b8aSRoberto Sassu 1074a804b8aSRoberto Sassu if (!(evm_initialized & EVM_SETUP_COMPLETE)) 1084a804b8aSRoberto Sassu return false; 1094a804b8aSRoberto Sassu 1104a804b8aSRoberto Sassu return true; 1114a804b8aSRoberto Sassu } 1124a804b8aSRoberto Sassu 11315647eb3SDmitry Kasatkin static int evm_find_protected_xattrs(struct dentry *dentry) 11415647eb3SDmitry Kasatkin { 115c6f493d6SDavid Howells struct inode *inode = d_backing_inode(dentry); 11621af7663SMatthew Garrett struct xattr_list *xattr; 11715647eb3SDmitry Kasatkin int error; 11815647eb3SDmitry Kasatkin int count = 0; 11915647eb3SDmitry Kasatkin 1205d6c3191SAndreas Gruenbacher if (!(inode->i_opflags & IOP_XATTR)) 12115647eb3SDmitry Kasatkin return -EOPNOTSUPP; 12215647eb3SDmitry Kasatkin 123770f6058SMadhuparna Bhowmik list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) { 12421af7663SMatthew Garrett error = __vfs_getxattr(dentry, inode, xattr->name, NULL, 0); 12515647eb3SDmitry Kasatkin if (error < 0) { 12615647eb3SDmitry Kasatkin if (error == -ENODATA) 12715647eb3SDmitry Kasatkin continue; 12815647eb3SDmitry Kasatkin return error; 12915647eb3SDmitry Kasatkin } 13015647eb3SDmitry Kasatkin count++; 13115647eb3SDmitry Kasatkin } 13215647eb3SDmitry Kasatkin 13315647eb3SDmitry Kasatkin return count; 13415647eb3SDmitry Kasatkin } 13515647eb3SDmitry Kasatkin 13666dbc325SMimi Zohar /* 13766dbc325SMimi Zohar * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr 13866dbc325SMimi Zohar * 13966dbc325SMimi Zohar * Compute the HMAC on the dentry's protected set of extended attributes 1407102ebcdSMimi Zohar * and compare it against the stored security.evm xattr. 1417102ebcdSMimi Zohar * 1427102ebcdSMimi Zohar * For performance: 1437102ebcdSMimi Zohar * - use the previoulsy retrieved xattr value and length to calculate the 14466dbc325SMimi Zohar * HMAC.) 1457102ebcdSMimi Zohar * - cache the verification result in the iint, when available. 14666dbc325SMimi Zohar * 14766dbc325SMimi Zohar * Returns integrity status 14866dbc325SMimi Zohar */ 14966dbc325SMimi Zohar static enum integrity_status evm_verify_hmac(struct dentry *dentry, 15066dbc325SMimi Zohar const char *xattr_name, 15166dbc325SMimi Zohar char *xattr_value, 15266dbc325SMimi Zohar size_t xattr_value_len, 15366dbc325SMimi Zohar struct integrity_iint_cache *iint) 15466dbc325SMimi Zohar { 15515647eb3SDmitry Kasatkin struct evm_ima_xattr_data *xattr_data = NULL; 1565feeb611SMatthew Garrett struct signature_v2_hdr *hdr; 157566be59aSMimi Zohar enum integrity_status evm_status = INTEGRITY_PASS; 1585feeb611SMatthew Garrett struct evm_digest digest; 15970946c4aSSascha Hauer struct inode *inode; 160cdef685bSRoberto Sassu int rc, xattr_len, evm_immutable = 0; 16166dbc325SMimi Zohar 16250b97748SMatthew Garrett if (iint && (iint->evm_status == INTEGRITY_PASS || 16350b97748SMatthew Garrett iint->evm_status == INTEGRITY_PASS_IMMUTABLE)) 16424e0198eSDmitry Kasatkin return iint->evm_status; 16566dbc325SMimi Zohar 1666d38ca01SDmitry Kasatkin /* if status is not PASS, try to check again - against -ENOMEM */ 1676d38ca01SDmitry Kasatkin 16815647eb3SDmitry Kasatkin /* first need to know the sig type */ 169c7c7a1a1STycho Andersen rc = vfs_getxattr_alloc(&init_user_ns, dentry, XATTR_NAME_EVM, 170c7c7a1a1STycho Andersen (char **)&xattr_data, 0, GFP_NOFS); 17115647eb3SDmitry Kasatkin if (rc <= 0) { 1721f100979SDmitry Kasatkin evm_status = INTEGRITY_FAIL; 1731f100979SDmitry Kasatkin if (rc == -ENODATA) { 17415647eb3SDmitry Kasatkin rc = evm_find_protected_xattrs(dentry); 17515647eb3SDmitry Kasatkin if (rc > 0) 17615647eb3SDmitry Kasatkin evm_status = INTEGRITY_NOLABEL; 17715647eb3SDmitry Kasatkin else if (rc == 0) 17815647eb3SDmitry Kasatkin evm_status = INTEGRITY_NOXATTRS; /* new file */ 1791f100979SDmitry Kasatkin } else if (rc == -EOPNOTSUPP) { 1801f100979SDmitry Kasatkin evm_status = INTEGRITY_UNKNOWN; 18115647eb3SDmitry Kasatkin } 182566be59aSMimi Zohar goto out; 183566be59aSMimi Zohar } 18466dbc325SMimi Zohar 185b1aaab22SDmitry Kasatkin xattr_len = rc; 18615647eb3SDmitry Kasatkin 18715647eb3SDmitry Kasatkin /* check value type */ 18815647eb3SDmitry Kasatkin switch (xattr_data->type) { 18915647eb3SDmitry Kasatkin case EVM_XATTR_HMAC: 190650b29dbSThiago Jung Bauermann if (xattr_len != sizeof(struct evm_xattr)) { 191b4bfec7fSSeth Forshee evm_status = INTEGRITY_FAIL; 192b4bfec7fSSeth Forshee goto out; 193b4bfec7fSSeth Forshee } 1945feeb611SMatthew Garrett 1955feeb611SMatthew Garrett digest.hdr.algo = HASH_ALGO_SHA1; 19615647eb3SDmitry Kasatkin rc = evm_calc_hmac(dentry, xattr_name, xattr_value, 1975feeb611SMatthew Garrett xattr_value_len, &digest); 19815647eb3SDmitry Kasatkin if (rc) 19915647eb3SDmitry Kasatkin break; 200650b29dbSThiago Jung Bauermann rc = crypto_memneq(xattr_data->data, digest.digest, 2015feeb611SMatthew Garrett SHA1_DIGEST_SIZE); 20215647eb3SDmitry Kasatkin if (rc) 20315647eb3SDmitry Kasatkin rc = -EINVAL; 20415647eb3SDmitry Kasatkin break; 20550b97748SMatthew Garrett case EVM_XATTR_PORTABLE_DIGSIG: 206cdef685bSRoberto Sassu evm_immutable = 1; 207cdef685bSRoberto Sassu fallthrough; 208cdef685bSRoberto Sassu case EVM_IMA_XATTR_DIGSIG: 209455b6c91SRoberto Sassu /* accept xattr with non-empty signature field */ 210455b6c91SRoberto Sassu if (xattr_len <= sizeof(struct signature_v2_hdr)) { 211455b6c91SRoberto Sassu evm_status = INTEGRITY_FAIL; 212455b6c91SRoberto Sassu goto out; 213455b6c91SRoberto Sassu } 214455b6c91SRoberto Sassu 2155feeb611SMatthew Garrett hdr = (struct signature_v2_hdr *)xattr_data; 2165feeb611SMatthew Garrett digest.hdr.algo = hdr->hash_algo; 21715647eb3SDmitry Kasatkin rc = evm_calc_hash(dentry, xattr_name, xattr_value, 2185feeb611SMatthew Garrett xattr_value_len, xattr_data->type, &digest); 21915647eb3SDmitry Kasatkin if (rc) 22015647eb3SDmitry Kasatkin break; 22115647eb3SDmitry Kasatkin rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM, 222b1aaab22SDmitry Kasatkin (const char *)xattr_data, xattr_len, 2235feeb611SMatthew Garrett digest.digest, digest.hdr.length); 22415647eb3SDmitry Kasatkin if (!rc) { 22570946c4aSSascha Hauer inode = d_backing_inode(dentry); 22670946c4aSSascha Hauer 22750b97748SMatthew Garrett if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) { 22850b97748SMatthew Garrett if (iint) 22950b97748SMatthew Garrett iint->flags |= EVM_IMMUTABLE_DIGSIG; 23050b97748SMatthew Garrett evm_status = INTEGRITY_PASS_IMMUTABLE; 23170946c4aSSascha Hauer } else if (!IS_RDONLY(inode) && 23270946c4aSSascha Hauer !(inode->i_sb->s_readonly_remount) && 23370946c4aSSascha Hauer !IS_IMMUTABLE(inode)) { 234c2baec7fSDmitry Kasatkin evm_update_evmxattr(dentry, xattr_name, 235c2baec7fSDmitry Kasatkin xattr_value, 23615647eb3SDmitry Kasatkin xattr_value_len); 23715647eb3SDmitry Kasatkin } 23850b97748SMatthew Garrett } 23915647eb3SDmitry Kasatkin break; 24015647eb3SDmitry Kasatkin default: 24115647eb3SDmitry Kasatkin rc = -EINVAL; 24215647eb3SDmitry Kasatkin break; 24315647eb3SDmitry Kasatkin } 24415647eb3SDmitry Kasatkin 245cdef685bSRoberto Sassu if (rc) { 246cdef685bSRoberto Sassu if (rc == -ENODATA) 247cdef685bSRoberto Sassu evm_status = INTEGRITY_NOXATTRS; 248cdef685bSRoberto Sassu else if (evm_immutable) 249cdef685bSRoberto Sassu evm_status = INTEGRITY_FAIL_IMMUTABLE; 250cdef685bSRoberto Sassu else 251cdef685bSRoberto Sassu evm_status = INTEGRITY_FAIL; 252cdef685bSRoberto Sassu } 2537102ebcdSMimi Zohar out: 2547102ebcdSMimi Zohar if (iint) 2557102ebcdSMimi Zohar iint->evm_status = evm_status; 25615647eb3SDmitry Kasatkin kfree(xattr_data); 2577102ebcdSMimi Zohar return evm_status; 25866dbc325SMimi Zohar } 25966dbc325SMimi Zohar 26066dbc325SMimi Zohar static int evm_protected_xattr(const char *req_xattr_name) 26166dbc325SMimi Zohar { 26266dbc325SMimi Zohar int namelen; 26366dbc325SMimi Zohar int found = 0; 26421af7663SMatthew Garrett struct xattr_list *xattr; 26566dbc325SMimi Zohar 26666dbc325SMimi Zohar namelen = strlen(req_xattr_name); 267770f6058SMadhuparna Bhowmik list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) { 26821af7663SMatthew Garrett if ((strlen(xattr->name) == namelen) 26921af7663SMatthew Garrett && (strncmp(req_xattr_name, xattr->name, namelen) == 0)) { 27066dbc325SMimi Zohar found = 1; 27166dbc325SMimi Zohar break; 27266dbc325SMimi Zohar } 273cb723180SMimi Zohar if (strncmp(req_xattr_name, 27421af7663SMatthew Garrett xattr->name + XATTR_SECURITY_PREFIX_LEN, 275cb723180SMimi Zohar strlen(req_xattr_name)) == 0) { 276cb723180SMimi Zohar found = 1; 277cb723180SMimi Zohar break; 278cb723180SMimi Zohar } 27966dbc325SMimi Zohar } 28021af7663SMatthew Garrett 28166dbc325SMimi Zohar return found; 28266dbc325SMimi Zohar } 28366dbc325SMimi Zohar 28466dbc325SMimi Zohar /** 28566dbc325SMimi Zohar * evm_verifyxattr - verify the integrity of the requested xattr 28666dbc325SMimi Zohar * @dentry: object of the verify xattr 28766dbc325SMimi Zohar * @xattr_name: requested xattr 28866dbc325SMimi Zohar * @xattr_value: requested xattr value 28966dbc325SMimi Zohar * @xattr_value_len: requested xattr value length 29066dbc325SMimi Zohar * 29166dbc325SMimi Zohar * Calculate the HMAC for the given dentry and verify it against the stored 29266dbc325SMimi Zohar * security.evm xattr. For performance, use the xattr value and length 29366dbc325SMimi Zohar * previously retrieved to calculate the HMAC. 29466dbc325SMimi Zohar * 29566dbc325SMimi Zohar * Returns the xattr integrity status. 29666dbc325SMimi Zohar * 29766dbc325SMimi Zohar * This function requires the caller to lock the inode's i_mutex before it 29866dbc325SMimi Zohar * is executed. 29966dbc325SMimi Zohar */ 30066dbc325SMimi Zohar enum integrity_status evm_verifyxattr(struct dentry *dentry, 30166dbc325SMimi Zohar const char *xattr_name, 3022960e6cbSDmitry Kasatkin void *xattr_value, size_t xattr_value_len, 3032960e6cbSDmitry Kasatkin struct integrity_iint_cache *iint) 30466dbc325SMimi Zohar { 305ae1ba167SMatthew Garrett if (!evm_key_loaded() || !evm_protected_xattr(xattr_name)) 30666dbc325SMimi Zohar return INTEGRITY_UNKNOWN; 30766dbc325SMimi Zohar 3082960e6cbSDmitry Kasatkin if (!iint) { 309c6f493d6SDavid Howells iint = integrity_iint_find(d_backing_inode(dentry)); 31066dbc325SMimi Zohar if (!iint) 31166dbc325SMimi Zohar return INTEGRITY_UNKNOWN; 3122960e6cbSDmitry Kasatkin } 3132960e6cbSDmitry Kasatkin return evm_verify_hmac(dentry, xattr_name, xattr_value, 31466dbc325SMimi Zohar xattr_value_len, iint); 31566dbc325SMimi Zohar } 31666dbc325SMimi Zohar EXPORT_SYMBOL_GPL(evm_verifyxattr); 31766dbc325SMimi Zohar 31866dbc325SMimi Zohar /* 3197102ebcdSMimi Zohar * evm_verify_current_integrity - verify the dentry's metadata integrity 3207102ebcdSMimi Zohar * @dentry: pointer to the affected dentry 3217102ebcdSMimi Zohar * 3227102ebcdSMimi Zohar * Verify and return the dentry's metadata integrity. The exceptions are 3237102ebcdSMimi Zohar * before EVM is initialized or in 'fix' mode. 3247102ebcdSMimi Zohar */ 3257102ebcdSMimi Zohar static enum integrity_status evm_verify_current_integrity(struct dentry *dentry) 3267102ebcdSMimi Zohar { 327c6f493d6SDavid Howells struct inode *inode = d_backing_inode(dentry); 3287102ebcdSMimi Zohar 329ae1ba167SMatthew Garrett if (!evm_key_loaded() || !S_ISREG(inode->i_mode) || evm_fixmode) 3307102ebcdSMimi Zohar return 0; 3317102ebcdSMimi Zohar return evm_verify_hmac(dentry, NULL, NULL, 0, NULL); 3327102ebcdSMimi Zohar } 3337102ebcdSMimi Zohar 334a924ce0bSMimi Zohar /* 335*1886ab01SRoberto Sassu * evm_xattr_acl_change - check if passed ACL changes the inode mode 336*1886ab01SRoberto Sassu * @mnt_userns: user namespace of the idmapped mount 337*1886ab01SRoberto Sassu * @dentry: pointer to the affected dentry 338*1886ab01SRoberto Sassu * @xattr_name: requested xattr 339*1886ab01SRoberto Sassu * @xattr_value: requested xattr value 340*1886ab01SRoberto Sassu * @xattr_value_len: requested xattr value length 341*1886ab01SRoberto Sassu * 342*1886ab01SRoberto Sassu * Check if passed ACL changes the inode mode, which is protected by EVM. 343*1886ab01SRoberto Sassu * 344*1886ab01SRoberto Sassu * Returns 1 if passed ACL causes inode mode change, 0 otherwise. 345*1886ab01SRoberto Sassu */ 346*1886ab01SRoberto Sassu static int evm_xattr_acl_change(struct user_namespace *mnt_userns, 347*1886ab01SRoberto Sassu struct dentry *dentry, const char *xattr_name, 348*1886ab01SRoberto Sassu const void *xattr_value, size_t xattr_value_len) 349*1886ab01SRoberto Sassu { 350*1886ab01SRoberto Sassu #ifdef CONFIG_FS_POSIX_ACL 351*1886ab01SRoberto Sassu umode_t mode; 352*1886ab01SRoberto Sassu struct posix_acl *acl = NULL, *acl_res; 353*1886ab01SRoberto Sassu struct inode *inode = d_backing_inode(dentry); 354*1886ab01SRoberto Sassu int rc; 355*1886ab01SRoberto Sassu 356*1886ab01SRoberto Sassu /* 357*1886ab01SRoberto Sassu * user_ns is not relevant here, ACL_USER/ACL_GROUP don't have impact 358*1886ab01SRoberto Sassu * on the inode mode (see posix_acl_equiv_mode()). 359*1886ab01SRoberto Sassu */ 360*1886ab01SRoberto Sassu acl = posix_acl_from_xattr(&init_user_ns, xattr_value, xattr_value_len); 361*1886ab01SRoberto Sassu if (IS_ERR_OR_NULL(acl)) 362*1886ab01SRoberto Sassu return 1; 363*1886ab01SRoberto Sassu 364*1886ab01SRoberto Sassu acl_res = acl; 365*1886ab01SRoberto Sassu /* 366*1886ab01SRoberto Sassu * Passing mnt_userns is necessary to correctly determine the GID in 367*1886ab01SRoberto Sassu * an idmapped mount, as the GID is used to clear the setgid bit in 368*1886ab01SRoberto Sassu * the inode mode. 369*1886ab01SRoberto Sassu */ 370*1886ab01SRoberto Sassu rc = posix_acl_update_mode(mnt_userns, inode, &mode, &acl_res); 371*1886ab01SRoberto Sassu 372*1886ab01SRoberto Sassu posix_acl_release(acl); 373*1886ab01SRoberto Sassu 374*1886ab01SRoberto Sassu if (rc) 375*1886ab01SRoberto Sassu return 1; 376*1886ab01SRoberto Sassu 377*1886ab01SRoberto Sassu if (inode->i_mode != mode) 378*1886ab01SRoberto Sassu return 1; 379*1886ab01SRoberto Sassu #endif 380*1886ab01SRoberto Sassu return 0; 381*1886ab01SRoberto Sassu } 382*1886ab01SRoberto Sassu 383*1886ab01SRoberto Sassu /* 384*1886ab01SRoberto Sassu * evm_xattr_change - check if passed xattr value differs from current value 385*1886ab01SRoberto Sassu * @mnt_userns: user namespace of the idmapped mount 386*1886ab01SRoberto Sassu * @dentry: pointer to the affected dentry 387*1886ab01SRoberto Sassu * @xattr_name: requested xattr 388*1886ab01SRoberto Sassu * @xattr_value: requested xattr value 389*1886ab01SRoberto Sassu * @xattr_value_len: requested xattr value length 390*1886ab01SRoberto Sassu * 391*1886ab01SRoberto Sassu * Check if passed xattr value differs from current value. 392*1886ab01SRoberto Sassu * 393*1886ab01SRoberto Sassu * Returns 1 if passed xattr value differs from current value, 0 otherwise. 394*1886ab01SRoberto Sassu */ 395*1886ab01SRoberto Sassu static int evm_xattr_change(struct user_namespace *mnt_userns, 396*1886ab01SRoberto Sassu struct dentry *dentry, const char *xattr_name, 397*1886ab01SRoberto Sassu const void *xattr_value, size_t xattr_value_len) 398*1886ab01SRoberto Sassu { 399*1886ab01SRoberto Sassu char *xattr_data = NULL; 400*1886ab01SRoberto Sassu int rc = 0; 401*1886ab01SRoberto Sassu 402*1886ab01SRoberto Sassu if (posix_xattr_acl(xattr_name)) 403*1886ab01SRoberto Sassu return evm_xattr_acl_change(mnt_userns, dentry, xattr_name, 404*1886ab01SRoberto Sassu xattr_value, xattr_value_len); 405*1886ab01SRoberto Sassu 406*1886ab01SRoberto Sassu rc = vfs_getxattr_alloc(&init_user_ns, dentry, xattr_name, &xattr_data, 407*1886ab01SRoberto Sassu 0, GFP_NOFS); 408*1886ab01SRoberto Sassu if (rc < 0) 409*1886ab01SRoberto Sassu return 1; 410*1886ab01SRoberto Sassu 411*1886ab01SRoberto Sassu if (rc == xattr_value_len) 412*1886ab01SRoberto Sassu rc = !!memcmp(xattr_value, xattr_data, rc); 413*1886ab01SRoberto Sassu else 414*1886ab01SRoberto Sassu rc = 1; 415*1886ab01SRoberto Sassu 416*1886ab01SRoberto Sassu kfree(xattr_data); 417*1886ab01SRoberto Sassu return rc; 418*1886ab01SRoberto Sassu } 419*1886ab01SRoberto Sassu 420*1886ab01SRoberto Sassu /* 421a924ce0bSMimi Zohar * evm_protect_xattr - protect the EVM extended attribute 422a924ce0bSMimi Zohar * 423bf6d0f5dSMimi Zohar * Prevent security.evm from being modified or removed without the 424bf6d0f5dSMimi Zohar * necessary permissions or when the existing value is invalid. 425bf6d0f5dSMimi Zohar * 426bf6d0f5dSMimi Zohar * The posix xattr acls are 'system' prefixed, which normally would not 427bf6d0f5dSMimi Zohar * affect security.evm. An interesting side affect of writing posix xattr 428bf6d0f5dSMimi Zohar * acls is their modifying of the i_mode, which is included in security.evm. 429bf6d0f5dSMimi Zohar * For posix xattr acls only, permit security.evm, even if it currently 43050b97748SMatthew Garrett * doesn't exist, to be updated unless the EVM signature is immutable. 431a924ce0bSMimi Zohar */ 4327e135dc7SRoberto Sassu static int evm_protect_xattr(struct user_namespace *mnt_userns, 4337e135dc7SRoberto Sassu struct dentry *dentry, const char *xattr_name, 434a924ce0bSMimi Zohar const void *xattr_value, size_t xattr_value_len) 435a924ce0bSMimi Zohar { 436a924ce0bSMimi Zohar enum integrity_status evm_status; 437a924ce0bSMimi Zohar 438a924ce0bSMimi Zohar if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { 439a924ce0bSMimi Zohar if (!capable(CAP_SYS_ADMIN)) 440a924ce0bSMimi Zohar return -EPERM; 441bf6d0f5dSMimi Zohar } else if (!evm_protected_xattr(xattr_name)) { 442bf6d0f5dSMimi Zohar if (!posix_xattr_acl(xattr_name)) 443a924ce0bSMimi Zohar return 0; 444bf6d0f5dSMimi Zohar evm_status = evm_verify_current_integrity(dentry); 445bf6d0f5dSMimi Zohar if ((evm_status == INTEGRITY_PASS) || 446566be59aSMimi Zohar (evm_status == INTEGRITY_NOXATTRS)) 447bf6d0f5dSMimi Zohar return 0; 4489b97b6cdSMimi Zohar goto out; 449bf6d0f5dSMimi Zohar } 450ae1ba167SMatthew Garrett 451a924ce0bSMimi Zohar evm_status = evm_verify_current_integrity(dentry); 4523dcbad52SDmitry Kasatkin if (evm_status == INTEGRITY_NOXATTRS) { 4533dcbad52SDmitry Kasatkin struct integrity_iint_cache *iint; 4543dcbad52SDmitry Kasatkin 4554a804b8aSRoberto Sassu /* Exception if the HMAC is not going to be calculated. */ 4564a804b8aSRoberto Sassu if (evm_hmac_disabled()) 4574a804b8aSRoberto Sassu return 0; 4584a804b8aSRoberto Sassu 459c6f493d6SDavid Howells iint = integrity_iint_find(d_backing_inode(dentry)); 4603dcbad52SDmitry Kasatkin if (iint && (iint->flags & IMA_NEW_FILE)) 4613dcbad52SDmitry Kasatkin return 0; 4625101a185SMimi Zohar 4635101a185SMimi Zohar /* exception for pseudo filesystems */ 464fc64005cSAl Viro if (dentry->d_sb->s_magic == TMPFS_MAGIC 465fc64005cSAl Viro || dentry->d_sb->s_magic == SYSFS_MAGIC) 4665101a185SMimi Zohar return 0; 4675101a185SMimi Zohar 4685101a185SMimi Zohar integrity_audit_msg(AUDIT_INTEGRITY_METADATA, 4695101a185SMimi Zohar dentry->d_inode, dentry->d_name.name, 4705101a185SMimi Zohar "update_metadata", 4715101a185SMimi Zohar integrity_status_msg[evm_status], 4725101a185SMimi Zohar -EPERM, 0); 4733dcbad52SDmitry Kasatkin } 4749b97b6cdSMimi Zohar out: 4754a804b8aSRoberto Sassu /* Exception if the HMAC is not going to be calculated. */ 4764a804b8aSRoberto Sassu if (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL || 4774a804b8aSRoberto Sassu evm_status == INTEGRITY_UNKNOWN)) 4784a804b8aSRoberto Sassu return 0; 479cdef685bSRoberto Sassu 480cdef685bSRoberto Sassu /* 481cdef685bSRoberto Sassu * Writing other xattrs is safe for portable signatures, as portable 482cdef685bSRoberto Sassu * signatures are immutable and can never be updated. 483cdef685bSRoberto Sassu */ 484cdef685bSRoberto Sassu if (evm_status == INTEGRITY_FAIL_IMMUTABLE) 485cdef685bSRoberto Sassu return 0; 486cdef685bSRoberto Sassu 487*1886ab01SRoberto Sassu if (evm_status == INTEGRITY_PASS_IMMUTABLE && 488*1886ab01SRoberto Sassu !evm_xattr_change(mnt_userns, dentry, xattr_name, xattr_value, 489*1886ab01SRoberto Sassu xattr_value_len)) 490*1886ab01SRoberto Sassu return 0; 491*1886ab01SRoberto Sassu 492*1886ab01SRoberto Sassu if (evm_status != INTEGRITY_PASS && 493*1886ab01SRoberto Sassu evm_status != INTEGRITY_PASS_IMMUTABLE) 494c6f493d6SDavid Howells integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry), 4959b97b6cdSMimi Zohar dentry->d_name.name, "appraise_metadata", 4969b97b6cdSMimi Zohar integrity_status_msg[evm_status], 4979b97b6cdSMimi Zohar -EPERM, 0); 498a924ce0bSMimi Zohar return evm_status == INTEGRITY_PASS ? 0 : -EPERM; 499a924ce0bSMimi Zohar } 500a924ce0bSMimi Zohar 50166dbc325SMimi Zohar /** 50266dbc325SMimi Zohar * evm_inode_setxattr - protect the EVM extended attribute 5037e135dc7SRoberto Sassu * @mnt_userns: user namespace of the idmapped mount 50466dbc325SMimi Zohar * @dentry: pointer to the affected dentry 50566dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 50666dbc325SMimi Zohar * @xattr_value: pointer to the new extended attribute value 50766dbc325SMimi Zohar * @xattr_value_len: pointer to the new extended attribute value length 50866dbc325SMimi Zohar * 5092fb1c9a4SMimi Zohar * Before allowing the 'security.evm' protected xattr to be updated, 5102fb1c9a4SMimi Zohar * verify the existing value is valid. As only the kernel should have 5112fb1c9a4SMimi Zohar * access to the EVM encrypted key needed to calculate the HMAC, prevent 5122fb1c9a4SMimi Zohar * userspace from writing HMAC value. Writing 'security.evm' requires 5132fb1c9a4SMimi Zohar * requires CAP_SYS_ADMIN privileges. 51466dbc325SMimi Zohar */ 5157e135dc7SRoberto Sassu int evm_inode_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry, 5167e135dc7SRoberto Sassu const char *xattr_name, const void *xattr_value, 5177e135dc7SRoberto Sassu size_t xattr_value_len) 51866dbc325SMimi Zohar { 5192fb1c9a4SMimi Zohar const struct evm_ima_xattr_data *xattr_data = xattr_value; 5202fb1c9a4SMimi Zohar 521ae1ba167SMatthew Garrett /* Policy permits modification of the protected xattrs even though 522ae1ba167SMatthew Garrett * there's no HMAC key loaded 523ae1ba167SMatthew Garrett */ 524ae1ba167SMatthew Garrett if (evm_initialized & EVM_ALLOW_METADATA_WRITES) 525ae1ba167SMatthew Garrett return 0; 526ae1ba167SMatthew Garrett 5273b1deef6SDmitry Kasatkin if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { 5283b1deef6SDmitry Kasatkin if (!xattr_value_len) 5293b1deef6SDmitry Kasatkin return -EINVAL; 53050b97748SMatthew Garrett if (xattr_data->type != EVM_IMA_XATTR_DIGSIG && 53150b97748SMatthew Garrett xattr_data->type != EVM_XATTR_PORTABLE_DIGSIG) 5322fb1c9a4SMimi Zohar return -EPERM; 5333b1deef6SDmitry Kasatkin } 5347e135dc7SRoberto Sassu return evm_protect_xattr(mnt_userns, dentry, xattr_name, xattr_value, 53566dbc325SMimi Zohar xattr_value_len); 53666dbc325SMimi Zohar } 53766dbc325SMimi Zohar 53866dbc325SMimi Zohar /** 53966dbc325SMimi Zohar * evm_inode_removexattr - protect the EVM extended attribute 5407e135dc7SRoberto Sassu * @mnt_userns: user namespace of the idmapped mount 54166dbc325SMimi Zohar * @dentry: pointer to the affected dentry 54266dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 54366dbc325SMimi Zohar * 5447102ebcdSMimi Zohar * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that 5457102ebcdSMimi Zohar * the current value is valid. 54666dbc325SMimi Zohar */ 5477e135dc7SRoberto Sassu int evm_inode_removexattr(struct user_namespace *mnt_userns, 5487e135dc7SRoberto Sassu struct dentry *dentry, const char *xattr_name) 54966dbc325SMimi Zohar { 550ae1ba167SMatthew Garrett /* Policy permits modification of the protected xattrs even though 551ae1ba167SMatthew Garrett * there's no HMAC key loaded 552ae1ba167SMatthew Garrett */ 553ae1ba167SMatthew Garrett if (evm_initialized & EVM_ALLOW_METADATA_WRITES) 554ae1ba167SMatthew Garrett return 0; 555ae1ba167SMatthew Garrett 5567e135dc7SRoberto Sassu return evm_protect_xattr(mnt_userns, dentry, xattr_name, NULL, 0); 55766dbc325SMimi Zohar } 55866dbc325SMimi Zohar 559523b74b1SDmitry Kasatkin static void evm_reset_status(struct inode *inode) 560523b74b1SDmitry Kasatkin { 561523b74b1SDmitry Kasatkin struct integrity_iint_cache *iint; 562523b74b1SDmitry Kasatkin 563523b74b1SDmitry Kasatkin iint = integrity_iint_find(inode); 564523b74b1SDmitry Kasatkin if (iint) 565523b74b1SDmitry Kasatkin iint->evm_status = INTEGRITY_UNKNOWN; 566523b74b1SDmitry Kasatkin } 567523b74b1SDmitry Kasatkin 56866dbc325SMimi Zohar /** 569e3ccfe1aSRoberto Sassu * evm_revalidate_status - report whether EVM status re-validation is necessary 570e3ccfe1aSRoberto Sassu * @xattr_name: pointer to the affected extended attribute name 571e3ccfe1aSRoberto Sassu * 572e3ccfe1aSRoberto Sassu * Report whether callers of evm_verifyxattr() should re-validate the 573e3ccfe1aSRoberto Sassu * EVM status. 574e3ccfe1aSRoberto Sassu * 575e3ccfe1aSRoberto Sassu * Return true if re-validation is necessary, false otherwise. 576e3ccfe1aSRoberto Sassu */ 577e3ccfe1aSRoberto Sassu bool evm_revalidate_status(const char *xattr_name) 578e3ccfe1aSRoberto Sassu { 579e3ccfe1aSRoberto Sassu if (!evm_key_loaded()) 580e3ccfe1aSRoberto Sassu return false; 581e3ccfe1aSRoberto Sassu 582e3ccfe1aSRoberto Sassu /* evm_inode_post_setattr() passes NULL */ 583e3ccfe1aSRoberto Sassu if (!xattr_name) 584e3ccfe1aSRoberto Sassu return true; 585e3ccfe1aSRoberto Sassu 586e3ccfe1aSRoberto Sassu if (!evm_protected_xattr(xattr_name) && !posix_xattr_acl(xattr_name) && 587e3ccfe1aSRoberto Sassu strcmp(xattr_name, XATTR_NAME_EVM)) 588e3ccfe1aSRoberto Sassu return false; 589e3ccfe1aSRoberto Sassu 590e3ccfe1aSRoberto Sassu return true; 591e3ccfe1aSRoberto Sassu } 592e3ccfe1aSRoberto Sassu 593e3ccfe1aSRoberto Sassu /** 59466dbc325SMimi Zohar * evm_inode_post_setxattr - update 'security.evm' to reflect the changes 59566dbc325SMimi Zohar * @dentry: pointer to the affected dentry 59666dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 59766dbc325SMimi Zohar * @xattr_value: pointer to the new extended attribute value 59866dbc325SMimi Zohar * @xattr_value_len: pointer to the new extended attribute value length 59966dbc325SMimi Zohar * 60066dbc325SMimi Zohar * Update the HMAC stored in 'security.evm' to reflect the change. 60166dbc325SMimi Zohar * 60266dbc325SMimi Zohar * No need to take the i_mutex lock here, as this function is called from 60366dbc325SMimi Zohar * __vfs_setxattr_noperm(). The caller of which has taken the inode's 60466dbc325SMimi Zohar * i_mutex lock. 60566dbc325SMimi Zohar */ 60666dbc325SMimi Zohar void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, 60766dbc325SMimi Zohar const void *xattr_value, size_t xattr_value_len) 60866dbc325SMimi Zohar { 609e3ccfe1aSRoberto Sassu if (!evm_revalidate_status(xattr_name)) 61066dbc325SMimi Zohar return; 61166dbc325SMimi Zohar 612523b74b1SDmitry Kasatkin evm_reset_status(dentry->d_inode); 613523b74b1SDmitry Kasatkin 614e3ccfe1aSRoberto Sassu if (!strcmp(xattr_name, XATTR_NAME_EVM)) 615e3ccfe1aSRoberto Sassu return; 616e3ccfe1aSRoberto Sassu 6174a804b8aSRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC)) 6184a804b8aSRoberto Sassu return; 6194a804b8aSRoberto Sassu 62066dbc325SMimi Zohar evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len); 62166dbc325SMimi Zohar } 62266dbc325SMimi Zohar 62366dbc325SMimi Zohar /** 62466dbc325SMimi Zohar * evm_inode_post_removexattr - update 'security.evm' after removing the xattr 62566dbc325SMimi Zohar * @dentry: pointer to the affected dentry 62666dbc325SMimi Zohar * @xattr_name: pointer to the affected extended attribute name 62766dbc325SMimi Zohar * 62866dbc325SMimi Zohar * Update the HMAC stored in 'security.evm' to reflect removal of the xattr. 6297c51bb00SDmitry Kasatkin * 6307c51bb00SDmitry Kasatkin * No need to take the i_mutex lock here, as this function is called from 6317c51bb00SDmitry Kasatkin * vfs_removexattr() which takes the i_mutex. 63266dbc325SMimi Zohar */ 63366dbc325SMimi Zohar void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) 63466dbc325SMimi Zohar { 635e3ccfe1aSRoberto Sassu if (!evm_revalidate_status(xattr_name)) 63666dbc325SMimi Zohar return; 63766dbc325SMimi Zohar 638523b74b1SDmitry Kasatkin evm_reset_status(dentry->d_inode); 639523b74b1SDmitry Kasatkin 640e3ccfe1aSRoberto Sassu if (!strcmp(xattr_name, XATTR_NAME_EVM)) 641e3ccfe1aSRoberto Sassu return; 642e3ccfe1aSRoberto Sassu 6434a804b8aSRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC)) 6444a804b8aSRoberto Sassu return; 6454a804b8aSRoberto Sassu 64666dbc325SMimi Zohar evm_update_evmxattr(dentry, xattr_name, NULL, 0); 64766dbc325SMimi Zohar } 64866dbc325SMimi Zohar 649*1886ab01SRoberto Sassu static int evm_attr_change(struct dentry *dentry, struct iattr *attr) 650*1886ab01SRoberto Sassu { 651*1886ab01SRoberto Sassu struct inode *inode = d_backing_inode(dentry); 652*1886ab01SRoberto Sassu unsigned int ia_valid = attr->ia_valid; 653*1886ab01SRoberto Sassu 654*1886ab01SRoberto Sassu if ((!(ia_valid & ATTR_UID) || uid_eq(attr->ia_uid, inode->i_uid)) && 655*1886ab01SRoberto Sassu (!(ia_valid & ATTR_GID) || gid_eq(attr->ia_gid, inode->i_gid)) && 656*1886ab01SRoberto Sassu (!(ia_valid & ATTR_MODE) || attr->ia_mode == inode->i_mode)) 657*1886ab01SRoberto Sassu return 0; 658*1886ab01SRoberto Sassu 659*1886ab01SRoberto Sassu return 1; 660*1886ab01SRoberto Sassu } 661*1886ab01SRoberto Sassu 66266dbc325SMimi Zohar /** 663817b54aaSMimi Zohar * evm_inode_setattr - prevent updating an invalid EVM extended attribute 664817b54aaSMimi Zohar * @dentry: pointer to the affected dentry 66550b97748SMatthew Garrett * 66650b97748SMatthew Garrett * Permit update of file attributes when files have a valid EVM signature, 66750b97748SMatthew Garrett * except in the case of them having an immutable portable signature. 668817b54aaSMimi Zohar */ 669817b54aaSMimi Zohar int evm_inode_setattr(struct dentry *dentry, struct iattr *attr) 670817b54aaSMimi Zohar { 671817b54aaSMimi Zohar unsigned int ia_valid = attr->ia_valid; 672817b54aaSMimi Zohar enum integrity_status evm_status; 673817b54aaSMimi Zohar 674ae1ba167SMatthew Garrett /* Policy permits modification of the protected attrs even though 675ae1ba167SMatthew Garrett * there's no HMAC key loaded 676ae1ba167SMatthew Garrett */ 677ae1ba167SMatthew Garrett if (evm_initialized & EVM_ALLOW_METADATA_WRITES) 678ae1ba167SMatthew Garrett return 0; 679ae1ba167SMatthew Garrett 680a924ce0bSMimi Zohar if (!(ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))) 681817b54aaSMimi Zohar return 0; 682817b54aaSMimi Zohar evm_status = evm_verify_current_integrity(dentry); 683cdef685bSRoberto Sassu /* 684cdef685bSRoberto Sassu * Writing attrs is safe for portable signatures, as portable signatures 685cdef685bSRoberto Sassu * are immutable and can never be updated. 686cdef685bSRoberto Sassu */ 687566be59aSMimi Zohar if ((evm_status == INTEGRITY_PASS) || 6884a804b8aSRoberto Sassu (evm_status == INTEGRITY_NOXATTRS) || 689cdef685bSRoberto Sassu (evm_status == INTEGRITY_FAIL_IMMUTABLE) || 6904a804b8aSRoberto Sassu (evm_hmac_disabled() && (evm_status == INTEGRITY_NOLABEL || 6914a804b8aSRoberto Sassu evm_status == INTEGRITY_UNKNOWN))) 692566be59aSMimi Zohar return 0; 693*1886ab01SRoberto Sassu 694*1886ab01SRoberto Sassu if (evm_status == INTEGRITY_PASS_IMMUTABLE && 695*1886ab01SRoberto Sassu !evm_attr_change(dentry, attr)) 696*1886ab01SRoberto Sassu return 0; 697*1886ab01SRoberto Sassu 698c6f493d6SDavid Howells integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry), 6999b97b6cdSMimi Zohar dentry->d_name.name, "appraise_metadata", 7009b97b6cdSMimi Zohar integrity_status_msg[evm_status], -EPERM, 0); 701566be59aSMimi Zohar return -EPERM; 702817b54aaSMimi Zohar } 703817b54aaSMimi Zohar 704817b54aaSMimi Zohar /** 70566dbc325SMimi Zohar * evm_inode_post_setattr - update 'security.evm' after modifying metadata 70666dbc325SMimi Zohar * @dentry: pointer to the affected dentry 70766dbc325SMimi Zohar * @ia_valid: for the UID and GID status 70866dbc325SMimi Zohar * 70966dbc325SMimi Zohar * For now, update the HMAC stored in 'security.evm' to reflect UID/GID 71066dbc325SMimi Zohar * changes. 71166dbc325SMimi Zohar * 71266dbc325SMimi Zohar * This function is called from notify_change(), which expects the caller 71366dbc325SMimi Zohar * to lock the inode's i_mutex. 71466dbc325SMimi Zohar */ 71566dbc325SMimi Zohar void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) 71666dbc325SMimi Zohar { 717e3ccfe1aSRoberto Sassu if (!evm_revalidate_status(NULL)) 71866dbc325SMimi Zohar return; 71966dbc325SMimi Zohar 720e3ccfe1aSRoberto Sassu evm_reset_status(dentry->d_inode); 721e3ccfe1aSRoberto Sassu 7224a804b8aSRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC)) 7234a804b8aSRoberto Sassu return; 7244a804b8aSRoberto Sassu 72566dbc325SMimi Zohar if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) 72666dbc325SMimi Zohar evm_update_evmxattr(dentry, NULL, NULL, 0); 72766dbc325SMimi Zohar } 72866dbc325SMimi Zohar 729cb723180SMimi Zohar /* 7309eea2904SRoberto Sassu * evm_inode_init_security - initializes security.evm HMAC value 731cb723180SMimi Zohar */ 732cb723180SMimi Zohar int evm_inode_init_security(struct inode *inode, 733cb723180SMimi Zohar const struct xattr *lsm_xattr, 734cb723180SMimi Zohar struct xattr *evm_xattr) 735cb723180SMimi Zohar { 736650b29dbSThiago Jung Bauermann struct evm_xattr *xattr_data; 737cb723180SMimi Zohar int rc; 738cb723180SMimi Zohar 7399eea2904SRoberto Sassu if (!(evm_initialized & EVM_INIT_HMAC) || 7409eea2904SRoberto Sassu !evm_protected_xattr(lsm_xattr->name)) 7415a4730baSMimi Zohar return 0; 742cb723180SMimi Zohar 743cb723180SMimi Zohar xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS); 744cb723180SMimi Zohar if (!xattr_data) 745cb723180SMimi Zohar return -ENOMEM; 746cb723180SMimi Zohar 747650b29dbSThiago Jung Bauermann xattr_data->data.type = EVM_XATTR_HMAC; 748cb723180SMimi Zohar rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest); 749cb723180SMimi Zohar if (rc < 0) 750cb723180SMimi Zohar goto out; 751cb723180SMimi Zohar 752cb723180SMimi Zohar evm_xattr->value = xattr_data; 753cb723180SMimi Zohar evm_xattr->value_len = sizeof(*xattr_data); 7549548906bSTetsuo Handa evm_xattr->name = XATTR_EVM_SUFFIX; 755cb723180SMimi Zohar return 0; 756cb723180SMimi Zohar out: 757cb723180SMimi Zohar kfree(xattr_data); 758cb723180SMimi Zohar return rc; 759cb723180SMimi Zohar } 760cb723180SMimi Zohar EXPORT_SYMBOL_GPL(evm_inode_init_security); 761cb723180SMimi Zohar 7622ce523ebSDmitry Kasatkin #ifdef CONFIG_EVM_LOAD_X509 7632ce523ebSDmitry Kasatkin void __init evm_load_x509(void) 7642ce523ebSDmitry Kasatkin { 76526ddabfeSDmitry Kasatkin int rc; 76626ddabfeSDmitry Kasatkin 76726ddabfeSDmitry Kasatkin rc = integrity_load_x509(INTEGRITY_KEYRING_EVM, CONFIG_EVM_X509_PATH); 76826ddabfeSDmitry Kasatkin if (!rc) 76926ddabfeSDmitry Kasatkin evm_initialized |= EVM_INIT_X509; 7702ce523ebSDmitry Kasatkin } 7712ce523ebSDmitry Kasatkin #endif 7722ce523ebSDmitry Kasatkin 77366dbc325SMimi Zohar static int __init init_evm(void) 77466dbc325SMimi Zohar { 77566dbc325SMimi Zohar int error; 77621af7663SMatthew Garrett struct list_head *pos, *q; 77766dbc325SMimi Zohar 778d3b33679SDmitry Kasatkin evm_init_config(); 779d3b33679SDmitry Kasatkin 780f4dc3778SDmitry Kasatkin error = integrity_init_keyring(INTEGRITY_KEYRING_EVM); 781f4dc3778SDmitry Kasatkin if (error) 78221af7663SMatthew Garrett goto error; 783f4dc3778SDmitry Kasatkin 78466dbc325SMimi Zohar error = evm_init_secfs(); 78566dbc325SMimi Zohar if (error < 0) { 78620ee451fSJoe Perches pr_info("Error registering secfs\n"); 78721af7663SMatthew Garrett goto error; 78821af7663SMatthew Garrett } 78921af7663SMatthew Garrett 79021af7663SMatthew Garrett error: 79121af7663SMatthew Garrett if (error != 0) { 79221af7663SMatthew Garrett if (!list_empty(&evm_config_xattrnames)) { 793c8b37524SYueHaibing list_for_each_safe(pos, q, &evm_config_xattrnames) 79421af7663SMatthew Garrett list_del(pos); 79521af7663SMatthew Garrett } 79621af7663SMatthew Garrett } 79721af7663SMatthew Garrett 798f4dc3778SDmitry Kasatkin return error; 79966dbc325SMimi Zohar } 80015647eb3SDmitry Kasatkin 80166dbc325SMimi Zohar late_initcall(init_evm); 802